Skip to content

Configuration

Every setting is an environment variable, read once at startup into a frozen object and validated there. An invalid or missing value stops the boot; nothing downstream re-checks it.

Required

variable what it is
DATABASE_URL the PostgreSQL connection URL
CDN_BASE_URL the public address objects are served from, as people will see it
CDN_SECRET_KEY signs session cookies and derives every S3 secret
CDN_CACHE_DIR the local cache directory, on a persistent volume
S3_ENDPOINT_URL the object store's address
S3_BUCKET the bucket holding objects
S3_ACCESS_KEY_ID the object store access key
S3_SECRET_ACCESS_KEY the object store secret key

DATABASE_URL may be written the way a platform addon injects it — postgresql://…. The async driver is filled in at the edge, because SQLAlchemy would otherwise read that as psycopg2 and fail at connect time with an error that says nothing about the cause.

Optional

variable default what it does
S3_REGION us-east-1 the region named in S3 signatures
CDN_S3_HOST unset a hostname whose root is the S3 API, for clients that cannot be given an endpoint with a path in it
CDN_MAX_UPLOAD_BYTES 2G refused before the body is read
CDN_WRITE_LIMIT_PER_MINUTE 1200 writes one token may make per minute; 0 turns it off
CDN_CACHE_HIGH_WATER 20G the sweeper starts evicting past this
CDN_CACHE_LOW_WATER 16G …and stops here
CDN_DEBUG unset 1, true or yes for tracebacks in responses

Sizes take the spelling a proxy uses for its own limits — 2G, 500M, 4K — so an operator writing 2G in two configuration files means the same thing in both.

The settings that interact with something else

CDN_SECRET_KEY signs session cookies and derives the S3 secret for every token. Rotating it signs everyone out and invalidates every S3 credential at once. Objects are unaffected.

CDN_MAX_UPLOAD_BYTES must not exceed what the proxy in front allows, or the proxy answers an opaque 413 before this service can say anything useful. See Running it.

CDN_CACHE_HIGH_WATER and CDN_CACHE_LOW_WATER are two marks rather than one so a full cache does not evict on every write. The low mark must be below the high one.

CDN_WRITE_LIMIT_PER_MINUTE is one number rather than a rate and a burst: a full minute's worth may arrive at once, which is what a deploy pushing a thousand files looks like, and the rest refills steadily. Set it to 0 behind a gateway that already does this.

Per-zone settings

These live in the database, on the zone's settings page, not in the environment:

visibility public, or private and served only through a signed URL
kind storage or pull; a zone never changes kind
origin, and min/max/negative TTL pull zones: what to mirror and how long to keep it
Cache-Control what clients are told, unless an object overrides it
hostname of its own serves the zone at the root of another domain
referrers hostnames allowed to embed these objects
CORS origins origins allowed to fetch them from a script
storage quota bytes this zone may hold

Organisation-wide storage quotas are the operator's, and are set with cdn set-quota.