OpenClaw Nginx reverse proxy with auth
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_IPwith the server’s public IP (e.g.x.x.x.x). Forhttps://IP:443, Origin is usuallyhttps://YOUR_SERVER_IP(no port). trustedProxiesis 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 sendAuthorization: Bearer <password>or pass it via URL (see access section).- For token instead of password:
Then use
"auth": {
"mode": "token",
"token": "your-access-token"
}?token=your-tokenin 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_IPtogateway.controlUi.allowedOriginsin~/.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"]undergateway(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:
After approval, reload the browser and open
openclaw devices list # Find Request ID in Pending
openclaw devices approve <Request ID>https://YOUR_SERVER_IP/?token=your-tokenagain. The UI should connect. Redirect from/to/chat?session=mainis normal.
9.2 Quick reference
| Symptom | Likely cause | Action |
|---|---|---|
| 502 Bad Gateway | Gateway not running or Nginx can’t reach 18789 | On server: curl -I http://127.0.0.1:18789/ (expect 200/3xx); run openclaw gateway start or restart systemd. |
| origin not allowed | https://YOUR_SERVER_IP not in allowedOrigins | Add it to gateway.controlUi.allowedOrigins, restart gateway. |
| Proxy headers from untrusted address | trustedProxies not set | Optional: add "trustedProxies": ["127.0.0.1"], restart. |
| pairing required / not-paired (1008) | Device not paired | On server: openclaw devices list, then openclaw devices approve <Request ID>. |
| Page loads but "disconnected from gateway" | WebSocket not proxied or Origin not allowed | Ensure Nginx has proxy_http_version 1.1, Upgrade, Connection "upgrade"; ensure allowedOrigins includes https://YOUR_SERVER_IP. |
| Auth failure | Wrong password/token or not sent | Check 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:18789 | Access only via Nginx’s https:// / wss://; do not connect to 18789 directly. |
10. References
- OpenClaw remote access (SSH / Tailscale / WSS)
- OpenClaw gateway authentication
- OpenClaw configuration examples
- Related: OpenClaw install guide — Section 6 “Remote access” and Section 10 “FAQ”