Skip to content

Abilian CDN

Somewhere to put the files, with a URL you can hand out.

"We need somewhere to put the release tarballs / the product images / the client's video, with a stable URL and no surprises on the bill" comes up constantly. The usual answers are a bucket with an ugly URL and no statistics, or a CDN account with a contract attached.

This is the third answer: one process you run yourself. Files live in S3 — or MinIO, or Garage, or Scaleway — get cached on the server's local disk, and are served over HTTP with the caching headers, byte ranges and conditional requests a browser expects. One server, not a distributed network: a request lands on one machine and is answered there.

cdn put ./dist/app-1.2.0.tar.gz assets/releases/
# https://cdn.example.com/assets/releases/app-1.2.0.tar.gz

Python 3.12 or later, PostgreSQL, and any S3. Apache-2.0, and not yet released: it installs from a checkout.

What you get

  • A stable public URL per file, and a hostname of your own if you point a CNAME at it.
  • Four ways in: a CLI, an HTTP API, drag-and-drop in a browser, and an S3-compatible endpoint that rclone, aws-cli and s3cmd drive unmodified.
  • Private files, served only through a URL this service signed, with an expiry.
  • Pull zones that mirror an origin you already have, and keep serving it when it goes down.
  • Download statistics per file, per day, with a cache hit ratio and a CSV export.
  • An audit log of every write, so "who deleted this" has an answer.

The part that is hard to buy

A bucket gives you storage. What it does not give you is the thing in front of it: a URL that does not expire, byte ranges so a video seeks, ETag and If-None-Match so a browser re-download costs nothing, a hit ratio so you know what to cache, and an answer when someone asks why a file changed.

That layer is what this is. The storage underneath stays yours — plain objects in your own bucket, readable without this service running.

What it is not

  • Not a distributed network. One machine, one region. If you need points of presence on three continents, you need a CDN, and this is not one.
  • Not a bucket replacement. S3 holds the bytes and the database holds the index of them; this serves and accounts for what is already yours.
  • Not an image pipeline. No resizing, no format conversion, no transformation on the fly.
  • Not multi-tenant SaaS. One deployment serves organisations you create yourself, from the command line.

The two kinds of zone

A zone is the unit of URL, configuration and statistics, and its name is the first path segment.

storage zone pull zone
where the bytes start you upload them an origin you already run
first request for a path served from S3, then cached fetched from the origin, then cached
when the origin is down there is no origin the stale copy is served, with X-Cache: STALE
deleting removes the object there is nothing to delete; the cache forgets

A storage zone is for files you own. A pull zone puts a cache in front of something that already answers HTTP, without moving it.

One request, end to end

GET /assets/releases/app-1.2.0.tar.gz
  • The first path segment names the zone, or the Host header does when the zone has a domain of its own.
  • A private zone checks the signature and the expiry, and refuses without them.
  • The local cache answers if it has the bytes (X-Cache: HIT); otherwise they come from S3 or the origin and stay on disk for next time (MISS).
  • Range and conditional headers are honoured, so a partial download resumes and an unchanged file costs a 304.
  • The response is counted in memory. The database is not touched on the read path.

Where to go next

  • Getting started: install it, configure it, and publish a file.
  • Publishing files: the four ways in, and when each one fits.
  • S3 clients: rclone sync against a zone, with nothing custom.
  • Running it: deployment, the background workers, backup and reconciliation.
  • Concepts: the nouns, and what each one owns.