# SSH Agent

URL: https://tuios.dev/docs/ssh-agent

> Let the panes of a session use the ssh agent of the client you attached from, on this machine and on remote hosts.

A shell in a pane keeps the `SSH_AUTH_SOCK` it started with. When you attach later from a new ssh connection, that value names an old agent, and `git push` or `ssh` in the pane fails. With `ssh_agent = "follow"`, the panes of a session use the agent of the client that you used last.

## Set it up

Turn on the option in `[daemon]`:

```toml
[daemon]
ssh_agent = "follow"
```

The default is `"off"`. A change in the config file applies to the next attach.

Then ssh to the machine with agent forwarding, and attach:

```bash
ssh -A workstation
tuios attach work
```

Each session gets a stable link to an agent socket. Each new pane of the session gets `SSH_AUTH_SOCK` set to that link. The link is `agent-<session id>.sock` in the folder of the daemon socket, for example `$XDG_RUNTIME_DIR/tuios/agent-3f2a9c1d-0b7e-4d0a-9c4e-5a1f2b3c4d5e.sock`. To print it, run `tuios ssh-agent-path`.

### The shell rc line

A shell that started before you turned on the option keeps its old value. Add this line to your shell rc. Then every shell in a pane uses the link:

```bash
p=$(tuios ssh-agent-path 2>/dev/null) && export SSH_AUTH_SOCK="$p"
```

Outside a pane, or with the option off, the command fails and the line changes nothing.

To see the socket that the link points at:

```bash
tuios ssh-agent-path -s work --json
```

```json
{"session": "work", "path": "/run/user/1000/tuios/agent-3f2a9c1d-0b7e-4d0a-9c4e-5a1f2b3c4d5e.sock", "follow": true, "target": "/tmp/ssh-XXXXabc/agent.4242"}
```

`target` is absent when there is no link.

## How follow chooses the agent

The link points at the agent socket of the client that attached to the session, or used it, last.

- Only `tuios attach` and `tuios new` send their `SSH_AUTH_SOCK`. Other commands do not move the link.
- A client that runs inside a pane does not count. TUIOS finds such a client by its process.
- When the client that the link points at detaches, the link moves to the socket of the client before it.
- When no attached client has a socket, the link points at the `SSH_AUTH_SOCK` of the daemon. The daemon socket must pass the checks below. If it does not, TUIOS removes the link.
- A client of the TUIOS SSH server or of `tuios-web` has no agent socket, so it does not move the link. To follow your agent, ssh to the machine with `ssh -A` and run `tuios attach`.
- The daemon removes its links when it stops and when you set the option to `"off"`. At start, it removes the links that a stopped daemon left.

### Which sockets TUIOS accepts

TUIOS resolves a symbolic link once, so `~/.ssh/agent.sock` and the 1Password agent work. The link then points at the real socket. TUIOS refuses the socket unless all of these are true:

- The real socket is a Unix socket that you own.
- Every folder above it is owned by you or by root.
- No other user can write to those folders. A sticky folder such as `/tmp` is accepted.

## Remote hosts

The agent can also follow you to a [remote host](https://tuios.dev/docs/remote-hosts). Then a session that you attach on the host uses the agent of your client on this machine.

1. Set `ssh_agent = "follow"` on both machines.
2. Turn on agent forwarding for the link to that host. TUIOS does not forward the agent by default.

Use one of these to turn on forwarding:

```
# ~/.ssh/config
Host buildbox
  ForwardAgent yes
```

```toml
# config.toml
[hosts.build]
addr = "gaurav@buildbox"
ssh_options = ["-A"]
```

For each host that forwards, the daemon keeps one link, `agent-link-<host>-<hash>.sock`. The host name is in lower case and cut to 32 characters. The hash is of the exact name, so two hosts never share a link.

- The link points at the agent of the person on this machine who attached a session on that host, or typed in one, last.
- A session of this machine does not move the link of a host.
- The daemon starts the link ssh to the host with `SSH_AUTH_SOCK` set to that link.
- Before any client attaches a session on the host, the link points at the daemon's own `SSH_AUTH_SOCK`. If the daemon has none, or its socket fails the checks, the panes on the host have no agent until a client attaches.
- If the link to a host shares an ssh master connection, ssh forwards the agent of that master.

TUIOS reads what `ssh -G` prints for the address of the host with its `ssh_options`, as ssh itself does. TUIOS asks again when the config changes, and when `ssh -G` failed the last time. A host that you remove from the config takes its link with it.

A host that does not forward gets the environment of the daemon, unchanged. Its panes use the `SSH_AUTH_SOCK` that their own login there sets: the agent of the daemon on the host, one from keychain or gnome-keyring through PAM, or none.

## Security

> **Forward the agent only to a host you trust**
>
> Root on the host can use a forwarded agent to sign in to other machines as you while the link is up.

- If the host pins this machine with `restrict` in `authorized_keys`, add `agent-forwarding` to the options of that key. Without it, the host refuses the forwarded agent.
- The check for a client in a pane stops mistakes and agents. It does not stop a local process that wants to get past it. A process that leaves its pane on purpose, for example with `setsid` and a clean environment, can still move the link.
- TUIOS refuses an agent socket that another user owns or can replace. See [Which sockets TUIOS accepts](https://tuios.dev/docs/ssh-agent#which-sockets-tuios-accepts).

## Related

*[An interactive figure goes here. Open the page to use it.](https://tuios.dev/docs/ssh-agent)*
