Two different jobs hide behind the phrase “OpenClaw SSH”, and mixing them up is where people get stuck. One is reaching OpenClaw itself: its dashboard runs on localhost, so you open it over an SSH tunnel. The other is the reverse — letting the OpenClaw agent run commands on your own servers. This post does both, and for the second one it shows a way that never puts an SSH key where the agent can read it.
One disclosure up front: we build Termalin, the keyless option in Part 2. OpenClaw is an open-source agent gateway you self-host — it runs on a box, serves a web dashboard, and installs “skills” from its marketplace, ClawHub. We describe the other approaches as fairly as we would want ours described.
Two things people mean by “OpenClaw SSH”
- Reaching OpenClaw over SSH. The dashboard is bound to localhost, so you forward its port to your machine. That is Part 1.
- Letting OpenClaw reach your servers. You want the agent to run commands on other boxes. That is Part 2, and it is the part worth doing carefully.
Part 1 — open the OpenClaw dashboard through an SSH tunnel
The OpenClaw gateway binds to 127.0.0.1:18789 on the host it runs on, on purpose. The dashboard is an admin control plane, not a public website. From your laptop, forward that port over your existing SSH login:
ssh -N -o ServerAliveInterval=30 -L 18789:127.0.0.1:18789 user@vps
Then open http://127.0.0.1:18789 in your browser. -N means “no shell, just the tunnel”; ServerAliveInterval=30 keeps the connection from going idle. The traffic uses the SSH session you already trust, so nothing new is exposed to the internet.
Do not bind the gateway to 0.0.0.0 to skip the tunnel. That puts your agent’s control plane on the public internet, and whoever finds the port has the agent. OpenClaw’s own docs say the same: use an SSH tunnel, do not expose the gateway port. Keep it on 127.0.0.1 and reach it through SSH.
When the tunnel will not connect
“Connection refused”, “check failed”, or a blank page usually means one of these:
- The gateway is not running, or is on a different port. Check on the box with
ss -tlnp | grep 18789. - Your local port 18789 is already in use. Pick another local port:
-L 28789:127.0.0.1:18789, then openhttp://127.0.0.1:28789. - You got a shell instead of a tunnel. You left off
-N.
More cases are in SSH connection refused or timed out.
Keep the dashboard tunnel up
A plain ssh -L tunnel stops when your network drops. For an always-up tunnel, use autossh or a small systemd service, or a tunnel manager that reconnects for you. The mechanics of local and remote forwards are covered in SSH port forwarding and tunnels.
Part 2 — let OpenClaw run commands on your other servers
This is the part most people want: OpenClaw sees a service is down and fixes it on the actual box. The common way is to give the agent an SSH key — a key in ~/.ssh on the gateway host, or an SSH skill from ClawHub. It works. It is also the arrangement that carries the most risk, so it is worth understanding before you reach for it.
The risky part: a key on the gateway
A skill marketplace is code you did not write, running next to your key. In early 2026, Koi Security’s “ClawHavoc” research audited 2,857 ClawHub skills and flagged 341 as malicious. Several were designed to steal SSH keys and credentials; most installed the AMOS stealer through fake “prerequisites”, and some exfiltrated the agent’s own .env file.
Add the failure mode every agent has — prompt injection from a web page or email it reads — and the consequence is plain. One SSH key on the gateway is a full shell on every host that trusts it, reachable by anything that can steer the agent. Revoking it means rotating that key on all of those hosts.
So the goal for Part 2 is to let OpenClaw run the commands you want, without a key that it — or a rogue skill — can lift.
The keyless path: a Connector, then Termalin as a remote MCP server
Two pieces.
First, install a Termalin Connector on each server you want OpenClaw to reach. It is a one-line install and outbound-only: it never listens on a port, so it works behind NAT or CGNAT and needs nothing opened in your firewall. On enrollment, the server’s sshd is set to trust Termalin’s SSH certificate authority, and every login then uses a short-lived certificate minted for your account. No long-lived key sits on the box, and none is ever handed to the agent.
Second, add Termalin to OpenClaw as a remote MCP server. MCP is how OpenClaw talks to tools it does not ship itself. Termalin’s hosted endpoint exposes your Connector-enrolled servers as tools: hosts_list, ssh_exec, ssh_exec_many, SFTP reads and writes, server_metrics, alerts_list, and more.
OpenClaw reads a JSON5 config from ~/.openclaw/openclaw.json and reloads it automatically. One gotcha first: when you leave transport out, current OpenClaw (2026.10.x) defaults to SSE. Termalin speaks Streamable HTTP, so you must set "transport": "streamable-http", or the connection fails.
There are two ways to authenticate.
API key — good for a gateway running on a VPS. Create a key in the Termalin web cabinet, scope it to the servers this agent should touch, and put the value in the environment as TERMALIN_API_KEY. Then add the server with one command:
openclaw mcp set termalin '{"url":"https://termal.in/api/v1/mcp","transport":"streamable-http","headers":{"Authorization":"Bearer ${TERMALIN_API_KEY}"}}'
Or write the same thing into ~/.openclaw/openclaw.json:
{
"mcp": {
"servers": {
"termalin": {
"url": "https://termal.in/api/v1/mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer ${TERMALIN_API_KEY}"
}
}
}
}
}
Use the ${TERMALIN_API_KEY} reference, not the literal key. openclaw mcp doctor warns when it finds a token written straight into headers, and header values are redacted in its logs.
OAuth — good when a person is signing in. Point the server at https://termal.in/mcp, set auth to oauth, then sign in:
openclaw mcp set termalin '{"url":"https://termal.in/mcp","transport":"streamable-http","auth":"oauth"}'
openclaw mcp login termalin
openclaw mcp doctor termalin --probe
openclaw mcp login prints an authorization URL and waits on a loopback callback (http://127.0.0.1:<port>/callback). Termalin’s OAuth accepts those loopback redirect URIs, so you approve the sign-in in your browser and the token is stored — there is no key to paste. If OpenClaw runs on a headless VPS and your browser is on a laptop, finish it by hand with openclaw mcp login termalin --code <code>. Note that with auth: "oauth" set, OpenClaw ignores any static Authorization header for that server, so pick one method.
Either way, openclaw mcp doctor termalin --probe confirms the server is reachable and lists its tools, and the Termalin tools then appear to the agent. (You can also add a server from the Control UI: chat → + → Connectors → Add MCP server…, admin only.)
Decide what it may do first, and log everything
A standing agent should start small. In Termalin’s AI apps card, give this connection a command policy: read-only, an allowlist of exact commands, or full access. Begin with read-only — “how are my servers”, disk, failed services, the last lines of a log, through server_metrics and alerts_list. Then widen to a narrow allowlist, then to writes, one step at a time. The reasoning behind tight, per-host command allowlists applies directly here.
Everything the agent runs is on the record. Each command lands in the session recording, the live watch grid, and the audit log, tagged as the agent’s. Because the secret is a Termalin credential and not an SSH key spread across hosts, turning the agent off is one toggle, not a key rotation on every server. If several people share one OpenClaw, OpenClaw can give each sender a separate identity (oauth.identity: "per-requester"), so the audit trail stays per person.
When the MCP server will not connect
- It connects but shows no tools, or fails on handshake. You left
transportout and OpenClaw fell back to SSE. Set"transport": "streamable-http". - 401 Unauthorized. The API key is missing or out of scope, or you are on the OAuth URL (
/mcp) without having runopenclaw mcp login. The key endpoint is/api/v1/mcp; the OAuth endpoint is/mcp. ${TERMALIN_API_KEY}arrives empty. The variable is not set in the environment OpenClaw runs in. Export it where the gateway starts.- A server you expect is missing from
hosts_list. It has no Connector yet, or it is outside the key’s scope.
Run openclaw mcp status --verbose and openclaw mcp doctor termalin --probe to see which stage fails.
Fair alternatives
The keyless path is not the only one. Two others are reasonable, depending on your needs.
Give the agent a key directly. Put an SSH key in ~/.ssh on the gateway host, or install a ClawHub SSH skill (ssh-executor, ssh-full, sshx, and others) that reads a key, a password, or a vault entry. This is the fastest to set up and depends on nothing hosted. The trade-off is exactly the risk described above: the key is readable by whatever the agent runs, its reach is every host that trusts it, and revoking it means rotating keys on all of them. If you do this, use a dedicated low-privilege key, restrict it hard with command= in authorized_keys, and never reuse your personal key.
Run a standalone SSH-MCP server that holds the key. A small self-hosted MCP server with an ssh_exec tool keeps the key in its own config, out of the model’s context. That is a real improvement — a leaked transcript no longer contains the credential. But most of these ship with no command policy, no live view, and no audit trail, so any tool call can run anything on any configured host, and your record of what happened is whatever the agent reports. We ranked these and every other arrangement by what a compromise costs in giving an AI agent SSH access, by blast radius.
FAQ
Does OpenClaw support MCP? Yes. Current OpenClaw (2026.10.x) connects to remote MCP servers over HTTP. Add one with openclaw mcp set or openclaw mcp add, or from the Control UI (chat → + → Connectors → Add MCP server…, admin only). Set "transport": "streamable-http" for servers like Termalin, because the default is otherwise SSE.
Can OpenClaw SSH into my server? It can, in two ways. Directly, if you give it a key through the exec tool or a ClawHub SSH skill. Or keyless, by connecting it to an MCP server that holds the access for it — the Connector-plus-MCP setup above, where no key ever reaches the agent.
Is it safe to give OpenClaw my SSH key? Treat it as high-risk. A key on the gateway is readable by any skill or injected instruction the agent follows, and ClawHub has shipped skills built to steal exactly that (Koi Security flagged 341 malicious skills in early 2026). If you must, use a throwaway low-privilege key with command= restrictions — never your personal key.
How do I fix “openclaw ssh connection refused”? For the dashboard tunnel, check that the gateway is running and bound to 127.0.0.1:18789 (ss -tlnp | grep 18789 on the box), make sure your local port is free, and keep -N on the ssh -L command. More cases are in SSH connection refused or timed out.
Do I need to open any ports? No. The dashboard tunnel uses your existing SSH connection, and a Termalin Connector is outbound-only — it never listens on a port, so it works behind NAT and CGNAT with nothing opened in your firewall.
Termalin is a cross-platform SSH client with a hosted MCP server, a key custodian and per-host agent policy. The hosted endpoint and Connector-based access are on Pro ($10/month, or $8/month billed yearly) and Team, with a 14-day Pro trial and no card — see MCP, the Connector, or SSH for AI agents.