Skip to content

Behind a proxy

Point your proxy at the published WEB_PORT and let it terminate HTTPS. Two variables must then follow in .env, and the stack restarted: PUBLIC_URL is the public address you serve the app on, and COOKIE_SECURE=true marks the session cookie HTTPS-only.

Where the proxy itself runs decides the upstream.

The published port is reached at 127.0.0.1:8080, the only address BIND_ADDRESS=127.0.0.1 leaves it on and the setting that closes the instance to everything but the proxy.

The application takes requests up to 25 MB, which is the size a JSON export of a full instance reaches and has to be re-imported at. nginx accepts 1 MB by default and answers anything larger with its own 413 Request Entity Too Large page. The request never reaches Badlen, so the application log holds nothing about it. Put client_max_body_size 25m; in the proxied location to match the two.

Tell the app how many proxies are in front

Section titled “Tell the app how many proxies are in front”

Behind a proxy every request arrives from the proxy, and two things read an address off a request. Rate limits are counted per address, so the ten-a-minute limit on the routes that check a password becomes ten a minute for the whole household, and one person mistyping twice locks everybody else out. And each session under Settings → Security is shown at the address it was opened from, so every device in the house is listed at the same one.

TRUSTED_PROXY_HOPS=1 gives both the reader again. The number is one for a single nginx or Caddy, two if something like a CDN sits in front of that. It is read as a count from the end of the X-Forwarded-For header, because each proxy appends the address it received the request from: with one proxy in front, the last address in that header is the one your proxy wrote. A client inventing a header of its own only pushes that invention further left, which is the whole reason the count comes from you and not from the header. Too low and the outer proxy is what gets counted; too high and there is no such address, so both fall back to the connecting one and the log says so, once a minute:

Terminal window
docker compose logs app | grep TRUSTED_PROXY_HOPS

COOKIE_SECURE=true is the one setting that can send you back to the sign-in page for ever. The browser keeps a cookie marked that way on an HTTPS origin and throws it away on a cleartext one, localhost excepted. Reaching the same instance directly at http://<lan-ip>:8080 while it is set signs you in and loses the session on the spot: the sign-in answers 201, the app opens, the first navigation lands back on the sign-in page, and nothing anywhere says why. Go through the proxy, or set COOKIE_SECURE=false while there is no HTTPS in front.

One last thing the browser decides alone: a certificate it does not trust, a self-signed one included, costs the installable app. It refuses to register the service worker and prints an SSL error in the console. The interface and the data are unaffected.

Privacy