Skip to main content

Remote access

By default the WednesdayAI gateway binds to loopback (127.0.0.1) and is only reachable from the machine it runs on. This is intentional — it avoids exposing the gateway before auth is configured.
Recommended path: Tailscale Serve. It gives you HTTPS, a stable hostname, and identity-based access control without changing the gateway bind address. The gateway stays on loopback.
Tailscale Serve creates an HTTPS endpoint on your tailnet that proxies to the local gateway. The gateway stays on loopback; Tailscale handles routing and TLS.
{
  gateway: {
    bind: "loopback",
    tailscale: { mode: "serve" },
  },
}
After restarting, the control panel is available at https://<hostname>.ts.net/ from any device on your tailnet. Allow Tailscale identity auth (skip token prompts for tailnet devices):
{
  gateway: {
    bind: "loopback",
    tailscale: { mode: "serve" },
    auth: { allowTailscale: true },
  },
}
When allowTailscale: true, control-panel WebSocket connections from tailnet devices are accepted without a token; HTTP API endpoints still require token/password auth. This tokenless flow assumes the gateway host is trusted — set it to false if untrusted code may run there.

Option 2 — SSH tunnel

An SSH tunnel forwards the gateway’s loopback port to your local machine. No gateway config changes needed.
ssh -N -L 18789:127.0.0.1:18789 user@gateway-host
http://127.0.0.1:18789/ on your local machine now reaches the remote gateway. Keep it alive across reconnects with autossh:
autossh -M 0 -N -o "ServerAliveInterval 30" -L 18789:127.0.0.1:18789 user@gateway-host
The macOS menubar app has built-in SSH tunnel management — Settings → General → “WednesdayAI runs on” → Remote over SSH.

Option 3 — Bind to tailnet IP directly

{
  gateway: {
    bind: "tailnet",
    auth: { mode: "token", token: "replace-with-a-strong-token" },
  },
}
The gateway listens on your tailnet IP at port 18789. Access at http://<tailscale-ip>:18789/.
When binding to a non-loopback address, auth is required — the gateway refuses to start without it. Loopback (http://127.0.0.1:18789/) will not work in this mode; connect via the tailnet IP.

Option 4 — LAN binding

For trusted home networks where every device should have access:
{
  gateway: {
    bind: "lan",
    auth: { mode: "token", token: "replace-with-a-strong-token" },
  },
}
Not recommended for untrusted networks — use Tailscale or SSH tunnels instead.

Option 5 — Reverse proxy with TLS

To put the gateway behind nginx or Caddy (for a custom domain, a shared LAN cert, or in front of an identity-aware proxy), keep the gateway on loopback and terminate TLS at the proxy.
gateway.example.com {
  reverse_proxy 127.0.0.1:18789
}
Caddy provisions and renews TLS automatically. WebSocket upgrades are proxied without extra config.
If the proxy authenticates users (OIDC/SAML/oauth2-proxy), delegate auth with trusted-proxy mode and set gateway.trustedProxies to the proxy IP(s) only.
A reverse proxy that only terminates TLS does not authenticate callers. Keep gateway.auth.mode: "token" (or "password") unless the proxy enforces identity and no path bypasses it.

Public internet access (Tailscale Funnel)

{
  gateway: {
    bind: "loopback",
    tailscale: { mode: "funnel" },
    auth: { mode: "password" },
  },
}
echo 'OPENCLAW_GATEWAY_PASSWORD=replace-me' >> ~/.openclaw/.env
The gateway becomes reachable at https://<hostname>.ts.net/. Because anyone can reach it, a password is required.

Remote CLI

To run CLI commands against a remote gateway without passing flags every time, persist a remote target:
{
  gateway: {
    mode: "remote",
    remote: {
      url: "ws://127.0.0.1:18789",        // adjust to your tunnel/tailnet URL
      token: "your-token",
      // tlsFingerprint: "<sha256>",       // pin the cert when using wss://
    },
  },
}
openclaw gateway status, openclaw models status, openclaw message send, and similar then reach the remote gateway transparently.
When you pass --url to a command, the CLI does not fall back to config or environment credentials. Include --token (or --password) explicitly — missing credentials is an error. For wss:// endpoints, pin the certificate with gateway.remote.tlsFingerprint.

Security principles

ScenarioRecommended approach
Personal use, your own devicesTailscale Serve + allowTailscale: true
Personal use, minimal setupSSH tunnel
Team or multi-user accessTailscale Serve + token auth, or trusted-proxy auth
Custom domain / shared certReverse proxy (Caddy/nginx) + token or proxy auth
Public access (uncommon)Tailscale Funnel + shared password
Air-gapped / on-prem LANbind: "lan" + token auth + firewall
Never expose bind: "lan" or bind: "custom" without a token or password — non-loopback binds are rejected at startup without auth.

Troubleshooting

  1. Confirm the gateway is running: openclaw gateway status (on the host)
  2. SSH tunnel: check the ssh -N -L ... process is up
  3. Tailscale: verify both devices share a tailnet (tailscale status)
  4. Confirm the port: openclaw doctor on the host shows the active port
Browsers cannot send bearer tokens in WebSocket handshakes. Use Tailscale Serve with allowTailscale: true, trusted-proxy auth, or connect via the macOS app or CLI.
A non-loopback bind without auth is rejected. Add a token or password, or set OPENCLAW_GATEWAY_TOKEN.
Run tailscale serve status. Ensure Tailscale is running and the gateway has started at least once with tailscale.mode: "serve". Manual: tailscale serve 18789.