Erken erişim programına katıl
Dokümanlarda gezin
Nasıl yapılıradvanced

SSH

Lets your agent work on your own servers over SSH: run commands, read files and logs, check and restart services, move files in and out, with destructive commands refused and wide ones waiting for your yes.

6 min okuma0 görüntülenmeGüncelleme 2026-09-01
JuliaRehber Asistanı

This guide begins with What SSH does, continues through Setting it up, Safety modes, and what they refuse, Ask before running, and finishes with Who is allowed to use it.

What SSH does

SSH connects your agent to your own servers, so the ordinary operational questions get answered in the same chat as everything else. The agent can run a command, read a file, list a directory, check a systemd service and read its logs, restart a service, and move a file in or out.

It is built for the small jobs that otherwise cost you a terminal session: "is the site up?", "show me the last 50 lines of the app log", "why did last night's deploy fail?", "restart the worker".

You can connect several servers and give each one a short name you would say out loud, for example prod-web and staging. Then "restart the worker on staging" goes to the right machine. With a single server configured the agent never has to ask which one you mean, and with more than one it asks rather than guessing.

This skill touches real machines. Two things decide whether that is safe in your hands: which account you give it and whether you pin the host key. Both are in the next section, and in practice neither is optional.

Setting it up

Open the agent, find SSH in its skills and press Settings. Add one entry per machine:

  • Name - a short label you would say in a sentence: prod-web, staging, db
  • Host, Port, Username - where it connects and as whom (port defaults to 22)
  • Sign in with - a private key (recommended, and it keeps working when password login is disabled) or a password
  • Private key / Key passphrase / Password - stored encrypted, never echoed back to you and never written into a log
  • Host key fingerprint - pins the server's identity, explained below
  • Working directory - where commands start; writing outside it counts as wide-reaching
  • May use sudo - off by default; while it is off, a command that elevates is refused before it is ever sent
  • Ask before running and Safety - the two policies, each with its own section below

Press Add for a second machine. Removing an entry removes only that one; the others keep their own credentials.

Give it a limited account, not root

This is the decision that actually bounds the damage. Everything the skill refuses or asks about is there to stop accidents, and it is worth having. But a shell command cannot be judged with certainty from its text, so the privileges of the account on the other side are the only hard limit on what the agent can do. A dedicated user, with narrow sudo rules for the few things you really want elevated, is a limit your own server enforces. No setting inside Botonom can be as certain as that.

sudo adduser --disabled-password --gecos "" botonom
sudo mkdir -p /home/botonom/.ssh && sudo chmod 700 /home/botonom/.ssh
# the public key whose private half you paste into the skill settings:
echo "ssh-ed25519 AAAA..." | sudo tee /home/botonom/.ssh/authorized_keys
sudo chown -R botonom:botonom /home/botonom/.ssh
sudo chmod 600 /home/botonom/.ssh/authorized_keys
# only the commands you actually want it to elevate for:
echo 'botonom ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp' | sudo tee /etc/sudoers.d/botonom

If the agent signs in as root, Test tells you so and says to use a limited account instead. That warning is the whole point of the check, so please do not scroll past it.

Pin the host key fingerprint

Leave Host key fingerprint empty the first time and press Test. The connection is made and the fingerprint of the machine that actually answered comes back to you, together with the account it signed in as and the system it is running. Check it against what your server reports and paste it into the field:

ssh-keyscan -t ed25519 your.host 2>/dev/null | ssh-keygen -lf -

From then on the identity is pinned. If the key on the other side ever changes, the connection is refused instead of quietly trusting whatever now answers at that address. That is the difference between "we rebuilt the box" and "something else is answering as our box", and it is the only reason pinning exists.

Press Test after every change. Per server it tells you whether it connected, which fingerprint answered, whether that matches the pinned value, and whether the account turned out to be root.

Safety modes, and what they refuse

Each server carries its own safety mode, so a production machine can be careful while a scratch one is not.

Guarded (the default) refuses these outright, before anything is sent:

  • formatting a disk, shutting the machine down, rebooting it
  • erasing logs, turning the firewall off, stopping sshd (which would lock the agent, and possibly you, out)
  • overwriting the credentials the connection itself depends on
  • commands that hide what they run: eval, piping a download straight into a shell, base64 payloads

That last group deserves a straight explanation, because it will occasionally block something you meant. Shell text cannot be classified the way a SQL statement can. The same destructive command can be written a dozen ways, so no list of forbidden words is a security boundary. Guarded refuses what it cannot read rather than waving it through under a name that promises more than it delivers. If you want that freedom, choose unrestricted deliberately.

Unrestricted: anything the SSH account can do, the agent can do, with no second look.

The real boundary is the account on the far side, not this setting. Guarded plus a limited user is the combination you want on anything you would miss. Unrestricted belongs on a machine you could lose without consequence.

Ask before running

Safety decides what is refused. This setting decides when the agent has to check with you first, and it lives on each server:

  • Wide changes (the default) - it asks before anything with a wide blast radius: sudo, a recursive or wildcard delete, stopping or restarting a service, installing or removing a package, a recursive chmod or chown, killing processes, removing or pruning containers, git push or git reset --hard, writing under /etc, /usr, /boot or /root, editing crontabs
  • Every command - it asks before anything at all, reads included
  • Never ask - commands run immediately; on a guarded server the refusals above still apply

The two settings are deliberately independent, so "anything goes, but ask me first" is a valid and sensible combination.

When the agent asks, nothing has run yet. You get the exact command text and what it would affect, and the agent can only proceed by sending that same command back. A general "yes, go ahead" is not enough on purpose: the approval has to belong to that command, not to the conversation around it.

Who is allowed to use it

Every tool here is limited to signed-in workspace members from staff level upward. Someone chatting with a public agent can never reach your servers through it, whatever they type.

On top of that, the skill's capabilities are off until someone grants them in Roles & Access. Restarting a service is a separate capability from running a shell command, because "may restart the app, may not run arbitrary commands" is a real and reasonable role. Until a role has a capability, the agent does not even see the tool and will say honestly that it cannot do it.

The reading tools (list the servers, read a file, list a directory, check a service, read its logs, download a file) are declared read-only, and that declaration is what makes a scheduled morning health report possible: a task that only reads never trips an approval gate and never stalls waiting for a human at 07:00.

Two more boundaries worth knowing:

  • Private networks are refused. The host is resolved first and judged afterwards, so a hostname that points at an internal address is refused just like a literal private IP. "SSH to this server" cannot become a walk into infrastructure that is not yours.
  • Anything read off a server comes back labelled as information, not instructions. A file on a machine can contain text that tells an agent what to do next; the agent is told to report it, not obey it.

Limits you will meet

  • Command output is cut at 8,000 characters and the reply says that it was cut. The full output is stored and handed back as a link, so nothing is actually lost.
  • Streaming stops at 4 MB and the command is killed there. A command that never ends, tail -f for instance, ends here rather than running forever.
  • Time limit is 60 seconds by default, 300 at most. If a command is killed, whatever it had already done on the server is done, and the answer says so instead of pretending it was rolled back.
  • File read returns up to 512 KB. A directory listing returns up to 500 entries. File transfer in either direction is capped at 25 MB; for a directory, archive it on the server first and move the archive.
  • Uploads only accept a file already shared in this workspace. An arbitrary web address is refused, because accepting one would turn the skill into a fetch-anything proxy aimed at your servers. After a write the size is read back from the server, because a tool answering "ok" is not proof the bytes landed.

When something does not work

"No server is configured" - the skill is installed but Settings is empty, or an entry is missing a required field. Open Settings and complete it.

"Cannot reach ..." - the machine did not answer in time, or the name does not resolve. Usually a firewall or the wrong port. Your server has to be reachable from the internet.

"Host denied (verification failed)" - the key the server presented no longer matches your pinned fingerprint. Either the machine was rebuilt, in which case check the new fingerprint and paste it in, or something else is answering. Do not just clear the field to make the message go away without knowing which of the two it is.

Permission denied at sign-in - the key or password is not accepted for that user. Check the public key really is in that account's authorized_keys, and the permissions are right: 700 on .ssh, 600 on authorized_keys.

A command was refused for sudo - May use sudo is off for that server. Turn it on only after you have written the narrow sudoers rule for the commands you want elevated.

The agent asks which server you mean - more than one is configured and the question did not say. Name it ("on staging...") and it goes straight there. It never guesses, because a guess would eventually run a staging command against production.

"This is a private or internal address" - the host resolves inside a private network. Refused on purpose.

It asks for confirmation even on plain reads - that server's Ask before running is set to Every command. Set it back to Wide changes if that is not what you wanted.

A long job stopped halfway - it hit the time limit. Run it detached on the server and read the log afterwards, rather than holding the connection open.

SSHServersLinuxOperationsDevOps

AI çalışanlarınız işe başlamaya hazırSiz işe almaya hazır mısınız?

Kredi kartı gerekmez5 dakikada kurulumİstediğiniz zaman iptal