Skip to content

Remote Access

Remote Access with Tailscale

Secure remote access to your OpenClaw agent using Tailscale — an encrypted mesh VPN that works through NAT and firewalls without exposing ports to the internet.

Why Tailscale?

Traditional SSH exposes port 22 to the internet and requires port forwarding. Tailscale provides:

  • Encrypted end-to-end — All traffic encrypted between devices
  • No port forwarding — Works through NAT and firewalls automatically
  • Access controls — Fine-grained ACLs per device and user
  • SSH integration — Tailscale SSH replaces macOS sshd entirely
  • MagicDNS — Access devices by name (e.g., ssh your-agent)

Installation

Important: Use the Homebrew CLI installation, not the GUI app.

Terminal window
brew install tailscale
brew services start tailscale

Why not the GUI app? Both the Mac App Store and standalone .pkg versions are sandboxed — they can’t host SSH or properly configure DNS. Only the Homebrew formula provides unsandboxed tailscaled.

Authenticate and enable SSH:

Terminal window
sudo tailscale up --ssh

SSH Configuration

Disable macOS sshd

Once Tailscale SSH is working, disable the built-in SSH server:

Terminal window
sudo systemsetup -setremotelogin off

Add SSH Config Entry

On your client machine, add to ~/.ssh/config:

Host your-agent
HostName your-agent.your-tailnet.ts.net
User AGENT_USER
IdentityFile ~/.ssh/id_ed25519

Now you can simply run:

Terminal window
ssh your-agent

PATH for Non-Interactive SSH

Non-interactive SSH sessions have a minimal PATH. Prefix commands with the full PATH:

Terminal window
ssh your-agent "export PATH=/opt/homebrew/bin:/opt/homebrew/sbin:\$PATH; openclaw status"

Tailscale Serve (Dashboard & Control UI)

Expose the OpenClaw gateway to your tailnet without opening ports:

Terminal window
sudo tailscale serve --bg 18789

This maps https://your-agent.your-tailnet.ts.net to 127.0.0.1:18789 over the tailnet only. The gateway stays bound to loopback — do NOT change bind to "tailnet", as that breaks both BlueBubbles webhooks and Tailscale Serve (both proxy to loopback).

Token-Based Access

Access the dashboard from any device on your tailnet using a token in the URL:

https://your-agent.your-tailnet.ts.net/?token=YOUR_GATEWAY_TOKEN

Find your token:

Terminal window
openclaw config get gateway.auth.token

Control UI with Tailscale Auth

For a better experience, enable the Control UI with Tailscale identity-based auth. This removes the need for ?token= in the URL — the gateway trusts Tailscale identity headers instead.

Add to the gateway block in openclaw.json:

"controlUi": {
"enabled": true,
"allowedOrigins": [
"https://your-agent.your-tailnet.ts.net"
]
},
"auth": {
"mode": "token",
"token": "${OPENCLAW_GATEWAY_TOKEN}",
"allowTailscale": true
}

Why both settings are needed:

  • controlUi.allowedOrigins — The browser sends the Tailscale hostname as the Origin header. Without it listed, the gateway rejects WebSocket/UI connections with “origin not allowed”.
  • auth.allowTailscale — Lets the gateway trust Tailscale identity headers instead of requiring a token parameter.

Device Pairing

New browsers require a one-time pairing approval, even on the same tailnet. Local connections (127.0.0.1) are auto-approved.

Terminal window
openclaw devices list
openclaw devices approve <requestId>

Clearing browser data or switching browser profiles triggers re-pairing.

ACL Configuration

Configure Tailscale ACLs so the agent machine cannot initiate connections to other devices:

{
"tagOwners": {
"tag:agent": ["autogroup:admin"]
},
"grants": [
// Personal devices talk freely
{ "src": ["autogroup:member"], "dst": ["autogroup:member"], "ip": ["*"] },
// Personal devices can reach agent
{ "src": ["autogroup:member"], "dst": ["tag:agent"], "ip": ["*"] }
// IMPORTANT: No grant allows tag:agent as src.
],
"ssh": [
// Personal devices — auto-accept
{ "action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:self"], "users": ["autogroup:nonroot", "root"] },
// Agent — require browser re-authentication
{ "action": "check", "src": ["autogroup:member"], "dst": ["tag:agent"], "users": ["AGENT_USER", "root"] }
]
}

Tag the agent machine as tag:agent in your Tailscale admin console.

Verify Network Isolation

Terminal window
# From agent Mac — test actual traffic (should FAIL/timeout):
tailscale ping --icmp your-main-mac
nc -z -w 3 your-main-mac 22
# From your main Mac (should SUCCEED):
tailscale ping --icmp your-agent

Note: Plain tailscale ping (without --icmp) uses TSMP, which tests WireGuard path establishment — not ACL-enforced connectivity. TSMP pings can succeed even when ACLs correctly block all traffic. Always use --icmp or an actual TCP connection to verify isolation.

Tailscale Lock

Enable Tailscale Lock with your phone and laptop as trusted approval devices. This prevents unauthorized devices from joining your tailnet.

Common Remote Commands

Terminal window
# Check agent status
ssh your-agent "export PATH=/opt/homebrew/bin:\$PATH; openclaw status"
# View recent logs
ssh your-agent "export PATH=/opt/homebrew/bin:\$PATH; openclaw logs --tail 50"
# Restart gateway
ssh your-agent "export PATH=/opt/homebrew/bin:\$PATH; openclaw gateway restart"
# Run diagnostics
ssh your-agent "export PATH=/opt/homebrew/bin:\$PATH; openclaw doctor --deep"

Node Access (Multi-Mac Setup)

OpenClaw nodes let you connect additional Macs to your agent’s gateway. There are two types of node connections, each serving a different purpose:

ConnectionWhat It DoesCapabilities
macOS app (device node)TUI, dashboard, canvas, browser proxybrowser, canvas, screen
CLI node host (core node)Headless shell executionbrowser, system (system.run)

The macOS app gives you a UI for interacting with your agent. The CLI node host lets the agent execute commands on your Mac, which is useful when the agent needs to run something where you physically are rather than on the gateway machine.

macOS App (TUI and Dashboard)

Install the OpenClaw macOS app on your other Mac and connect it to the gateway:

  1. Open Settings and set the mode to Remote (another host)
  2. Set transport to Direct (ws/wss)
  3. Enter the gateway URL: wss://your-agent.your-tailnet.ts.net
  4. Enter the gateway token
  5. Approve the pairing on the gateway:
Terminal window
openclaw nodes pending
openclaw nodes approve <requestId>

Now you can use the TUI and dashboard from your other Mac:

Terminal window
openclaw tui
openclaw dashboard

CLI Node Host (Remote Execution)

The CLI node host registers as a separate node that supports system.run. This lets the agent selectively execute shell commands on your Mac instead of the gateway machine.

Install

Terminal window
# On your other Mac
npm install -g openclaw
openclaw node install --host your-agent.your-tailnet.ts.net --port 443 --tls

This creates a LaunchAgent (ai.openclaw.node) that runs automatically and survives reboots.

Approve the Pairing

On the gateway machine, approve the new node:

Terminal window
openclaw nodes pending
openclaw nodes approve <requestId>

Configure Exec Approvals

On your other Mac, open the OpenClaw macOS app and go to Settings. Set exec approvals to Always ask (recommended) or Allowlist. Without this, the node will reject system.run.prepare calls from the gateway.

Verify

From the gateway, check that both connections are live:

Terminal window
openclaw nodes status

You should see two entries for your Mac: one device node (macOS app) and one core node (CLI node host). The core node should list system in its capabilities.

Test remote execution:

Terminal window
openclaw nodes run --node "Your Mac (node)" --raw "echo hello && hostname"

Manage the Service

Terminal window
openclaw node status # Check if running
openclaw node restart # Restart after config changes
openclaw node stop # Stop the service
openclaw node uninstall # Remove the LaunchAgent

The node host config lives at ~/.openclaw/node.json:

{
"version": 1,
"nodeId": "generated-uuid",
"displayName": "Your Mac",
"gateway": {
"host": "your-agent.your-tailnet.ts.net",
"port": 443,
"tls": true
}
}

How the Agent Uses Nodes

The agent doesn’t route all commands to nodes by default. It executes on the gateway machine unless a specific tool call includes host=node. This means you can configure the agent to selectively target your Mac for operations that make sense there (browser automation on your local network, accessing local files, etc.) while keeping everything else on the gateway.

Node Cleanup

Over time you may accumulate stale pairings (old devices, re-paired nodes). List and inspect them with:

Terminal window
openclaw nodes status

Rename nodes for clarity:

Terminal window
openclaw nodes rename --node <id> --name "Descriptive Name"

Troubleshooting

Tailscale DNS / Serve Not Working

Use the Homebrew CLI (brew install tailscale), not the GUI app.

Stale Tailscale Shim

If you previously installed the Mac App Store version, a shim script at /usr/local/bin/tailscale may shadow the real binary:

Terminal window
sudo rm /usr/local/bin/tailscale

SSH Hangs or Timeouts

Check that Tailscale SSH is enabled:

Terminal window
tailscale status

If SSH is not shown, re-enable:

Terminal window
sudo tailscale up --ssh