Once OpenClaw is working on the host itself, the next question is how far you really want to expose it. This is usually the point where a clean setup starts getting messy. People bind the Gateway to a public interface too early, skip authentication, or assume HTTPS alone solves the problem.
In most cases, the safer move is to leave the Gateway on loopback and layer remote access on top of it. For most home labs and small VPS setups, that means one of three choices: an SSH tunnel, Tailscale Serve, or an identity-aware reverse proxy. If you still need the base install first, start with How to Install OpenClaw on Ubuntu and Complete Your First Setup, then come back here.
The short version
If you want the quick recommendation first, use this order:
Best universal default: loopback plus SSH tunnel
Best tailnet-friendly default: loopback plus Tailscale Serve
Best domain-based shared setup: identity-aware reverse proxy in front of OpenClaw
What I would avoid for a fresh setup: opening the Gateway directly on a public IP and hoping a secret URL counts as security
That order fits the way OpenClaw is meant to be exposed, and it avoids the mistakes I see most often in self-hosted AI setups.
What should stay true before you expose anything
Remote access should come after local OpenClaw health is boring.
Make sure you already have:
a working OpenClaw install or Docker Compose deployment
a Gateway that responds locally
a plan for authentication before you leave loopback
SSH access to the host if this is a VPS
a domain name only if you are taking the reverse-proxy route
If your current install still feels shaky, use these companion guides first:
Step 1: Verify the Gateway locally before you think about remote access
From the OpenClaw host, confirm the Gateway is already healthy.
openclaw gateway status
If you want a little more detail, check the deeper status path too.
openclaw status --deep
If those commands already show a broken Gateway, do not move on to reverse proxying yet. Remote exposure does not fix a local runtime problem. It just gives you a bigger blast radius.
Step 2: Keep the safest baseline, loopback first
OpenClaw's normal remote-access model assumes the Gateway usually binds to loopback on port 18789.
{
gateway: {
bind: "loopback",
},
}
That means the Gateway is reachable on the host itself, but not directly exposed to the wider network. From there, you add a deliberate access method on top.
This is the mindset that keeps the rest of the setup simple:
loopback is the default trust boundary
remote access is something you add on purpose
public exposure should be the rare case, not the starting point
Step 3: Add a real shared secret if clients will authenticate directly
If you are using direct remote clients instead of Tailscale identity headers or a trusted proxy, set real Gateway auth before you move past localhost.
Generate a long random token on the Gateway host.
openssl rand -hex 32
Create the OpenClaw env file if it is missing.
mkdir -p ~/.openclaw
Save the token there.
printf 'OPENCLAW_GATEWAY_TOKEN=replace-with-your-generated-token\n' >> ~/.openclaw/.env
Then restart the Gateway using whatever method you already use on that host and verify it came back cleanly.
openclaw gateway status
A small but important detail: client-side settings like gateway.remote.token help the client authenticate to a remote Gateway. They do not configure server-side auth for you.
Option A: SSH tunnel, the safest boring answer
If this is just for you, or for a very small setup, I would start here.
Create a local tunnel from your laptop to the remote OpenClaw host:
ssh -N -L 18789:127.0.0.1:18789 user@your-server
With that tunnel running, your local machine can reach the remote Gateway through:
ws://127.0.0.1:18789
That keeps the real Gateway private on the server while your local machine talks to a forwarded loopback port.
Why SSH tunneling is still a good default
it works almost everywhere
it keeps the remote Gateway off the public internet
it does not require a domain or reverse proxy
it matches OpenClaw's documented remote pattern closely
One easy mistake with CLI URL overrides
If you pass --url manually, OpenClaw does not quietly reuse your usual credentials.
So this kind of command needs explicit auth when the Gateway requires it:
openclaw gateway status --url ws://127.0.0.1:18789 --token your-token
That trips people up all the time because the URL looks local, but the CLI treats it as an explicit override.
Option B: Tailscale Serve, great when your tailnet already exists
If you already use Tailscale, this is usually the cleanest way to reach OpenClaw from a browser.
A minimal config looks like this:
{
gateway: {
bind: "loopback",
tailscale: { mode: "serve" },
},
}
In that setup, OpenClaw stays on 127.0.0.1, while Tailscale publishes the Control UI and WebSocket access over HTTPS inside your tailnet.
OpenClaw can also accept Tailscale identity headers for the Control UI and WebSocket when gateway.auth.allowTailscale is enabled. That is convenient, but it assumes you trust the host itself. If you do not want tokenless identity-header auth on that box, turn it off and require a token or password instead.
When Tailscale Serve is the right pick
Use it when:
you want HTTPS without building a full public reverse-proxy stack
your users are just you or a small trusted tailnet
you want the browser path to feel more natural than an SSH tunnel
When not to use it
Do not treat Tailscale Funnel like an easy beginner shortcut for public exposure. OpenClaw requires password auth for Funnel mode for a reason.
Option C: Identity-aware reverse proxy, for domain-based access that still has guardrails
This is the right choice when you want a proper URL such as https://openclaw.example.com and normal browser access through a real domain.
The key phrase here is identity-aware.
A plain TLS terminator is not enough. OpenClaw's trusted-proxy mode expects a proxy that authenticates users first, then forwards verified identity headers to the Gateway.
That can be:
Pomerium
Caddy with an OAuth-capable setup
nginx with
oauth2-proxyTraefik with forward-auth
The rule that matters most
If there is any path to the Gateway that bypasses the authenticated proxy, you have not really secured it.
That means:
firewall the Gateway so the proxy is the intended path
make sure the proxy strips or overwrites forwarded identity headers
avoid trusted-proxy mode if you only have a plain reverse proxy with no auth layer
Same-host reverse proxy pitfall
If your reverse proxy runs on the same host as OpenClaw, trusted-proxy auth does not trust loopback automatically.
Same-host loopback proxies need an explicit opt-in with gateway.auth.trustedProxy.allowLoopback = true, and you still need to list the trusted proxy source in gateway.trustedProxies.
That is a good guardrail. Without it, any local process could try to impersonate the proxy by sending identity headers.
Minimal trusted-proxy example
{
gateway: {
trustedProxies: ["10.0.0.1"],
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-forwarded-user",
requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"],
},
},
},
}
And if you are intentionally using a same-host loopback proxy, the extra opt-in matters:
{
gateway: {
trustedProxies: ["127.0.0.1"],
auth: {
mode: "trusted-proxy",
trustedProxy: {
userHeader: "x-forwarded-user",
allowLoopback: true,
},
},
},
}
Why this route is worth the effort
you get a clean domain-based URL
HTTPS lives at the proxy where it belongs
you can use OAuth or SSO instead of sharing one token everywhere
it scales better than ad hoc tunnels when more than one trusted person needs access
Know when ws:// is fine and when wss:// is not optional
OpenClaw accepts plain ws:// for loopback, LAN, .local, .ts.net, and Tailscale CGNAT hosts.
That means these patterns are normal:
ws://127.0.0.1:18789through an SSH tunnelws://192.168.x.x:18789on a trusted LANprivate tailnet access in environments you already trust
For public remote hosts, use wss://.
If you are putting OpenClaw behind a public-facing domain, stop thinking in terms of raw WebSocket endpoints. Think in terms of a properly authenticated HTTPS front door.
A safer decision ladder for beginners
If you are still deciding, this is the order I would test in real life:
SSH tunnel first if only you need access.
Tailscale Serve next if you already live in Tailscale.
Trusted reverse proxy if you want polished browser access on a real domain.
Direct non-loopback bind only when you understand the tradeoffs and have auth set correctly.
That sequence gives you convenience without jumping straight to the riskiest option first.
What I would not do on a fresh VPS
I would not do these on day one:
bind OpenClaw to a public interface with no auth plan
put it behind a plain reverse proxy that only adds HTTPS
trust client-side remote token settings to configure server-side protection
open the Gateway broadly before confirming local health, logs, and auth behavior
If you want a simpler secure-remote pattern for your overall host, Set Up a WireGuard VPN on Ubuntu 24.04 LTS is still a strong companion guide.
Final check after you pick a method
Whatever route you choose, finish with a quick sanity pass:
openclaw gateway status
openclaw health
openclaw logs --follow
You are looking for a very boring result:
the Gateway is running
the browser or client reaches the expected URL
auth succeeds the way you intended
nothing is unexpectedly reachable from a path you meant to keep private
That kind of boring is exactly what you want here.
Frequently Asked Questions
What is the safest normal way to reach OpenClaw remotely?
Can I put OpenClaw behind a plain reverse proxy with just HTTPS?
When do I need wss:// instead of ws://?
Was this article helpful?
Let me know so I can keep improving.
