Skip to main content

OpenClaw Nginx reverse proxy with auth

· 6 min read

This guide describes using Nginx as a reverse proxy for the OpenClaw gateway with HTTPS/WSS and password authentication when you have only an IP and no domain. It is based on OpenClaw remote access, authentication, and local setup docs.


1. Prerequisites and constraints

  • No domain: Access via https://<server-IP> only; you need a self-signed certificate (browser will warn; user must trust or continue).
  • OpenClaw: Remote access must use wss://, not plain ws://; gateway must stay bind: "loopback" and be reached only via Nginx.
  • Auth: Enable password (or token) authentication on the OpenClaw gateway.

2. OpenClaw gateway config (password auth)

Before Nginx, configure OpenClaw to use password auth and allow the Origin from Nginx (https://<your-IP>).

2.1 Edit ~/.openclaw/openclaw.json

In the gateway section set:

"gateway": {
"port": 18789,
"mode": "local",
"bind": "loopback",
"controlUi": {
"allowedOrigins": [
"http://127.0.0.1:18789",
"http://localhost:18789",
"https://YOUR_SERVER_IP"
]
},
"auth": {
"mode": "password",
"password": "your-access-password"
},
"trustedProxies": ["127.0.0.1"]
}

Notes:

  • Replace YOUR_SERVER_IP with the server’s public IP (e.g. x.x.x.x). For https://IP:443, Origin is usually https://YOUR_SERVER_IP (no port).
  • trustedProxies is optional. When Nginx and the gateway are on the same host, ["127.0.0.1"] lets the gateway trust proxy headers and avoids "Proxy headers detected from untrusted address" in logs.
  • auth.mode: "password" means clients must send Authorization: Bearer <password> or pass it via URL (see access section).
  • For token instead of password:
    "auth": {
    "mode": "token",
    "token": "your-access-token"
    }
    Then use ?token=your-token in the URL.

2.2 Restart gateway

systemctl --user restart openclaw-gateway.service
# or
openclaw gateway start

3. Install Nginx

On Ubuntu/Debian:

sudo apt update
sudo apt install -y nginx

Verify:

sudo nginx -v

4. Self-signed certificate (IP only, no domain)

Without a domain you cannot use Let’s Encrypt; use a self-signed cert. Replace YOUR_SERVER_IP with the real IP (e.g. x.x.x.x):

sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/openclaw.key \
-out /etc/nginx/ssl/openclaw.crt \
-subj "/CN=OpenClaw" \
-addext "subjectAltName=IP:YOUR_SERVER_IP"

Note: Use the public IP if accessed from the internet; use the private IP if only from LAN. The browser will show "connection not private"; the user must accept to continue.


5. Nginx reverse proxy

5.1 Site config

Create a config file (e.g. a server block for OpenClaw only):

sudo nano /etc/nginx/sites-available/openclaw

Paste the following (replace YOUR_SERVER_IP with the actual IP):

# OpenClaw reverse proxy (IP only, no domain, HTTPS + WSS)
# Upstream: OpenClaw gateway on 18789, loopback only
upstream openclaw_backend {
server 127.0.0.1:18789;
keepalive 64;
}

server {
listen 443 ssl;
listen [::]:443 ssl;
server_name YOUR_SERVER_IP;

ssl_certificate /etc/nginx/ssl/openclaw.crt;
ssl_certificate_key /etc/nginx/ssl/openclaw.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

access_log /var/log/nginx/openclaw_access.log;
error_log /var/log/nginx/openclaw_error.log;

location / {
proxy_pass http://openclaw_backend;
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;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}

Important: Upgrade and Connection "upgrade" are required for WebSocket; otherwise Control UI and wss will not work. Long timeouts avoid Nginx closing long-lived connections.

5.2 Enable site and reload

sudo ln -sf /etc/nginx/sites-available/openclaw /etc/nginx/sites-enabled/
sudo nginx -t

If the test passes, reload Nginx:

sudo systemctl reload nginx

6. Firewall and security group

  • Allow 443 (HTTPS).
  • Allow 80 if you want HTTP→HTTPS redirect (see next section).
  • Do not expose 18789 to the internet; the gateway listens only on localhost.

7. How to access

7.1 Browser (Control UI)

  • URL: https://YOUR_SERVER_IP (e.g. https://x.x.x.x).
  • Accept the certificate warning (normal for self-signed).
  • Password auth: If OpenClaw uses password mode, enter the password in the UI or (if supported) use https://YOUR_SERVER_IP/?password=your-password.
  • Token mode: https://YOUR_SERVER_IP/?token=your-token (use ?token=, not #token=...; the hash is not sent to the server).

8. Optional: HTTP → HTTPS redirect

To redirect http://YOUR_SERVER_IP to https://, add a server block on port 80:

server {
listen 80;
listen [::]:80;
server_name YOUR_SERVER_IP;
return 301 https://$host$request_uri;
}

Then run sudo nginx -t && sudo systemctl reload nginx.


9. Troubleshooting

9.1 Typical issues after first access via Nginx

When you first open https://YOUR_SERVER_IP/?token=..., you may see the following; address them in order.

1) "origin not allowed"

  • Cause: The browser’s Origin is https://YOUR_SERVER_IP, which is not in the gateway whitelist.
  • Fix: Add https://YOUR_SERVER_IP to gateway.controlUi.allowedOrigins in ~/.openclaw/openclaw.json (use the real IP, no :443). Restart the gateway.

2) "Proxy headers detected from untrusted address" in logs

  • Cause: The gateway sees proxy headers from Nginx but Nginx’s address is not in trusted proxies.
  • Fix: Add "trustedProxies": ["127.0.0.1"] under gateway (when Nginx is on the same host). Restart. This is optional and mainly removes the warning.

3) Connection failed: pairing required / not-paired (WebSocket 1008)

  • Cause: Via the proxy, the browser is treated as a remote device and must be paired once on the gateway. Not related to Nginx config.
  • Fix: On the server where the gateway runs:
    openclaw devices list          # Find Request ID in Pending
    openclaw devices approve <Request ID>
    After approval, reload the browser and open https://YOUR_SERVER_IP/?token=your-token again. The UI should connect. Redirect from / to /chat?session=main is normal.

9.2 Quick reference

SymptomLikely causeAction
502 Bad GatewayGateway not running or Nginx can’t reach 18789On server: curl -I http://127.0.0.1:18789/ (expect 200/3xx); run openclaw gateway start or restart systemd.
origin not allowedhttps://YOUR_SERVER_IP not in allowedOriginsAdd it to gateway.controlUi.allowedOrigins, restart gateway.
Proxy headers from untrusted addresstrustedProxies not setOptional: add "trustedProxies": ["127.0.0.1"], restart.
pairing required / not-paired (1008)Device not pairedOn server: openclaw devices list, then openclaw devices approve <Request ID>.
Page loads but "disconnected from gateway"WebSocket not proxied or Origin not allowedEnsure Nginx has proxy_http_version 1.1, Upgrade, Connection "upgrade"; ensure allowedOrigins includes https://YOUR_SERVER_IP.
Auth failureWrong password/token or not sentCheck auth.mode and auth.password/auth.token in openclaw.json; use ?token= or ?password= in URL (not #).
SECURITY ERROR (plain ws)Using ws:// or http://IP:18789Access only via Nginx’s https:// / wss://; do not connect to 18789 directly.

10. References

Related posts