HTTPS / Reverse Proxy
The default stack binds directly to localhost:4263 with plain HTTP. There is no built-in reverse proxy or TLS termination — bring your own (nginx, Traefik, Tailscale, etc.) for anything beyond your own LAN.
Reverse proxy options
Section titled “Reverse proxy options”If you already run nginx for other services, point a server block at the app container. Run nginx on the host (not in the Compose network) and target the published port:
# /etc/nginx/sites-available/boardsite — LAN / no TLSserver { listen 80; server_name games.local;
location / { proxy_pass http://127.0.0.1:4263; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }}For a public domain with TLS, terminate TLS in nginx (e.g. via certbot --nginx) and proxy the same way:
# /etc/nginx/sites-available/boardsite — public domain, TLS via certbotserver { listen 443 ssl; server_name games.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/games.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/games.yourdomain.com/privkey.pem;
location / { proxy_pass http://127.0.0.1:4263; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }}
server { listen 80; server_name games.yourdomain.com; return 301 https://$host$request_uri;}Run certbot --nginx -d games.yourdomain.com once to obtain the certificate and wire up the 443 block automatically (it edits the file above in place).
Either way, nginx proxies to the host-published port, not the container’s internal one — it runs outside the Compose network. Both are 4263 by default, so they look identical; if you set APP_PORT in .env, use that value here instead.
For a Traefik setup, add labels to the app service via a Compose override file instead of editing docker-compose.yml directly:
services: app: ports: !reset [] # Traefik handles ingress; direct port 4263 not needed labels: - "traefik.enable=true" - "traefik.http.routers.boardsite.rule=Host(`games.yourdomain.com`)" - "traefik.http.routers.boardsite.entrypoints=websecure" - "traefik.http.routers.boardsite.tls.certresolver=letsencrypt" - "traefik.http.services.boardsite.loadbalancer.server.port=4263" networks: - traefik-net
networks: traefik-net: external: trueRun with both files:
docker compose -f docker-compose.yml -f docker-compose.traefik.yml up -d --buildThis assumes Traefik itself is already running (e.g. as its own Compose stack) and joined to the traefik-net external network. The loadbalancer.server.port=4263 label targets the container’s internal port — Traefik reaches app over the Docker network, so !reset [] removes the host-published port the same way.
Run tailscale serve (or a Tailscale sidecar container) pointed at 127.0.0.1:4263. MagicDNS gives you a https://your-machine.tail-scale.ts.net URL with TLS handled automatically — no reverse-proxy config needed on your side.
Behind the proxy
Section titled “Behind the proxy”All three setups above work with the defaults. The app trusts X-Forwarded-For and
X-Forwarded-Proto from private and Docker-internal IP ranges (FORWARDED_ALLOW_IPS, see
Configuration), so:
- login rate limiting sees each visitor’s real IP rather than the proxy’s
- the session cookie gets its
Secureflag when TLS terminates at the proxy, even though the proxy talks plain HTTP to the container — see Security Model → Passwords and sessions