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-cliands3cmddrive 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¶
- The first path segment names the zone, or the
Hostheader 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 syncagainst a zone, with nothing custom. - Running it: deployment, the background workers, backup and reconciliation.
- Concepts: the nouns, and what each one owns.