Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

Archive · Linux

Quality of Life: ~/.ssh/config and tmux

Faster, safer SSH with per-host config, jump hosts and multiplexing, and tmux sessions that survive disconnects.

3 min read

  • Ubuntu 18.04.4 LTS
  • OpenSSH 7.6
  • tmux 2.6
  • ssh-agent

Two small tools remove most daily friction on servers: an SSH client config that remembers hosts, users and keys, and tmux, which keeps your work running when your connection drops. Both are worth ten minutes of setup.

Versions in use on this date. OpenSSH 7.6 and tmux 2.6 on Ubuntu 18.04.4 LTS. ProxyJump needs OpenSSH 7.3 or later on the client; the jump host only needs a normal sshd.

How the pieces fit

flowchart TB
  L[Laptop<br/>ssh-agent holds unlocked key] -->|ssh bastion| B[Bastion host<br/>public IP, locked down]
  B -->|ProxyJump| W[web01 private subnet]
  B -->|ProxyJump| D[db01 private subnet]
  L -.->|ControlMaster reuses one connection| B
  W --> T[tmux session on server<br/>survives disconnects]

~/.ssh/config

Host *
  ServerAliveInterval 30
  ServerAliveCountMax 3
  AddKeysToAgent yes
  IdentitiesOnly yes
  ControlMaster auto
  ControlPath ~/.ssh/cm-%r@%h:%p
  ControlPersist 10m

Host bastion
  HostName 203.0.113.10
  User ravi
  IdentityFile ~/.ssh/id_ed25519

Host web01 db01
  User ravi
  ProxyJump bastion
  IdentityFile ~/.ssh/id_ed25519

Host web01
  HostName 10.0.1.11
Host db01
  HostName 10.0.2.21
  LocalForward 15432 localhost:5432
chmod 600 ~/.ssh/config
ssh web01                         # goes through bastion automatically
ssh -L 8080:internal-app:80 bastion      # one-off local port forward
scp file.txt web01:/tmp/          # config applies to scp and rsync as well
ssh -O check bastion              # is the shared connection alive

What the options do:

  • ServerAliveInterval keeps NAT and firewalls from dropping idle sessions, and ends dead ones.
  • ControlMaster/ControlPersist reuse one TCP connection for later sessions, which makes the second ssh or scp to the same host instant.
  • IdentitiesOnly yes offers only the key named for that host, which avoids “Too many authentication failures”.
  • ProxyJump is safer than agent forwarding. Avoid ForwardAgent yes on shared hosts because a root user there can use your forwarded agent while you are connected.

ssh-agent

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519          # asks for the passphrase once
ssh-add -l                         # list loaded keys

Keep a passphrase on every key; the agent removes the repeated typing.

tmux: sessions that survive

Without tmux, a closed laptop or dropped Wi-Fi kills a long-running command. tmux runs on the server, and you re-attach.

sudo apt install tmux
tmux new -s deploy              # new named session
# ... run work ...  Ctrl-b d    # detach: it keeps running
tmux ls
tmux attach -t deploy
tmux kill-session -t deploy

The prefix is Ctrl-b, followed by:

Keys Action
c / n / p / , New / next / previous window, rename window
% / " Split pane vertically / horizontally
arrow keys Move between panes
z Zoom a pane
[ Scroll and copy mode (q to leave)
d Detach
? Help

A starter ~/.tmux.conf:

set -g mouse on
set -g history-limit 50000
set -g base-index 1
setw -g pane-base-index 1
set -g status-right '#H %H:%M'
bind r source-file ~/.tmux.conf \; display "reloaded"

Reload with tmux source-file ~/.tmux.conf. Because tmux 2.6 on Ubuntu 18.04 is not the newest, check options against man tmux for your version.

Good habits

  • Start long jobs (upgrades, migrations, big copies) inside tmux, and name sessions after the task.
  • Do not leave a root shell open in a shared tmux session; use separate sessions per person, or tmux -S shared sockets only on purpose.
  • Keep ~/.ssh/config in a private repository (without keys) so new laptops are productive immediately.
  • Use ssh -v host to debug connections, and ssh -G host to print the effective configuration for a host.