Ramblings of an aging IT geek
← Ramblings of an aging IT geek
tooling

the ssh drop that no longer costs me anything

How a persistent tmux session on every remote box turned a dropped SSH connection from a small disaster into a non-event, and the handful of config lines that make it pleasant to use.

A mechanical keyboard in front of a terminal full of split panes

The habit that has saved me the most grief over the years is also the most boring: I never run a long job over a bare SSH connection. The connection will drop. The train goes into a tunnel, the wifi hiccups, the laptop sleeps, and whatever was running in that terminal, the migration, the long build, the half-finished sentence in an editor, gets a hangup and dies with it. tmux fixes this so completely that I'd forgotten it was ever a problem until I watched a colleague lose an hour to it last week.

The idea is simple. tmux runs a session on the server, detached from your terminal. Your SSH connection attaches to that session. When the connection drops, the session keeps running, blissfully unaware that the human went away. You reconnect, run tmux attach, and you're back exactly where you were: same processes, same scrollback, same cursor position. The job never knew you left.

Split terminal panes showing a build and logs side by side

The workflow on a remote box is two commands. Start or reattach to a named session, and that's it:

# first time, or after a reboot
tmux new -s work

# every time after that, from a fresh ssh
tmux attach -t work || tmux new -s work

That attach || new is the whole trick: reattach if it's there, create it if it isn't. I have it aliased so connecting to a server drops me straight into my persistent session without thinking.

Out of the box tmux is a bit austere, and the default prefix of Ctrl-b is awkward enough that people bounce off it. A few lines in ~/.tmux.conf make it genuinely pleasant rather than merely useful:

# screen-style prefix, easier on the hands
set -g prefix C-a
unbind C-b
bind C-a send-prefix

# saner splits that remember the current path
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

# bigger scrollback and mouse on for the lazy days
set -g history-limit 50000
set -g mouse on

# start numbering at 1, my fingers prefer it
set -g base-index 1

None of that is clever. mouse on in particular feels like cheating, and I resisted it for years on principle before admitting that scrolling with a mouse wheel and dragging pane borders is just nicer when I'm tired.

The split panes are the bit I'd undersell at my peril. On a remote box I'll routinely have a build running in one pane, a tail of the logs in another, and a shell in a third, all in one window, all surviving a disconnect together. Reattach and the whole arrangement is intact. It turns a remote server from a single fragile pipe into a workspace that's waiting for you whenever you come back.

The reason I keep banging on about it: the value isn't the splits or the scrollback, nice as they are. It's that a dropped connection stopped being an event. I no longer hesitate before kicking off a two-hour job over a flaky link, no longer babysit a terminal because closing the lid would kill it. The work happens on the server and I'm just a window onto it. Set it up once on every box you touch and you'll forget, as I had, that losing an SSH session was ever something to dread.