Push and pull
Push/static files under /data/static/<zone>/ with sendfile. Pull zones append the request path to an origin (scheme+host). Zone names are lowercase alphanumeric, 1–20 chars — same constraint as KeyCDN.
Built from plan.txt: OpenResty edges, Go control plane, KeyCDN-compatible management API. First launch is CSS, JS, fonts, images, and other static files on a fast URL.
Push/static files under /data/static/<zone>/ with sendfile. Pull zones append the request path to an origin (scheme+host). Zone names are lowercase alphanumeric, 1–20 chars — same constraint as KeyCDN.
Image cache 50g and other 20g so image waves cannot evict CSS and fonts. Default key $zone_id|$uri. Lock, revalidate, background update, and stale-on-error. Responses over 100 MB stream with X-Cache: BYPASS.
Control fans out POST /internal/purge to every active edge. Snapshot carries a monotonic purge_generation as the correctness backstop. Browser caches are not purged.
Shared wildcard on the zone domain, Let’s Encrypt for one alias per zone (lego on control), or a custom PEM. Optional HTTP→HTTPS 301. HTTP/2 on; HTTP/3 later.
Referrer allow/deny, empty-referrer toggle, secure token (optional bind-to-IP), CORS *, force download, block bad bots (451). Applied in Lua from the snapshot.
Server: cdn-server. X-Cache HIT|MISS|EXPIRED|STALE|BYPASS|UPDATING. X-Edge-Location. Accept-Ranges: bytes. Vary only when compressed.
No anycast. Each edge has a public IP. Dashboard prints A/AAAA records. Add a server from the operator UI; Ansible installs Docker and copies shared data — cache stays empty until filled on demand.
HTTP Basic (API key as username, empty password). Zones, aliases, referrers, purge, reports, and credits with the KeyCDN envelope, parameters, and error codes. Rate limit 60/min.
Zones, media library, FTP users, reports, tickets, packages and credits. Operator console manages nodes, users, packages, redeem codes, and transactions.
Optional imgproxy (Go + libvips) when a zone has image processing enabled and the request carries transform query parameters. nginx caches the transformed bytes so libvips runs once per variant.
Streaming, HLS, CMS plugins, anycast, and HTTP/3 are catalogued for later. Stack does not include Redis, Elasticsearch, Kafka, MinIO, Varnish, Node, PHP, or Python app servers on the hot path.