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 proxyRestart the container after making changes:
docker compose down && docker compose up -dHow BASE_URL affects cookie security
Zerobyte uses BASE_URL to determine whether authentication cookies should be marked as Secure. This directly affects how login sessions work:
| BASE_URL value | Cookie 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 nginxCaddy
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 caddyCaddy 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/zerobyteMake 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 withopenssl 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.comVerifying 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 zerobyteConfirm 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.
