VOD Docs

Caddy

The reverse proxy: TLS, routing, caching and why it runs on the host network.

Caddy is the backend's only public entry point. It was chosen for automatic HTTPS (it obtains and renews Let's Encrypt certificates by itself), a short configuration file, and solid streaming reverse-proxy support.

The routing rules are explained in Request routing. This page covers the configuration files and operational details.

Flow diagram · placeholder
Caddy request pipeline: TLS termination → route match (first match wins) → headers → upstream

Annotate each route with its upstream and cache policy.

Config files

FileUsed forIn git
infra/caddy/Caddyfile.exampleTemplate for local developmentYes
infra/caddy/Caddyfile.prod.exampleTemplate for productionYes
infra/caddy/Caddyfile.localYour local config, copied from the exampleNo
infra/caddy/Caddyfile.prodThe production config on the serverNo

The real files are git-ignored so environment-specific details stay out of the repository. The container mounts the file read-only.

Production config, in outline

Caddyfile.prod (outline)
api.vod.spokhrel.dev {
    handle /files/*                         → tusd   (flush_interval -1)
    handle /internal/tus/hooks/uploads/*    → api
    handle /internal/*                      → respond 404
    handle_path /storage/*                  → minio  (prefix stripped)
    reverse_proxy                           → api
}
DirectiveMeaning
handleMatch a path and keep it unchanged
handle_pathMatch a path and strip the matched prefix before proxying
reverse_proxyForward to an upstream
flush_interval -1Stream the response immediately instead of buffering (needed for upload progress)
respond 404Answer directly without contacting an upstream

/files uses handle, not handle_path: tusd serves under /files/ and does not honour a forwarded prefix, so stripping it would break the protocol.

Caching

The production config sets Cache-Control per media type: one year and immutable for .ts segments, 60 seconds for .m3u8 playlists. See Request routing.

Why host networking in production

Caddy runs with network_mode: host and reaches the API, MinIO and tusd on loopback ports. Those services publish their ports only on 127.0.0.1, so they are reachable from Caddy on the same machine but not from the internet. Locally, Caddy instead joins the Compose bridge network and uses service names.

Certificates

Certificates and ACME account data are stored in the caddy_data volume, so they survive container recreation and Caddy does not re-request certificates on every deploy.

On this page