Zerobyte

Reverse Proxy

Run Zerobyte behind Nginx, Caddy, or Traefik with HTTPS

When running Zerobyte behind a reverse proxy, you need to configure the BASE_URL environment variable with your HTTPS domain and ensure your proxy passes the correct headers.

Prerequisites

Set the following environment variables in your docker-compose.yml:

environment:
  - BASE_URL=https://zerobyte.example.com
  - TRUST_PROXY=true  # Optional: trust X-Forwarded-For headers from your proxy

Restart the container after making changes:

docker compose down && docker compose up -d

Zerobyte uses BASE_URL to determine whether authentication cookies should be marked as Secure. This directly affects how login sessions work:

BASE_URL valueCookie behavior
http:// or IP address (e.g., http://192.168.1.100:4096)Secure cookies disabled, cookies sent over HTTP. Suitable for local network access.
https:// with domain (e.g., https://zerobyte.example.com)Secure cookies enabled, cookies only sent over HTTPS. Required for production.

If BASE_URL is set to an https:// address, browsers will only send authentication cookies over HTTPS connections. Accessing Zerobyte over plain HTTP will fail with login loops or session errors. Make sure your reverse proxy terminates TLS before forwarding to Zerobyte.

Proxy configurations

Nginx

Create a server block for Zerobyte. This configuration handles TLS termination and forwards requests to the container:

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

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:4096;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Reload Nginx after saving:

sudo nginx -t && sudo systemctl reload nginx

Caddy

Caddy automatically provisions and renews TLS certificates from Let's Encrypt. Add this to your Caddyfile:

zerobyte.example.com {
    reverse_proxy localhost:4096
}

Reload Caddy after saving:

sudo systemctl reload caddy

Caddy automatically handles X-Forwarded-For, X-Forwarded-Proto, and TLS, with no extra configuration needed.

Traefik

If you run Traefik as your reverse proxy, add labels to the Zerobyte service in your docker-compose.yml:

services:
  zerobyte:
    image: ghcr.io/nicotsx/zerobyte:v0.29
    container_name: zerobyte
    restart: unless-stopped
    environment:
      - BASE_URL=https://zerobyte.example.com
      - APP_SECRET=your-secret-here
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.zerobyte.rule=Host(`zerobyte.example.com`)"
      - "traefik.http.routers.zerobyte.entrypoints=websecure"
      - "traefik.http.routers.zerobyte.tls.certresolver=letsencrypt"
      - "traefik.http.services.zerobyte.loadbalancer.server.port=4096"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/lib/zerobyte:/var/lib/zerobyte

Make sure your Traefik instance is configured with a websecure entrypoint and a letsencrypt certificate resolver.

Binding to localhost

If you are using a reverse proxy on the same machine, bind the Zerobyte port to 127.0.0.1 so it is not directly accessible from the network:

ports:
  - "127.0.0.1:4096:4096"

This ensures all traffic goes through your reverse proxy, which handles TLS and authentication headers.

Security considerations

Exposing Zerobyte to the internet requires care. Even behind a reverse proxy with HTTPS, make sure you:

  • Bind the container port to localhost only (127.0.0.1:4096:4096) so it cannot be accessed directly.
  • Use a strong APP_SECRET (generated with openssl rand -hex 32).
  • Keep Zerobyte updated to the latest version.
  • Consider placing Zerobyte behind a secure tunnel (Cloudflare Tunnel, Tailscale, WireGuard) for an additional layer of protection.

A note on TRUSTED_ORIGINS

The TRUSTED_ORIGINS environment variable allows you to add additional CORS origins for cross-origin requests. It does not make HTTP work when BASE_URL is set to HTTPS. If your BASE_URL uses https://, all access must go through HTTPS regardless of what is listed in TRUSTED_ORIGINS.

# TRUSTED_ORIGINS only adds allowed CORS origins, it does NOT downgrade HTTPS to HTTP
environment:
  - BASE_URL=https://zerobyte.example.com
  - TRUSTED_ORIGINS=https://other-app.example.com

Verifying your setup

After configuring your reverse proxy:

Test HTTPS access

Open https://zerobyte.example.com in your browser. You should see the Zerobyte login page with a valid TLS certificate.

Check headers

Verify that your proxy is forwarding the correct headers. In the Zerobyte container logs, you should see requests coming from your proxy:

docker compose logs -f zerobyte

Confirm login works

Log in with your admin credentials. If login fails or loops, double-check that BASE_URL matches the URL you are accessing and that cookies are being set correctly over HTTPS.