> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-webui/open-webui/llms.txt
> Use this file to discover all available pages before exploring further.

# Reverse Proxy Configuration

> Configure nginx, Apache, and other reverse proxies for Open WebUI

Configure a reverse proxy to add SSL/TLS, load balancing, and additional security features to your Open WebUI deployment.

## Why Use a Reverse Proxy?

* **SSL/TLS Termination**: Handle HTTPS encryption at the proxy layer
* **Load Balancing**: Distribute traffic across multiple instances
* **Security**: Add authentication, rate limiting, and WAF rules
* **Caching**: Improve performance with static asset caching
* **Multiple Services**: Host multiple services on different paths/domains

## Nginx

### Basic Configuration

Create `/etc/nginx/sites-available/open-webui`:

```nginx theme={null}
server {
    listen 80;
    server_name open-webui.example.com;

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

server {
    listen 443 ssl http2;
    server_name open-webui.example.com;

    # SSL Configuration
    ssl_certificate /etc/ssl/certs/open-webui.crt;
    ssl_certificate_key /etc/ssl/private/open-webui.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Proxy Settings
    location / {
        proxy_pass http://localhost:8080;
        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_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        # WebSocket Support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Timeouts
        proxy_connect_timeout 600;
        proxy_send_timeout 600;
        proxy_read_timeout 600;
        send_timeout 600;

        # Buffering
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # File Upload Size
    client_max_body_size 50M;

    # Logging
    access_log /var/log/nginx/open-webui-access.log;
    error_log /var/log/nginx/open-webui-error.log;
}
```

### Enable the Configuration

```bash theme={null}
# Create symbolic link
sudo ln -s /etc/nginx/sites-available/open-webui /etc/nginx/sites-enabled/

# Test configuration
sudo nginx -t

# Reload nginx
sudo systemctl reload nginx
```

### With Let's Encrypt SSL

Use Certbot for free SSL certificates:

<Steps>
  <Step title="Install Certbot">
    ```bash theme={null}
    sudo apt-get update
    sudo apt-get install certbot python3-certbot-nginx
    ```
  </Step>

  <Step title="Obtain Certificate">
    ```bash theme={null}
    sudo certbot --nginx -d open-webui.example.com
    ```
  </Step>

  <Step title="Auto-Renewal">
    Certbot automatically sets up renewal. Test it:

    ```bash theme={null}
    sudo certbot renew --dry-run
    ```
  </Step>
</Steps>

### Nginx with Subdirectory

To serve Open WebUI at `https://example.com/chat`:

```nginx theme={null}
location /chat/ {
    proxy_pass http://localhost:8080/;
    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_set_header X-Script-Name /chat;

    # WebSocket Support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}
```

## Apache

### Basic Configuration

Create `/etc/apache2/sites-available/open-webui.conf`:

```apache theme={null}
<VirtualHost *:80>
    ServerName open-webui.example.com
    
    # Redirect HTTP to HTTPS
    Redirect permanent / https://open-webui.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName open-webui.example.com

    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/open-webui.crt
    SSLCertificateKeyFile /etc/ssl/private/open-webui.key
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5

    # Security Headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"

    # Proxy Configuration
    ProxyPreserveHost On
    ProxyRequests Off
    
    # WebSocket Support
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:8080/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://localhost:8080/$1 [P,L]

    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    # Headers
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"

    # Timeouts
    ProxyTimeout 600

    # File Upload Size
    LimitRequestBody 52428800

    # Logging
    ErrorLog ${APACHE_LOG_DIR}/open-webui-error.log
    CustomLog ${APACHE_LOG_DIR}/open-webui-access.log combined
</VirtualHost>
```

### Enable Required Modules

```bash theme={null}
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo a2enmod headers
sudo a2enmod rewrite
```

### Enable the Site

```bash theme={null}
# Enable the site
sudo a2ensite open-webui

# Test configuration
sudo apache2ctl configtest

# Reload Apache
sudo systemctl reload apache2
```

## Caddy

Caddy automatically handles SSL certificates with Let's Encrypt:

### Basic Configuration

Create `Caddyfile`:

```caddy theme={null}
open-webui.example.com {
    reverse_proxy localhost:8080
    
    # WebSocket support is automatic
    
    # Security Headers
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
        X-XSS-Protection "1; mode=block"
    }
    
    # Request size limit
    request_body {
        max_size 50MB
    }
}
```

### Advanced Configuration

```caddy theme={null}
open-webui.example.com {
    # Custom TLS
    # tls your-email@example.com
    
    # Rate limiting (requires caddy-rate-limit plugin)
    # rate_limit {
    #     zone dynamic {
    #         key {remote_host}
    #         events 100
    #         window 1m
    #     }
    # }
    
    # Logging
    log {
        output file /var/log/caddy/open-webui-access.log
    }
    
    reverse_proxy localhost:8080 {
        # Custom headers
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
        
        # Timeouts
        transport http {
            read_timeout 600s
            write_timeout 600s
        }
    }
}
```

### Run Caddy

```bash theme={null}
# Test configuration
caddy validate --config Caddyfile

# Run Caddy
caddy run --config Caddyfile

# Or as a service
sudo systemctl enable caddy
sudo systemctl start caddy
```

## Traefik

### Docker Compose with Traefik

```yaml docker-compose.yml theme={null}
version: '3'

services:
  traefik:
    image: traefik:v2.10
    command:
      - --api.dashboard=true
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.letsencrypt.acme.tlschallenge=true
      - --certificatesresolvers.letsencrypt.acme.email=your-email@example.com
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - web

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    volumes:
      - open-webui:/app/backend/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.open-webui.rule=Host(`open-webui.example.com`)"
      - "traefik.http.routers.open-webui.entrypoints=websecure"
      - "traefik.http.routers.open-webui.tls.certresolver=letsencrypt"
      - "traefik.http.services.open-webui.loadbalancer.server.port=8080"
      - "traefik.http.middlewares.open-webui-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.routers.open-webui.middlewares=open-webui-headers"
    networks:
      - web
    restart: unless-stopped

volumes:
  open-webui:

networks:
  web:
    external: true
```

## HAProxy

### Basic Configuration

```haproxy haproxy.cfg theme={null}
global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

    # SSL
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

defaults
    log global
    mode http
    option httplog
    option dontlognull
    timeout connect 5000
    timeout client 600000
    timeout server 600000

frontend open-webui-frontend
    bind *:80
    bind *:443 ssl crt /etc/ssl/certs/open-webui.pem
    
    # Redirect HTTP to HTTPS
    redirect scheme https code 301 if !{ ssl_fc }
    
    # Security Headers
    http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
    http-response set-header X-Frame-Options "SAMEORIGIN"
    http-response set-header X-Content-Type-Options "nosniff"
    
    # Forward headers
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
    http-request set-header X-Forwarded-Port %[dst_port]
    
    default_backend open-webui-backend

backend open-webui-backend
    balance roundrobin
    option httpchk GET /health
    http-check expect status 200
    
    server open-webui-1 localhost:8080 check
    # Add more servers for load balancing
    # server open-webui-2 localhost:8081 check
```

## Kubernetes Ingress

### Nginx Ingress Controller

```yaml ingress.yaml theme={null}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: open-webui
  namespace: open-webui
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - open-webui.example.com
    secretName: open-webui-tls
  rules:
  - host: open-webui.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: open-webui
            port:
              number: 80
```

### Traefik Ingress

```yaml theme={null}
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: open-webui
  namespace: open-webui
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`open-webui.example.com`)
      kind: Rule
      services:
        - name: open-webui
          port: 80
  tls:
    certResolver: letsencrypt
```

## Security Considerations

### Rate Limiting (Nginx)

```nginx theme={null}
http {
    # Define rate limit zone
    limit_req_zone $binary_remote_addr zone=openwebui_limit:10m rate=10r/s;
    
    server {
        location / {
            # Apply rate limiting
            limit_req zone=openwebui_limit burst=20 nodelay;
            
            proxy_pass http://localhost:8080;
            # ... other proxy settings
        }
    }
}
```

### IP Whitelisting (Nginx)

```nginx theme={null}
location / {
    # Allow specific IPs
    allow 192.168.1.0/24;
    allow 10.0.0.0/8;
    deny all;
    
    proxy_pass http://localhost:8080;
}
```

### Basic Authentication (Nginx)

```bash theme={null}
# Create password file
sudo htpasswd -c /etc/nginx/.htpasswd username
```

```nginx theme={null}
location / {
    auth_basic "Restricted Access";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    proxy_pass http://localhost:8080;
}
```

## Environment Variables for Proxied Setup

When behind a reverse proxy, configure these environment variables:

```bash theme={null}
# Trust forwarded headers from proxy
FORWARDED_ALLOW_IPS=*

# For HTTPS behind proxy
WEBUI_SESSION_COOKIE_SECURE=true
WEBUI_AUTH_COOKIE_SECURE=true
```

## Troubleshooting

### WebSocket Connection Issues

Ensure WebSocket upgrade headers are set:

```nginx theme={null}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
```

### Large File Uploads Failing

Increase client body size:

```nginx theme={null}
client_max_body_size 50M;
```

### Timeout Errors

Increase proxy timeouts:

```nginx theme={null}
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
```

### Check Proxy Logs

```bash theme={null}
# Nginx
sudo tail -f /var/log/nginx/error.log

# Apache
sudo tail -f /var/log/apache2/error.log

# Caddy
sudo journalctl -u caddy -f
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Environment Variables" icon="gear" href="/deployment/environment-variables">
    Configure security and performance settings
  </Card>

  <Card title="Kubernetes" icon="dharmachakra" href="/deployment/kubernetes">
    Kubernetes Ingress configuration
  </Card>

  <Card title="Docker" icon="docker" href="/deployment/docker">
    Docker deployment guide
  </Card>

  <Card title="Updating" icon="arrow-up" href="/deployment/updating">
    Keep your deployment updated
  </Card>
</CardGroup>
