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 go out over HTTP with the caching headers, byte ranges and conditional requests a browser expects. One server: 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
It needs Python 3.12 or later, PostgreSQL, and any S3. The licence is Apache-2.0. Nothing is published to PyPI yet, so it installs from a checkout.
What you get¶
- A stable public URL per file, plus 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. The layer in front of it is the part you end up building: 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.
This service is that layer. 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. The bytes come back exactly as they went in.
- 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.