diff --git a/paseo/.env.example b/paseo/.env.example index cdf6c71..7174730 100644 --- a/paseo/.env.example +++ b/paseo/.env.example @@ -9,3 +9,10 @@ PASEO_PASSWORD= # Comma-separated DNS names allowed to reach the daemon. The domain mapped in # Coolify/Dokploy must be listed here. IPs and localhost are always allowed. PASEO_HOSTNAMES= + +# Proxy addresses whose X-Forwarded-Proto the daemon trusts. Without this the +# daemon only trusts loopback, so behind Coolify/Dokploy it sees plain HTTP, +# tells the web UI the connection is not TLS, and the UI falls back to trying +# ws://...:6767 from an HTTPS page -- which the browser blocks. +# `uniquelocal` covers the private ranges Docker bridge networks use. +PASEO_TRUSTED_PROXIES=uniquelocal diff --git a/paseo/README.md b/paseo/README.md index 9df25b6..bb84331 100644 --- a/paseo/README.md +++ b/paseo/README.md @@ -28,6 +28,7 @@ stanza; there is nothing to push. | --- | --- | | `PASEO_PASSWORD` | Auth for the daemon API and WebSocket | | `PASEO_HOSTNAMES` | Comma-separated DNS names allowed to reach the daemon, e.g. `paseo.example.com,.lan`. IPs and localhost always pass. | +| `PASEO_TRUSTED_PROXIES` | Proxy addresses whose `X-Forwarded-*` headers the daemon believes. Required behind a TLS-terminating proxy — see below. | Generate a password with `openssl rand -base64 24`. The proxied domain must appear in `PASEO_HOSTNAMES` or requests are rejected. @@ -35,7 +36,19 @@ appear in `PASEO_HOSTNAMES` or requests are rejected. ## Networking Listens on `6767`. No ports are published — point the domain at that port in -Coolify or Dokploy. See the [root README](../README.md) for why. +Coolify or Dokploy. See the [root README](../README.md) for why. `localhost:6767` +on the host will refuse connections; reach the daemon through its domain. + +`PASEO_TRUSTED_PROXIES` must be set, or the web UI loads but never connects. +The daemon trusts `X-Forwarded-Proto` from loopback only by default. Coolify's +Traefik reaches it from the Docker bridge network instead, so the daemon +concludes the request was plain HTTP and hands the UI `useTls: false`. The UI +then builds a `ws://` URL from an `https://` page, the browser blocks it as +mixed content, and the UI falls back to its built-in `localhost:6767` default — +which in a browser means the viewer's own machine, not the server. + +`uniquelocal` covers the private ranges Docker uses. A specific CIDR works too, +but Coolify assigns a fresh subnet per project, so it will not survive a move. ## Storage diff --git a/paseo/compose.yml b/paseo/compose.yml index b5ee9cb..e2e1cae 100644 --- a/paseo/compose.yml +++ b/paseo/compose.yml @@ -4,6 +4,7 @@ services: environment: - PASEO_PASSWORD=${PASEO_PASSWORD} - PASEO_HOSTNAMES=${PASEO_HOSTNAMES} + - PASEO_TRUSTED_PROXIES=${PASEO_TRUSTED_PROXIES} volumes: - 'paseo-home:/home/paseo' - 'paseo-workspace:/workspace'