Reverse Proxy

Put TaskBandit behind HTTPS safely.

Use a reverse proxy for TLS, public hostnames, and routing while keeping the server and web containers simple.

Recommended shape

Run two TaskBandit containers behind your proxy:

  • taskbandit-server:8080 for API, auth, realtime sync, uploads, health, and notification delivery.
  • taskbandit-web:80 for the client UI/PWA at / and the admin UI at /admin.

Use HTTPS at the proxy. The containers do not need to terminate TLS themselves.

Important .env values

For a normal dedicated web origin plus a separate API origin, use values like these:

TASKBANDIT_PUBLIC_WEB_BASE_URL=https://taskbandit.example.com
TASKBANDIT_PUBLIC_API_BASE_URL=https://api.taskbandit.example.com
TASKBANDIT_SERVE_EMBEDDED_WEB=false

TaskBandit derives the admin URL automatically as <web-base-url>/admin. In most domain-based installs, you do not need to set separate admin/client URL overrides or explicit CORS values.

Only set TASKBANDIT_REVERSE_PROXY_PATH_BASE if you intentionally mount the API under a subpath. For most domain-based setups, leave it blank.

Headers to preserve

The server needs the original browser-facing host and scheme so auth callbacks, generated URLs, and secure-cookie decisions stay correct.

  • Host
  • X-Forwarded-Host
  • X-Forwarded-Proto
  • X-Forwarded-For
  • Upgrade and Connection for live sync/WebSocket-style traffic.

Nginx Proxy Manager UI example

If you use the Nginx Proxy Manager web UI, create exactly two proxy hosts:

  • taskbandit.example.com -> taskbandit-web:80 if NPM is on the same Docker network, or your Docker host IP on port 4173.
  • api.taskbandit.example.com -> taskbandit-server:8080 if NPM is on the same Docker network, or your Docker host IP on port 8080.

Keep /admin on the web host. Do not create a third proxy host just for the admin UI.

After saving the proxy hosts, verify these URLs:

  • https://taskbandit.example.com/
  • https://taskbandit.example.com/admin/
  • https://api.taskbandit.example.com/health

Nginx example

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 443 ssl http2;
    server_name api.taskbandit.example.com;

    location / {
        proxy_pass http://taskbandit-server:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

server {
    listen 443 ssl http2;
    server_name taskbandit.example.com;

    location / {
        proxy_pass http://taskbandit-web:80;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Traefik labels example

services:
  server:
    labels:
      - traefik.enable=true
      - traefik.http.routers.taskbandit-api.rule=Host(`api.taskbandit.example.com`)
      - traefik.http.routers.taskbandit-api.entrypoints=websecure
      - traefik.http.routers.taskbandit-api.tls=true
      - traefik.http.services.taskbandit-api.loadbalancer.server.port=8080

  web:
    labels:
      - traefik.enable=true
      - traefik.http.routers.taskbandit-web.rule=Host(`taskbandit.example.com`)
      - traefik.http.routers.taskbandit-web.entrypoints=websecure
      - traefik.http.routers.taskbandit-web.tls=true
      - traefik.http.services.taskbandit-web.loadbalancer.server.port=80

Subpath hosting notes

Prefer dedicated hostnames when possible. If you must mount the API under a subpath, set TASKBANDIT_REVERSE_PROXY_PATH_BASE to that subpath and keep /health routed separately or use Docker health checks instead.

TASKBANDIT_REVERSE_PROXY_PATH_BASE=/taskbandit