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.