Browse documentation

Documentation overview

Tutorial

Reference

Project

Put Caddy in front

HTTPS, a reverse proxy, and a configuration file you can read before your coffee gets cold. Caddy is annoyingly good at this.

Keep the Python listener private

These deployment chapters use the notebook at the site root, including its static files. Use a host with Caddy installed and your app dependencies in a virtualenv. First run the backend on IPv4 loopback:

Terminal
# Run from the repository root with the notebook dependencies installed.
weft example_app.asgi:app --host 127.0.0.1 --port 8000 \
  --lifespan on --forwarded-allow-ips 127.0.0.1

Accept forwarded headers only from the loopback proxy. That gives the notebook the external HTTPS scheme for cookie flags and same-origin checks, and the actual client address for its rate limiter. Use your supervisor to keep this process running; the operations chapter includes systemd.

Give your domain a Caddyfile

Replace notes.example.com with your domain. Point its DNS records at this host and make ports 80 and 443 reachable. Keep Caddy’s certificate storage writable and persistent. With those prerequisites, automatic HTTPS handles certificate issuance, renewal, and HTTP redirects.

CaddyfileDownload
notes.example.com {
    request_body {
        max_size 1MB
    }
    encode zstd gzip
    reverse_proxy 127.0.0.1:8000
}

request_body caps uploads at about one megabyte. reverse_proxy preserves the request path and forwards the Host and proxy headers. The notebook still sees /api/notes, which is fortunate because that’s where we put it.

Validate, reload, and check

Save the site configuration in the Caddyfile used by your installation, commonly /etc/caddy/Caddyfile. Validate it before applying it:

Terminal
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy
curl -i https://notes.example.com/api/health

Use the Caddy CLI reload workflow if your installation isn’t managed by systemd. Expect JSON 200 from health. Visit the site, log in, and check that the refresh cookie has Secure under HTTPS. A green health check cannot inspect your cookies on your behalf.

Try the proxy locally

For an HTTP-only local smoke check, replace the domain line with http://localhost:8080, save as Caddyfile.local, and run:

Terminal
caddy run --config Caddyfile.local --adapter caddyfile

Open http://localhost:8080/. This explicitly disables automatic HTTPS for that local site. Use the domain configuration for public HTTPS.

Keep the responsibilities obvious

Caddy terminates TLS and limits request bodies. Weft runs the ASGI app. The notebook handles its database lifecycle and authorization. You still need a shared rate-limit strategy if you want one limit across workers; this Caddyfile does not add one.

Choose whether compression belongs in Caddy or an application middleware layer. For streams, check proxy timeouts and disconnect behavior with a real client. For a separate frontend build, use explicit static and API routing while preserving the API prefix.