What I use Unraid for: Self hosting OpenClaw

OpenClaw is an agentic AI framework — basically it lets you run and orchestrate AI agents on your own infrastructure. I have been running it as a Docker container on Unraid and it works pretty well. As with most things I self host, I wanted to get it behind an Apache2 reverse proxy with a proper domain and SSL certificate.

Getting the basic proxy working wasn’t too bad, but the GUI kept showing a broken WebSocket connection — specifically it was trying to connect to wss:// and failing. The problem is that OpenClaw’s gateway is fundamentally WebSocket based, and a standard ProxyPass setup just silently drops the WebSocket upgrade handshake and the whole thing falls apart.

The fix is to use mod_proxy_wstunnel and mod_rewrite together to detect the Upgrade: websocket header and route those connections differently to normal HTTP traffic. You also need to tell OpenClaw itself to trust your proxy’s IP in its gateway config, otherwise it will throw 1008 unauthorised errors on the WebSocket connections.

First make sure you have the required modules enabled:

a2enmod proxy proxy_http proxy_wstunnel headers rewrite
systemctl restart apache2

Then the Apache config:

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName your.domain.com
  ServerAlias www.your.domain.com
  ServerAdmin admin@your.domain.com

  ProxyPreserveHost On
  ProxyRequests Off

  Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
  Header always set Referrer-Policy "no-referrer"

  RequestHeader set X-Real-IP %{REMOTE_ADDR}s
  RequestHeader append X-Forwarded-For %{REMOTE_ADDR}s
  RequestHeader set X-Forwarded-Proto "https"

  # WebSocket + HTTP routing
  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteRule /(.*) ws://xx.xx.xx.xx:18789/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*) http://xx.xx.xx.xx:18789/$1 [P,L]

  ErrorLog ${APACHE_LOG_DIR}/openclaw_error.log
  CustomLog ${APACHE_LOG_DIR}/openclaw_access.log combined

  Include /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile /etc/letsencrypt/live/your.domain.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/your.domain.com/privkey.pem
</VirtualHost>
</IfModule>

<VirtualHost *:80>
  ServerName your.domain.com
  Redirect permanent / https://your.domain.com/
</VirtualHost>

Replace xx.xx.xx.xx with the IP of your OpenClaw Docker container (or the Unraid host IP if you’re using port mapping), and swap in your actual domain.

The other thing you need to do is configure OpenClaw’s gateway to trust your proxy IP, and set the allowed origin for the Control UI. You can do this via the OpenClaw config or CLI:

openclaw config set gateway.trustedProxies '["your.proxy.ip"]'
openclaw config set gateway.controlui.allowedOrigins '["https://your.domain.com"]'
openclaw gateway restart

Once that’s all in place it should connect cleanly with no WebSocket errors. Remove the Let’s Encrypt section at the bottom and let Certbot add that for you if you’re setting it up fresh.