SSH sessions worth configuring once
2026-03-05
Multiplexing: one connection, many sessions
Every new SSH session pays for a TCP connection, a key exchange and an authentication. On a flaky link that is where the pain is, and it is avoidable: let the first connection carry the rest.
Host *
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
ControlPersist 10mkeeps the master alive for ten minutes after the last client exits. That is what makes a burst ofscps or a provisioning script fast, and what lets you keep a session across a brief link drop.- The
%r@%h:%pin the path is not decoration — without it two hosts with the same port and user collide, and you get "session refused" with no obvious cause. - Inspect and control it:
ssh -O check host,ssh -O exit host.
Keepalives that detect a dead peer
TCP keepalive does not help here: it is answered by the peer's kernel, which answers even when the remote process is gone. Client keepalive probes go through the encrypted channel and are answered by the SSH server, so they detect the failure you actually meet.
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
Thirty seconds times three means a dead session dies in about ninety seconds instead of
hanging for an hour with a frozen terminal. On the server side the equivalent is
ClientAliveInterval, and it matters for the sessions you leave open on
long-running work: without it, a network renumbering kills them silently.
The escape sequence
When the terminal is frozen and Ctrl-C does nothing, type a newline, then
~. — that is the client's escape for "terminate this session". There are
neighbours worth knowing: ~^Z suspends, ~? lists the rest. It is
only recognised after a newline and only when typed literally, which is why it never works
the first time you try it in a panic.
Agent forwarding, and why not
ForwardAgent yes makes your keys usable on every host you hop through, which
is convenient until one of those hosts is compromised or is someone else's machine with root.
The remote agent socket is a file another privileged user on that host can open and use.
- Prefer
ProxyJump(-J) to two-hop manual jumping: no agent needed on the intermediate host at all. - If you must forward, restrict it per host and consider
AddKeysToAgent confirmso each use of a key is acknowledged on your own machine. - On the server side,
AllowAgentForwarding nois a reasonable default for machines you do not use as jump hosts.
Per-host blocks
Host lab-*
User admin
IdentityFile ~/.ssh/id_lab
ForwardAgent no
Host jump
HostName jump.example.net
ServerAliveInterval 15
Host *
Include ~/.ssh/config.d/*
Include at the end of the file, not the beginning: in OpenSSH the
first obtained value wins for most options, so a blanket block placed before the
specific ones quietly overrides them. That ordering rule is the source of a great deal of
"my config clearly says otherwise".