Skip to main content
Running Zipline behind a reverse proxy enables SSL/TLS termination, load balancing, and better security. This guide covers popular reverse proxy configurations.

Before You Begin

1

Enable trust proxy mode

Configure Zipline to trust proxy headers by setting:
CORE_TRUST_PROXY=true
This allows Zipline to correctly identify client IP addresses from X-Forwarded-For headers.
Only enable CORE_TRUST_PROXY if Zipline is behind a reverse proxy. Enabling this in a direct-to-internet setup could allow IP spoofing.
2

Configure bind address

By default, Zipline binds to 0.0.0.0:3000. When behind a reverse proxy, you can restrict it to localhost:
CORE_HOSTNAME=127.0.0.1
CORE_PORT=3000
Binding to 127.0.0.1 prevents direct external access to Zipline, forcing all traffic through your reverse proxy.
3

Update Docker port mapping (if applicable)

If using Docker, update your docker-compose.yml to only expose the port locally:
services:
  zipline:
    ports:
      - '127.0.0.1:3000:3000'  # Only accessible from localhost

Nginx Configuration

1

Create Nginx configuration file

Create a new configuration file at /etc/nginx/sites-available/zipline:
server {
    listen 80;
    listen [::]:80;
    server_name your-domain.com;

    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name your-domain.com;

    # SSL configuration (paths will vary)
    ssl_certificate /etc/ssl/certs/your-domain.crt;
    ssl_certificate_key /etc/ssl/private/your-domain.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Client max body size (adjust based on your needs)
    client_max_body_size 100M;

    # Proxy headers
    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;

    # Proxy timeouts for large uploads
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;

    location / {
        proxy_pass http://localhost:3000;
    }
}
2

Enable the site

Create a symbolic link to enable the site:
sudo ln -s /etc/nginx/sites-available/zipline /etc/nginx/sites-enabled/
3

Test and reload Nginx

Test the configuration and reload Nginx:
sudo nginx -t
sudo systemctl reload nginx
The client_max_body_size directive should match or exceed your FILES_MAX_FILE_SIZE configuration in Zipline.

Caddy Configuration

Caddy automatically handles SSL certificates via Let’s Encrypt, making it the simplest option.
1

Create Caddyfile

Create or edit your Caddyfile:
your-domain.com {
    reverse_proxy localhost:3000

    # Optional: Increase timeout for large uploads
    request_body {
        max_size 100MB
    }
}
That’s it! Caddy automatically obtains and renews SSL certificates from Let’s Encrypt.
2

Reload Caddy

Reload Caddy to apply changes:
sudo systemctl reload caddy

Apache Configuration

1

Enable required modules

Enable the necessary Apache modules:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod ssl
sudo a2enmod headers
2

Create virtual host configuration

Create /etc/apache2/sites-available/zipline.conf:
<VirtualHost *:80>
    ServerName your-domain.com
    Redirect permanent / https://your-domain.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName your-domain.com

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/your-domain.crt
    SSLCertificateKeyFile /etc/ssl/private/your-domain.key

    # Proxy settings
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    # Forward headers
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"

    # Increase timeout for large uploads
    ProxyTimeout 300

    # Error log
    ErrorLog ${APACHE_LOG_DIR}/zipline_error.log
    CustomLog ${APACHE_LOG_DIR}/zipline_access.log combined
</VirtualHost>
3

Enable site and reload Apache

sudo a2ensite zipline
sudo systemctl reload apache2

Traefik Configuration (Docker)

Traefik is popular for Docker deployments with automatic service discovery.
services:
  traefik:
    image: traefik:v2.10
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=your-email@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"

  zipline:
    image: ghcr.io/diced/zipline
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.zipline.rule=Host(`your-domain.com`)"
      - "traefik.http.routers.zipline.entrypoints=websecure"
      - "traefik.http.routers.zipline.tls.certresolver=myresolver"
      - "traefik.http.services.zipline.loadbalancer.server.port=3000"
    environment:
      - CORE_TRUST_PROXY=true

Cloudflare Tunnel (Cloudflared)

Cloudflare Tunnel provides secure access without opening ports.
1

Install cloudflared

2

Create a tunnel

cloudflared tunnel create zipline
3

Configure tunnel

Create ~/.cloudflared/config.yml:
tunnel: <tunnel-id>
credentials-file: /root/.cloudflared/<tunnel-id>.json

ingress:
  - hostname: your-domain.com
    service: http://localhost:3000
  - service: http_status:404
4

Route traffic

cloudflared tunnel route dns zipline your-domain.com
5

Run the tunnel

cloudflared tunnel run zipline
When using Cloudflare Tunnel, set CORE_TRUST_PROXY=true in Zipline’s configuration.

Important Configuration

HTTPS URLs

If you’re using HTTPS with a reverse proxy, configure Zipline to return HTTPS URLs:
CORE_RETURN_HTTPS_URLS=true
This ensures that file URLs returned by the API use https:// instead of http://.

Custom Domain

Set your primary domain to ensure correct URL generation:
CORE_DEFAULT_DOMAIN=your-domain.com

WebSocket Support (if needed in future)

If Zipline adds WebSocket support, ensure your reverse proxy forwards WebSocket connections: Nginx:
location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
Caddy:
reverse_proxy localhost:3000 {
    transport http {
        upgrade
    }
}

Troubleshooting

This usually means the reverse proxy cannot connect to Zipline:
  • Verify Zipline is running: docker compose ps or systemctl status zipline
  • Check the bind address and port in Zipline config
  • Ensure firewall allows connections between proxy and Zipline
  • Check proxy logs: sudo tail -f /var/log/nginx/error.log
This means Zipline isn’t reading forwarded headers correctly:
  • Ensure CORE_TRUST_PROXY=true is set
  • Verify your reverse proxy is sending X-Forwarded-For headers
  • Check that the header name matches (some proxies use different headers)
Increase timeout and size limits in both Zipline and the reverse proxy:Nginx:
client_max_body_size 1G;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
Caddy:
request_body {
    max_size 1GB
}
timeouts {
    read 10m
    write 10m
}
  • Verify certificate paths in proxy configuration
  • Check certificate validity: openssl x509 -in cert.pem -text -noout
  • For Let’s Encrypt, ensure ports 80 and 443 are accessible
  • Check proxy error logs for specific SSL errors

Security Best Practices

  • Always use HTTPS in production
  • Keep your reverse proxy software updated
  • Use strong SSL/TLS configurations (TLSv1.2+)
  • Implement rate limiting at the proxy level if needed
  • Consider using fail2ban to prevent brute force attacks
  • Restrict Zipline to localhost when behind a proxy
  • Enable security headers (HSTS, CSP, X-Frame-Options)
For production deployments, consider using a CDN like Cloudflare or AWS CloudFront in front of your reverse proxy for additional performance and DDoS protection.

Build docs developers (and LLMs) love