July 3, 2026 · 6 min read · RemoteWebAdmin Team

OpenClaw Nginx Reverse Proxy: The Production Setup Guide

Put OpenClaw behind an nginx reverse proxy: full server block with WebSocket headers, Let's Encrypt via certbot, firewall rules, and verification steps.

OpenClaw Nginx Reverse Proxy: The Production Setup Guide

OpenClaw Nginx Reverse Proxy: The Production Setup Guide

Putting an OpenClaw nginx reverse proxy in front of your instance is the production way to expose it: nginx terminates TLS with a free Let’s Encrypt certificate, proxies traffic to OpenClaw on localhost port 18789, and keeps the gateway itself off the public internet. This guide gives you the complete server block, the certbot commands, and the checks that prove it works.

Why Put OpenClaw Behind a Reverse Proxy?

You could expose OpenClaw’s port directly, or serve it with a self-signed certificate like our self-signed HTTPS guide covers. Both work in narrow cases. The reverse proxy wins for anything public, for three concrete reasons:

  1. Real certificates. Nginx plus certbot gets you a publicly trusted Let’s Encrypt certificate that browsers accept without warnings and webhook validators accept without complaint. A self-signed cert encrypts just as well, but nobody vouches for it - Meta’s WhatsApp webhook validator, for one, will flatly reject it.
  2. One hardened entry point. Everything arrives on port 443. TLS versions, ciphers, timeouts, and logging live in one nginx config instead of inside the Node process. Swap certificates or add security headers without ever touching OpenClaw.
  3. Rate limiting and abuse control. Nginx can throttle abusive clients before a single request reaches OpenClaw - something the app cannot do for itself once a flood is already inside the process.

The short rule: self-signed is fine for personal LAN use; nginx plus Let’s Encrypt is the production posture.

Step 1: Bind OpenClaw to Localhost

Before nginx enters the picture, make sure OpenClaw is not listening on all interfaces. In your OpenClaw config (config/openclaw.yaml if you followed our VPS install guide), the server block should read:

server:
  host: "127.0.0.1"
  port: 18789

Restart and verify:

pm2 restart openclaw
sudo ss -tlnp | grep 18789

The output must show 127.0.0.1:18789. If you see 0.0.0.0:18789, the gateway is reachable from the internet and the reverse proxy is decorative rather than protective. Fix the bind address first.

Step 2: Install Nginx and Create the Server Block

Install nginx and the certbot plugin in one go:

sudo apt-get install -y nginx certbot python3-certbot-nginx

Point a domain or subdomain (for example ai.yourdomain.com) at your server’s IP, then create /etc/nginx/sites-available/openclaw:

# Throttle abusive clients before they reach OpenClaw
limit_req_zone $binary_remote_addr zone=openclaw:10m rate=10r/s;

server {
    listen 80;
    server_name ai.yourdomain.com;

    location / {
        limit_req zone=openclaw burst=20 nodelay;

        proxy_pass http://127.0.0.1:18789;

        # WebSocket upgrade - OpenClaw uses WebSockets for live messaging
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Standard 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;

        # Keep long-lived WebSocket sessions open
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
}

Two parts of this block do the heavy lifting:

  • The WebSocket headers are not optional. OpenClaw’s dashboard and gateway hold WebSocket connections open for live messaging. Without proxy_http_version 1.1 and the Upgrade/Connection pair, nginx quietly downgrades the connection and you get a dashboard that loads once and then goes dead.
  • The timeouts matter for idle sessions. Nginx’s default proxy_read_timeout is 60 seconds, which will sever a quiet WebSocket. Raising it to 300 seconds keeps sessions alive between messages.

Enable the site and check the config:

sudo ln -s /etc/nginx/sites-available/openclaw /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 3: Get a Real Certificate with Certbot

This is the whole reason to be here instead of the self-signed path. One command:

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

Certbot validates that you control the domain, obtains a Let’s Encrypt certificate, rewrites your server block to listen on 443 with the certificate installed, and adds an HTTP-to-HTTPS redirect when you accept the prompt.

Renewal is automatic via a systemd timer. Verify it once and forget about it:

sudo systemctl status certbot.timer
sudo certbot renew --dry-run

If the dry run passes, your certificate renews itself before expiry with zero maintenance - no calendar reminders, no midnight expiry surprises, which is exactly the failure mode that bites self-signed setups.

Step 4: Close Every Port Except 80 and 443

The proxy only pays off if the firewall enforces it. With UFW:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp    # SSH
sudo ufw allow 80/tcp    # HTTP (Let's Encrypt validation + redirect)
sudo ufw allow 443/tcp   # HTTPS (all real traffic)
sudo ufw enable

Do not add a rule for 18789. The gateway port stays bound to localhost, reachable only by nginx on the same machine. Port 80 stays open because certbot’s renewal challenges and the HTTPS redirect both use it. For the full firewall picture, including verification and common mistakes, see our OpenClaw firewall rules guide.

Rather not maintain this yourself?

We install and run managed OpenClaw for you - setup, SSL, firewall, updates, monitoring, and fixes when a channel breaks. Your AI assistant on WhatsApp, Telegram, Discord, or iMessage - always running.

See managed plans

How Do You Verify the Proxy Actually Works?

Three checks, in order. First, confirm HTTPS answers cleanly:

curl -I https://ai.yourdomain.com

You want a 200 (or a redirect into the app) with no certificate errors - no --cacert gymnastics needed, because the certificate chain is publicly trusted now.

Second, confirm the WebSocket upgrade path by sending the upgrade headers yourself:

curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  https://ai.yourdomain.com/

A 101 Switching Protocols response means nginx is passing WebSocket upgrades through correctly. A 200 or 502 here means the Upgrade/Connection headers in your location block are missing or misspelled.

Third, re-confirm the gateway never leaked onto a public interface:

sudo ss -tlnp | grep 18789

Still 127.0.0.1:18789? Then the only way into OpenClaw is through nginx on 443, which is the whole design.

If the dashboard loads but conversations freeze after a minute of silence, that is the proxy_read_timeout symptom - bump the timeouts from Step 2 and reload nginx.

What About Caddy as a Simpler Alternative?

If nginx feels like more machinery than you want, Caddy collapses this entire guide into a few lines. Caddy obtains and renews Let’s Encrypt certificates automatically - no certbot, no timers to check - and its reverse_proxy directive handles WebSocket upgrades out of the box. A complete Caddyfile:

ai.yourdomain.com {
    reverse_proxy 127.0.0.1:18789
}

That is genuinely the whole config: automatic HTTPS, HTTP redirect, and WebSocket support included by default.

So why does this guide lead with nginx? Ubiquity and control. Nginx ships in every distro’s repos, every VPS tutorial assumes it, and fine-grained features like the limit_req rate limiting above are mature and well documented. If you are starting fresh on a personal server and want the shortest path, Caddy is a fine choice. If you want the battle-tested standard that every guide (including our security hardening guide) builds on, stay with nginx. Either way, the firewall rules and the localhost bind from this guide apply unchanged.

The Production Posture, Summarised

Exposing OpenClaw directly is fragile, and self-signed certificates cap out at LAN use. The reverse proxy pattern - OpenClaw on 127.0.0.1:18789, nginx on 443 with a Let’s Encrypt certificate, UFW allowing only 22, 80, and 443 - is the setup that survives contact with real users, real webhooks, and real attackers scanning for open ports.

If you would rather have this configured, verified, and monitored by someone who does it daily, our OpenClaw Personal Installation service sets up the full proxy stack from day one, and Maintenance & Monitoring keeps the certificate renewing and the proxy healthy long after launch.

Frequently Asked Questions

Do I need nginx for OpenClaw?

For any internet-facing OpenClaw instance, yes - a reverse proxy is the recommended production posture. Nginx terminates TLS with a real Let's Encrypt certificate, keeps port 18789 bound to localhost, holds WebSocket connections open, and gives you one hardened 443 entry point. For a LAN-only or localhost setup you can skip it, but nothing public should hit the Node process directly.

Nginx or self-signed certificate for OpenClaw?

Use nginx with a Let's Encrypt certificate for anything public - browsers trust it, webhooks accept it, and certbot renews it automatically. A self-signed certificate encrypts traffic just as well but no third party vouches for it, so it triggers browser warnings and webhook validators reject it. Self-signed is fine for personal LAN use; nginx plus Let's Encrypt is the production posture.

Why does OpenClaw disconnect behind my nginx reverse proxy?

Almost always missing WebSocket upgrade headers. OpenClaw uses WebSockets for live messaging, and plain proxy_pass silently downgrades the connection. Add proxy_http_version 1.1, proxy_set_header Upgrade $http_upgrade, and proxy_set_header Connection "upgrade" to the location block, then raise proxy_read_timeout so nginx does not cut idle sessions after its 60-second default.

Which ports should be open on an OpenClaw server behind nginx?

Only 22 for SSH, 80 for HTTP, and 443 for HTTPS. Port 18789 must never appear in your firewall rules - OpenClaw should bind to 127.0.0.1 so only nginx on the same machine can reach it. Verify with ss -tlnp | grep 18789 and confirm the output shows 127.0.0.1, not 0.0.0.0.

Does the Let's Encrypt certificate on my OpenClaw proxy renew automatically?

Yes. Running certbot --nginx installs the certificate and registers a systemd timer that renews it before expiry with no action from you. Confirm the timer is active with systemctl status certbot.timer and rehearse a renewal safely with certbot renew --dry-run. If the dry run passes, renewals will keep working unattended.

Ready for Your Personal AI Assistant?

Free 30-minute consultation. We'll assess your setup and recommend the right OpenClaw configuration for you.

Talk to an Expert