# Reverse proxy in front of Puter — mirrors what the prod ALB does: # accepts every Host header, forwards to the Puter container, and lets # the Puter app handle subdomain-based routing internally (api.*, # site.*, app.*, dev.*, plus the per-user subdomains under those). # # To enable TLS: # 1. Drop a wildcard fullchain.pem + privkey.pem into ./puter/tls/ # (see "Step 3 — TLS" in doc/self-hosting.md). # 2. Uncomment the `:443` block at the bottom of this file, and swap the # `:80` block for the redirect shown alongside it. # 3. Uncomment the `443:443` port mapping under the `caddy` service in # docker-compose.yml, and HTTPS_PORT in .env. # 4. Set `"protocol": "https"` and `"pub_port": 443` in config.json. { # Certs are supplied by the operator, not issued by Caddy. Puter serves # per-user sites and apps on dynamic subdomains (.site., # .app.) — only a DNS-01 wildcard cert covers those, and # DNS-01 needs a provider plugin that isn't in the stock caddy image. # `off` stops Caddy attempting ACME on boot (it would fail and leave the # site unreachable) and stops it inventing its own http→https redirects. auto_https off } # Shared handling, imported by the HTTP and HTTPS site blocks below so the # two can't drift apart. (puter_routes) { # Rough size cap that mirrors prod ALB defaults; tune for your uploads. # Puter chunks large uploads, so 1 GiB per request is plenty. request_body { max_size 1024MiB } # RustFS — see the `s3` service in docker-compose.yml. Browsers PUT/GET # here for presigned-URL uploads / downloads. Matched on the `s3.` # subdomain of whatever the install domain is, so signature verification # works (Caddy preserves the original Host end-to-end) and HTTPS stays # clean — no mixed content from a port-9000 host publish. @s3 header_regexp Host ^s3\. handle @s3 { reverse_proxy s3:9000 } # Everything else, on every Host, goes to Puter — which routes on that # Host internally. Caddy forwards it unchanged and adds X-Forwarded-For # / -Proto / -Host, which is what `trust_proxy` in config.json counts. handle { reverse_proxy puter:4100 { # Stream responses through unbuffered — Puter uses SSE and # socket.io. WebSocket upgrades need no config of their own; # Caddy proxies them by default. flush_interval -1 } } } # ── HTTP (port 80) ───────────────────────────────────────────────────── # A site address with no hostname is the catch-all: it answers for every # Host, which is what Puter's subdomain routing requires. :80 { import puter_routes } # ── HTTPS (port 443) — uncomment after dropping certs in ./puter/tls/ ── # Replace the `:80` block above with a redirect to force HTTPS everywhere: # # :80 { # redir https://{host}{uri} permanent # } # # :443 { # tls /etc/caddy/tls/fullchain.pem /etc/caddy/tls/privkey.pem # import puter_routes # }