Install OpenClaw Gateway on exe.dev for Remote Access
Deploy OpenClaw Gateway on an exe.dev virtual machine with HTTPS proxy for remote access. Includes automated setup via Shelley and manual installation steps.
Read this when
- You want a cheap always-on Linux host for the Gateway
- You want remote Control UI access without running your own VPS
Goal: An OpenClaw Gateway deployed on an exe.dev virtual machine, exposed at https://<vm-name>.exe.xyz.
This setup targets exe.dev's standard exeuntu image. On other distributions, translate the package names as needed.
What you need
- An exe.dev account
ssh exe.devaccess to exe.dev VMs (optional, for manual configuration)
Beginner quick path
- Navigate to https://exe.new/openclaw
- Provide your auth key or token when prompted
- Select "Agent" beside your VM and let Shelley complete provisioning
- Go to
https://<vm-name>.exe.xyz/and sign in with the shared secret you set (token auth is the default; password auth is available after changinggateway.auth.mode) - Accept pending device pairing requests via
openclaw devices approve <requestId>
Automated install with Shelley
Shelley, the agent on exe.dev, can set up OpenClaw directly from a prompt:
Set up OpenClaw (https://docs.openclaw.ai/install) on this VM. Use the non-interactive and accept-risk flags for openclaw onboarding. Add the supplied auth or token as needed. Configure nginx to forward from the default port 18789 to the root location on the default enabled site config, making sure to enable Websocket support. Set gateway.controlUi.allowedOrigins to the exact https://<vm-name>.exe.xyz origin, and set gateway.trustedProxies to ["127.0.0.1"] because nginx connects to the Gateway over loopback and overwrites X-Forwarded-For. Pairing is done by "openclaw devices list" and "openclaw devices approve <request id>". Make sure the dashboard shows that OpenClaw's health is OK. exe.dev handles forwarding from port 8000 to port 80/443 and HTTPS for us, so the final "reachable" should be <vm-name>.exe.xyz, without port specification.
Manual installation
Create the VM
From your device:
ssh exe.dev new
Then establish the connection:
ssh <vm-name>.exe.xyz
Tip
Leave this VM stateful. OpenClaw keeps
openclaw.json, per-agentauth-profiles.json, sessions, and channel/provider state in~/.openclaw/, with the workspace under~/.openclaw/workspace/.
Install prerequisites (on the VM)
sudo apt-get update
sudo apt-get install -y git curl jq ca-certificates openssl
Install OpenClaw
curl -fsSL https://openclaw.ai/install.sh | bash
Configure nginx to proxy to port 8000
Modify /etc/nginx/sites-enabled/default:
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 8000;
listen [::]:8000;
server_name _;
location / {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
# WebSocket support
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 $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeout settings for long-lived connections
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
Replace client-supplied forwarding headers rather than appending to them. OpenClaw only trusts forwarded IP metadata from proxies you explicitly list, and append-style X-Forwarded-For chains are considered a security concern.
Trust nginx and allow the public browser origin
Set the exact public origin and restrict trust to the loopback nginx hop:
openclaw config set gateway.controlUi.allowedOrigins '["https://<vm-name>.exe.xyz"]' --strict-json
openclaw config set gateway.trustedProxies '["127.0.0.1"]' --strict-json
openclaw gateway restart
For public hostnames, the browser origin check fails closed. The proxy allowlist lets OpenClaw rely on nginx's overwritten X-Forwarded-For value instead of assuming every request came from the loopback proxy. Only include proxies you control in this list.
Access OpenClaw and approve devices
Open https://<vm-name>.exe.xyz/ (refer to the Control UI output from onboarding). If authentication is requested, enter the shared secret configured on the VM.
Token auth is the default here, so run openclaw gateway auth-token --show in an interactive terminal to fetch the configured token. When no token exists, create one with openclaw doctor --generate-gateway-token and restart the Gateway. For password auth, use gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD instead.
Approve devices using openclaw devices list and openclaw devices approve <requestId>. When unsure, rely on Shelley from your browser.
Remote channel setup
For remote hosts, a single config patch call beats multiple SSH sessions to config set. Store actual tokens in the VM environment or ~/.openclaw/.env, and keep only SecretRefs in openclaw.json. The complete SecretRef contract is in Secrets management.
On the VM, ensure the service environment contains the required secrets:
cat >> ~/.openclaw/.env <<'EOF'
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
DISCORD_BOT_TOKEN=...
OPENAI_API_KEY=sk-...
EOF
From your local machine, generate a patch file and send it to the VM:
// openclaw.remote.patch.json5
{
secrets: {
providers: {
default: { source: "env" },
},
},
channels: {
slack: {
enabled: true,
mode: "socket",
botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" },
appToken: { source: "env", provider: "default", id: "SLACK_APP_TOKEN" },
groupPolicy: "open",
requireMention: false,
},
discord: {
enabled: true,
token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" },
dmPolicy: "disabled",
dm: { enabled: false },
groupPolicy: "allowlist",
},
},
agents: {
defaults: {
model: { primary: "openai/gpt-5.6-sol" },
models: {
"openai/gpt-5.6-sol": { params: { fastMode: true } },
},
},
},
}
ssh <vm-name>.exe.xyz 'openclaw config patch --stdin --dry-run' < ./openclaw.remote.patch.json5
ssh <vm-name>.exe.xyz 'openclaw config patch --stdin' < ./openclaw.remote.patch.json5
ssh <vm-name>.exe.xyz 'openclaw gateway restart && openclaw health'
Use --replace-path when a nested allowlist should match the patch value exactly, such as swapping a Discord channel allowlist:
ssh <vm-name>.exe.xyz 'openclaw config patch --stdin --replace-path "channels.discord.guilds[\"123\"].channels"' < ./discord.patch.json5
Full channel configuration details are in Discord and Slack.
Remote access
exe.dev manages authentication for remote access. By default, HTTP traffic on port 8000 forwards to https://<vm-name>.exe.xyz with email auth.
Updating
openclaw update
For channel changes and manual recovery, see Updating.