Tailscale Serve and reverse proxies
Keep EdgeWatch bound to loopback when exposing it through Tailscale Serve or a
reverse proxy. Serve the public hostname over HTTPS and add the hostname that
users open to web.allowed_hosts:
web: listen: 127.0.0.1:8080 allowed_hosts: - edgewatch.example.ts.net forwarded_header: x-forwarded-for trusted_proxies: - 127.0.0.1/32 - ::1/128Replace edgewatch.example.ts.net with your tailnet or proxy hostname. Use the
bare hostname only; do not include https://, a path, or a port. EdgeWatch
checks the forwarded Host value before authentication, so an unlisted proxy
hostname is rejected with 421 Misdirected Request even when the loopback
listener is healthy. Approved non-loopback hostnames receive Secure session
cookies; direct loopback HTTP remains available for local administration and
SSH tunnels. The example trusts a local proxy and its sanitized
X-Forwarded-For client address; replace these networks with the addresses that
actually connect to EdgeWatch when the proxy runs elsewhere. If a
TLS-terminating proxy rewrites the upstream Host to a loopback address, list
the proxy address or network in web.trusted_proxies so EdgeWatch can trust its
X-Forwarded-Proto: https (or RFC 7239 Forwarded: ...;proto=https) signal
and keep the session cookie Secure. Do not trust untrusted peers: the configured
proxy must sanitize the forwarding headers.
After changing the bind-mounted configuration, recreate the container:
docker compose up -d --force-recreate edgewatchYou can verify both paths from the Docker host (replace the example hostname with the one configured above):
curl -i http://127.0.0.1:8080/api/v1/setup/statuscurl -i -H 'Host: edgewatch.example.ts.net:8443' \ http://127.0.0.1:8080/api/v1/setup/statusBoth requests should return a successful response. If the direct request works
but the request with the proxy Host returns 421, correct
web.allowed_hosts. The listener remains loopback-only; this setting approves
the public name, not a new network bind address.