All posts
OpenClaw Reverse Proxy Setup: Caddy, Nginx & Trusted Proxies

OpenClaw Reverse Proxy Setup: Caddy, Nginx & Trusted Proxies

|4 min read

Running OpenClaw behind a reverse proxy gives you HTTPS, custom domains, and the ability to run multiple services on one server. Here's how to set it up correctly with Caddy, Nginx, or Traefik.

Why Use a Reverse Proxy?

  • HTTPS with auto-TLS: Free SSL certificates via Let's Encrypt
  • Custom domain: Access OpenClaw at openclaw.yourdomain.com
  • Security: Hide the gateway port from the public internet
  • Multi-service: Run OpenClaw alongside other apps on the same server

The Trusted Proxies Setting

This is the most important step. Without it, OpenClaw can't tell the difference between a real local connection and a spoofed one.

openclaw config set gateway.trustedProxies '["127.0.0.1"]'

If you skip this, you'll see:

WARN  gateway.trusted_proxies_missing
      Reverse proxy headers are not trusted.

And OpenClaw's local-client checks won't work properly through the proxy.

What trustedProxies Does

When a request comes through a reverse proxy, the original client IP is lost. The proxy adds it back via X-Forwarded-For headers. But OpenClaw only trusts these headers from IPs in the trustedProxies list.

Without it:

  • OpenClaw sees all requests as coming from 127.0.0.1 (the proxy)
  • It can't enforce per-client access controls
  • The security audit will flag trusted_proxies_missing

Caddy Setup

Caddy is the easiest option — automatic HTTPS, minimal config.

Caddyfile

openclaw.yourdomain.com {
    reverse_proxy localhost:3001
}

That's it. Caddy automatically:

  • Obtains a Let's Encrypt certificate
  • Handles HTTPS termination
  • Forwards requests to OpenClaw

OpenClaw Config for Caddy

openclaw config set gateway.mode local
openclaw config set gateway.trustedProxies '["127.0.0.1"]'
openclaw restart

Reload Caddy

caddy reload --adapter caddyfile --config /etc/caddy/Caddyfile

Important: Always include --adapter caddyfile when reloading. Without it, Caddy may fail silently.

Nginx Setup

Nginx Config

server {
    listen 443 ssl;
    server_name openclaw.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/openclaw.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/openclaw.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
    }
}

server {
    listen 80;
    server_name openclaw.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

Key points:

  • WebSocket support: The Upgrade and Connection headers are required for OpenClaw's real-time connection
  • Forwarded headers: X-Real-IP and X-Forwarded-For pass the real client IP to OpenClaw
  • HTTPS redirect: Force all traffic to HTTPS

Get SSL Certificate (Certbot)

sudo certbot --nginx -d openclaw.yourdomain.com

OpenClaw Config for Nginx

openclaw config set gateway.mode local
openclaw config set gateway.trustedProxies '["127.0.0.1"]'
openclaw restart

Traefik Setup

docker-compose.yml

services:
  traefik:
    image: traefik:v3.0
    command:
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.le.acme.email=you@example.com"
      - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "letsencrypt:/letsencrypt"

  openclaw:
    image: openclaw-stack
    labels:
      - "traefik.http.routers.openclaw.rule=Host(`openclaw.yourdomain.com`)"
      - "traefik.http.routers.openclaw.tls.certresolver=le"
      - "traefik.http.services.openclaw.loadbalancer.server.port=3001"
    environment:
      - OPENCLAW_GATEWAY_TOKEN=your-stable-token

DNS Configuration

Point your domain to your server's IP:

Type: A
Name: openclaw (or subdomain of choice)
Value: YOUR_SERVER_IP
TTL: 300

Cloudflare users: If using Cloudflare's free plan with a wildcard subdomain, set the DNS record to DNS only (grey cloud), not Proxied (orange cloud). Cloudflare's free plan doesn't support proxied wildcard DNS records.

Security Audit

After setting up the proxy, run OpenClaw's security audit:

openclaw security audit

You should see:

OK  gateway.trusted_proxies — reverse proxy headers are trusted

For a deeper analysis:

openclaw security audit --deep

This checks:

  • Trusted proxy configuration
  • Attack surface (open ports, enabled tools)
  • Webhook security
  • Browser control settings

Troubleshooting

"trusted_proxies_missing" Warning

openclaw config set gateway.trustedProxies '["127.0.0.1"]'
openclaw restart

Dashboard Loads But Can't Connect

WebSocket connections need special proxy config. Make sure your proxy passes Upgrade and Connection headers.

Certificate Errors

  • DNS must point to your server before requesting a cert
  • Port 80 must be open for HTTP-01 challenge (Let's Encrypt)
  • Cloudflare proxy must be disabled during initial cert issuance

502 Bad Gateway

OpenClaw isn't running or isn't on the expected port:

openclaw status
openclaw config get gateway.port

Pre-Configured Proxy

ClawTank handles reverse proxy, TLS certificates, and subdomain routing automatically. Each instance gets its own HTTPS subdomain — no proxy configuration needed.

Ready to deploy OpenClaw?

No Docker, no SSH, no DevOps. Deploy in under 1 minute.

Get started free