termal.in

← Blog

Give Hermes Agent SSH access to your servers without handing it a key

· Termalin Team ai-agentsmcpsshsecuritytutorial

Hermes Agent already runs shell commands on a remote box. Its SSH terminal backend points at one host and runs each command over ssh. That is fine for a single server. The moment you have more than one, or you do not want a private key sitting on the machine that runs the agent, the backend is the wrong tool. The cleaner setup is to connect Hermes to a remote MCP server that reaches your servers for it — no key on the agent box, many hosts, per-connection rules, and an audit log. This post covers both: how the SSH backend works today, and how to wire Termalin in as an MCP server instead.

Disclosure: we build Termalin. The Hermes Agent details below are from its public docs and issue tracker, checked October 15, 2026.

How Hermes Agent uses SSH today

Hermes Agent runs its tools through a terminal backend. One of those backends is SSH. You set it in ~/.hermes/config.yaml:

terminal:
  backend: ssh

The credentials go in ~/.hermes/.env:

TERMINAL_SSH_HOST=my-server.example.com
TERMINAL_SSH_USER=ubuntu

TERMINAL_SSH_PORT defaults to 22, and TERMINAL_SSH_KEY is a path to a private key (the system default is used when you leave it blank). The docs describe the mechanism plainly: it “runs commands on a remote server over SSH,” reuses the connection with ControlMaster and a 5-minute idle keepalive, and each command is a fresh ssh … bash -c.

Three facts follow from that design, and they are the reason people go looking for something else:

  • One backend means one host. TERMINAL_SSH_HOST and TERMINAL_SSH_USER are both required, and the backend has no multi-host inventory. To work a second server you reconfigure.
  • A private key lives on the Hermes machine, either as a file or through the system ssh-agent. Anything that can read that machine can use the key, and the key opens every host that trusts it.
  • Hermes copies its own credentials to the remote box. The docs note that for the SSH, Modal, and Daytona backends, Hermes pushes your ~/.hermes/ state — credential files, skills, cache — into the remote sandbox for the session, and syncs changed state files back on teardown.

The docs do make a fair argument for the SSH backend: because the agent runs on a different box, it “can’t modify its own code.” That isolation is real, and we come back to it below.

The problems people hit

The hermes-agent tracker has a recognizable cluster of open issues around these SSH paths. Cited by number, without overclaiming what each one means for you:

  • The SSH backend fails with “path too long for Unix domain socket” when you use named profiles (#133436).
  • /reload does not clear cached SSH environments after a config change (#71085).
  • The desktop SSH mode has its own set: a macOS probe that fails about a second in (#80836), and Windows OpenSSH hangs and timeouts (#118983, #138378, #127320).
  • A boot retry storm of roughly 25 SSH logins a minute (#134197).
  • hermes update fails on networks that block port 22 (#133439).

Some of these are about the desktop app rather than the backend, and some may already be resolved by the time you read this. The pattern is what matters: the SSH backend is a thin wrapper over one ssh connection, so it inherits every sharp edge of that connection — including needing port 22 reachable.

A keyless alternative: Termalin as a remote MCP server

Hermes Agent supports MCP. It can talk to stdio servers and to remote HTTP servers, with either a Bearer header or OAuth. That is the opening. Instead of giving the agent a key and one host, you point it at a remote MCP server that already knows how to reach your fleet.

Termalin is an SSH client with a hosted MCP server. Each server you want reachable runs a Connector — a one-line install that dials out and never listens on a port, so it works behind NAT and CGNAT, and port 22 does not need to be open. On enrollment the server’s sshd trusts Termalin’s SSH certificate authority. Every login then uses a short-lived certificate scoped to your account. No long-lived key sits on the box, and none is handed to the agent.

MCP servers go under the top-level mcp_servers key in ~/.hermes/config.yaml. There are two ways to authenticate. On a VPS — the usual place Hermes runs — the API key is simpler, so start there.

Option A — API key (best on a VPS)

Create an API key in the Termalin web cabinet, scope it to the servers this agent should touch, set it read-only or to an allowlist, and give it an expiry. Put it in ~/.hermes/.env:

TERMALIN_API_KEY=tk_live_your_key_here

Then add the server. Hermes resolves ${VAR} references at server-connect time, inside headers too:

# ~/.hermes/config.yaml
mcp_servers:
  termalin:
    url: "https://termal.in/api/v1/mcp"
    headers:
      Authorization: "Bearer ${TERMALIN_API_KEY}"

Check the connection, then reload MCP inside a session:

hermes mcp test termalin
/reload-mcp

Streamable HTTP is the default transport for url servers, and that is what termal.in speaks, so you do not need a transport: line.

Option B — OAuth sign-in (for a laptop)

If Hermes runs on your own machine with a browser, OAuth avoids storing a key:

# ~/.hermes/config.yaml
mcp_servers:
  termalin:
    url: "https://termal.in/mcp"
    auth: oauth
hermes mcp login termalin

On first connect Hermes prints an authorize URL, opens your browser when it can, and waits for the OAuth callback on a local loopback port. Termalin’s sign-in accepts that loopback redirect (http://127.0.0.1:<port>/callback), so auth: oauth works on our side.

On a headless VPS the loopback callback cannot reach your laptop. Two ways around it work with Termalin: paste the redirect URL back at the Hermes prompt, or forward the port with ssh -N -L <port>:127.0.0.1:<port> user@host and finish the sign-in in your laptop’s browser. Hermes also has a device-code flow, but Termalin’s sign-in does not offer it — on a server, the API key in Option A is the simpler route.

What you get once it is connected

After hermes mcp test termalin (or hermes mcp login termalin) and /reload-mcp, Termalin’s tools appear to the agent: hosts_list to see which servers it may reach, ssh_exec and ssh_exec_many to run commands on one or many, sftp_list / sftp_read / sftp_write for files, server_metrics and alerts_list for health, and job_start / job_status / job_stop / job_list for work that outlives a single call.

The practical differences from the SSH backend:

  • Many servers at once. ssh_exec_many runs the same command across a set of hosts. There is no one-host limit and no reconfiguring to switch boxes.
  • Per-connection rules. In the AI apps card you set a command policy for this connection: full access, an allowlist, or read-only. Start read-only, widen later.
  • An audit log. Every command the agent runs is tagged as the agent’s, recorded, and shown in the live watch grid. “The agent did this” is a filter, not a reconstruction. See auditing what an agent does.
  • Background jobs. A long migration or build runs as a job, so a slow task does not block the session or hit a fixed timeout.
  • No open port. The Connector dials out, which also sidesteps the “port 22 blocked” class of problem.

Revoking access is one toggle, not a key rotation across every host. For the reasoning behind that trade, see why you should not hand an agent your SSH key and blast radius.

When to keep the SSH backend instead

This is not a case where one option wins every row.

  • If you have exactly one box, already keep a key on the Hermes machine, and want nothing else in the loop, the SSH backend is the least to set up.
  • The docs’ isolation point holds: running on a separate host means the agent cannot edit its own code. The MCP route keeps that property too, since commands execute on your servers, not on the agent box — but if the SSH backend already gives you that and nothing more is needed, there is no reason to switch.
  • Termalin’s MCP and monitoring tools need a Pro plan ($10/mo, or $8/mo billed yearly — $96/yr), or the 14-day trial, and a Connector on each server. A lone key and the SSH backend cost nothing.

Use Termalin when you have several servers, when you do not want a key on the agent box, when the servers sit behind NAT, or when you need per-connection rules and an audit trail. Keep the SSH backend when one key on one host is genuinely all you need.

Troubleshooting

  • The tools do not show up. Run hermes mcp test termalin, confirm the url is right, and that TERMALIN_API_KEY is set in ~/.hermes/.env. Then /reload-mcp inside the session.
  • 401 from the endpoint. The API key is missing, wrong, or expired. Create a new one in the cabinet and update ~/.hermes/.env.
  • The ${TERMALIN_API_KEY} reference is sent literally. Hermes expands ${VAR} at connect time; make sure the variable is in ~/.hermes/.env (or the shell that launched Hermes) and reconnect.
  • OAuth on a headless VPS never completes. The loopback callback cannot reach your laptop. Forward the port with ssh -N -L <port>:127.0.0.1:<port> user@host, or paste the redirect URL back at the prompt. On a server, the API key route is simpler.
  • Wrong transport. url servers default to Streamable HTTP, which termal.in uses. Only set transport: sse for servers that speak SSE alone — not this one.

FAQ

Does Hermes Agent support MCP? Yes. It connects to stdio servers and to remote HTTP servers, with a Bearer header or OAuth, configured under mcp_servers in ~/.hermes/config.yaml.

Can I use this with Hermes Agent on a VPS? Yes, and the API-key route is the easiest there. The OAuth flow needs a browser or one of the headless workarounds above.

Do I need to open a port on my servers? No. The Connector dials out, so it works behind NAT and CGNAT without any inbound port. See SSH behind NAT.

Is my SSH key given to the agent? No. Servers are reached with short-lived certificates issued per login. No long-lived key leaves Termalin, and none is placed in the agent’s environment.


Termalin is a cross-platform SSH client with a hosted MCP server, a key custodian, and per-host agent policy. Running a different agent? The same keyless setup works for OpenClaw, Codex and others — or download the app to start.

Try it on one host.

Termalin is a fast SSH client for you — and your agents.

Free tier · 14-day Pro trial · pricing