- If your host is publicly reachable on ports 80 and 443: Caddy’s default HTTP challenge works with no extra configuration. Delete the
tlsblock from the Caddyfile shown below. This is standard Caddy behaviour and simpler to set up, though it requires your server to be publicly reachable on those ports. - If it’s not reachable (e.g. sitting behind Cloudflare’s proxy): use the DNS-01 challenge with Caddy’s Cloudflare module. The steps below cover DNS-01, since it’s the tested path. It works whether or not the host is reachable from the internet.
Install Caddy
1
Add the Caddy repository and install
Run these commands on your Debian or Ubuntu host:
2
Add the Cloudflare DNS module
caddy binary with a build from caddyserver.com that includes the Cloudflare DNS module. Skip this step if you’re using the default HTTP challenge instead.Create a Cloudflare API token
In the Cloudflare dashboard, create an API token with two permissions on the zone your domain is in:- Zone → DNS → Edit
- Zone → Zone → Read
1
Store the token in a root-only file
2
Hook the token into the Caddy service
Configure Caddy
Copy the Caddyfile from the plamotrack repo to/etc/caddy/Caddyfile and replace the hostname with your own:
http:// to https://, passes the Host header through unchanged, sets X-Forwarded-For and X-Forwarded-Proto, and streams text/event-stream responses without buffering.
There is no log directive — and that’s intentional. A proxy access log records full request URIs. In OIDC mode those URIs include one-time authorization codes from your identity provider’s callbacks. Don’t add one unless you know what you’re doing.
Update .env and start
Add these three lines to your.env:
PUBLIC_BASE_URLtells plamotrack what address browsers see. Without it, every save from a browser returns403 ingress.origin_not_allowedbecause thehttps://origin in the request doesn’t match the instance’s plain-HTTP socket.TRUSTED_PROXIES=127.0.0.1tells plamotrack to trustX-Forwarded-Forheaders from Caddy, so rate limits and the audit log see your actual visitors rather than the proxy address.
Verify
From another machine, open:{"status":"ok"}. Then open the app in your browser and claim the instance — run docker compose logs api | grep -A6 "no owner yet" to find the one-time setup token.
Behind TLS, your session cookie is Secure and __Host--prefixed. OIDC mode is also available — set AUTH_MODE=oidc in .env to sign in with Google or your own identity provider, and let Claude web and ChatGPT web connect directly without pasting a token.