Skip to content

Getting started

What follows installs the service, points it at a database and a bucket, and publishes a file. It takes about five minutes against services you already have, or against the local ones in Running it.

Install

Nothing is published to PyPI yet, so it installs from a checkout:

git clone https://github.com/abilian/cdn
cd cdn
uv sync

Python 3.12 or later. The service needs PostgreSQL and something that speaks S3; the client half of the CLI needs neither.

Configure

Everything is read from the environment once, at startup, and validated there. A missing value stops the boot rather than failing on the first request that needs it, so a health check never reports green in front of a service that cannot serve.

export DATABASE_URL=postgresql://localhost/cdn
export CDN_BASE_URL=https://cdn.example.com    # the public address, as people will see it
export CDN_SECRET_KEY=$(openssl rand -hex 32)  # signs session cookies and derives S3 secrets
export CDN_CACHE_DIR=/var/lib/cdn/cache        # a persistent, disposable volume

export S3_ENDPOINT_URL=https://s3.example.com
export S3_BUCKET=cdn
export S3_ACCESS_KEY_ID=export S3_SECRET_ACCESS_KEY=

CDN_SECRET_KEY is load-bearing: it signs session cookies and derives the secret every S3 client authenticates with. Changing it signs everyone out and invalidates every S3 credential. The rest of the settings, and their defaults, are in Configuration.

Create the schema

cdn migrate

Run this before the new code serves traffic, on every deploy. Schema changes go through migrations and never through create_all, so a process that started against an empty database has the same schema as one that has been upgraded for a year.

Create an organisation, a zone and a token

An organisation is a tenant; a zone is a unit of URL and configuration; a token is a machine credential. Organisations are made from the command line, because they are the operator's business rather than a tenant's.

cdn create-org acme "Acme Corp"
cdn create-zone assets --org acme
cdn create-token "laptop" --org acme --scopes read,write,delete

The token is printed once and stored only as a hash. There is no way to read it back.

Publish a file

Point the CLI at the service and hand it the token:

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

It prints the URL, which is also what cdn url prints:

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

Fetch it, and ask twice:

curl -I https://cdn.example.com/assets/releases/app-1.2.0.tar.gz
# HTTP/1.1 200 OK
# X-Cache: MISS
curl -I https://cdn.example.com/assets/releases/app-1.2.0.tar.gz
# X-Cache: HIT

The first request fetched the object from S3 and left a copy on the cache volume. The second was answered from disk.

Create a person

The browser UI is at /_/ui. Accounts are created from the command line too, and the first one has to be, because there is nobody to sign in as yet:

cdn create-user you@example.com "Your Name" --org acme --role owner

The password is generated and printed once. After that, owners invite everyone else from the Members page.

Where to go next

  • Publishing files — the CLI, the HTTP API, the browser, and rclone.
  • S3 clients — point rclone or aws-cli at a zone.
  • Private links — files that are served only through a URL you signed.
  • Running it — deployment, the workers, and what to back up.