How to start a tmux session after login in a server using ssh, so that if the connection is lost, when I login back, I can go back to the same tmux session.
Short answer (manual):
- SSH into the server: ssh user@server
- Start a named tmux session: tmux new -s mysession
- Work inside tmux. If your SSH connection drops, reconnect and reattach: ssh user@server tmux attach -t mysession
- Useful commands:
- List sessions: tmux ls
- Detach from inside tmux: Ctrl-b then d
- Create or attach in one step: tmux new -As mysession
- Kill a session: tmux kill-session -t mysession
Automatic attach/create on login:
Put this in your ~/.bash_profile
(or ~/.profile
) so SSH logins automatically attach to (or create) a session named “main”:
if [[ $- == *i* ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ]; then
exec tmux new -As main
fi
Explanation of the checks:
[[ $- == *i* ]]
ensures the shell is interactive.[ -n "$SSH_CONNECTION" ]
ensures this runs only for SSH logins (not local scripts).[ -z "$TMUX" ]
avoids nesting tmux if you’re already inside one.- exec replaces your login shell with tmux (so Ctrl-d exits the session as expected).
Caveats / tips:
- Install tmux if it’s not present (apt/yum/pacman/etc).
- Using tmux new -As name is handy: it attaches if the session exists, otherwise creates it.
- If you want the option not to start tmux on some SSH connections, either remove the auto-start or use a different login method.
- Sessions persist on the server when your client disconnects; reattaching resumes the same environment (processes continue running unless they depend on a client-held resource).
That’s all you need to reliably get back to the same tmux session after reconnecting.
Long answer (auto-resume optional):
- a recommended automatic login snippet for bash/zsh
- a safer variant that avoids interfering with scp/rsync or non-interactive sessions
- a systemd-user approach to keep a tmux session running even when no one is logged in
- tips, caveats and helpful extras
- Automatic attach/create on SSH login — simple solution Add this to the end of your ~/.bash_profile (or ~/.profile, or ~/.zprofile for zsh). It will exec tmux so your login shell is replaced by tmux (Ctrl-D will then log you out):
if [[ $- == *i* ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ]; then
exec tmux new -As main
fi
What the checks do:
[[ $- == *i* ]]
— run only for interactive shells[ -n "$SSH_CONNECTION" ]
— run only for SSH sessions (not local)[ -z "$TMUX" ]
— don’t start tmux if you’re already inside one- exec replaces the shell with tmux (so closing tmux exits the session cleanly)
- Safer automatic startup (recommended) The simple snippet above is fine for many, but it can break non-interactive SSH uses (scp, rsync, git over SSH) and other tools. Use a slightly stricter check to run only when logging into a TTY and not during scp/rsync:
# Put this in ~/.bash_profile or ~/.profile
if [[ $- == *i* ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ] && [ -t 1 ]; then
# Choose a session name; optionally include hostname
session="main-$(hostname -s)"
exec tmux new -As "$session"
fi
Notes:
- [ -t 1 ] ensures stdout is a TTY (avoids running for scp/rsync/git that use no TTY)
- Using hostname in the session name lets you use the same dotfiles across multiple servers and keep sessions distinct
- Variant: offer choice instead of automatically replacing shell If you prefer to be prompted (or want an option to bypass tmux), you can use this approach:
if [[ $- == *i* ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ] && [ -t 1 ]; then
session="main-$(hostname -s)"
echo "Attaching to tmux session '$session' (press Ctrl-C to skip)"
sleep 1
tmux new -As "$session"
fi
This runs tmux but does not exec it; pressing Ctrl-C returns you to the normal shell.
- systemd user service (start tmux at boot / independent of login)
If you want a tmux session to exist even when nobody is logged in (useful for long-running daemons you manage interactively), create a systemd –user unit that starts a tmux session for your user on boot. Example (
~/.config/systemd/user/tmux@.service
):
[Unit]
Description=tmux session %i
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/env tmux new-session -d -s %i
ExecStop=/usr/bin/env tmux kill-session -t %i
[Install]
WantedBy=default.target
Enable / start:
systemctl --user enable --now tmux@main.service
This creates a detached tmux session named “main” that persists while the system/user systemd is running. You can then attach from any SSH session with tmux attach -t main. This is a different model (tmux session lives independent of your shells).
- Extra useful tips and tools
- Use tmux-resurrect / tmux-continuum to save/restore layout, pane commands and scrollback across reboots.
- If you want multiple named sessions (per project), change session name logic in your login script (e.g., derive name from working directory).
- Avoid nesting tmux: always check
$TMUX
. - If you use zsh, put the snippet in
~/.zprofile
or~/.zshrc
with equivalent conditions. - To reattach manually:
tmux attach -t main
ortmux new -As main
- To list sessions:
tmux ls
- Make sure tmux is installed:
apt install tmux
(Debian/Ubuntu),dnf install tmux
,pacman -S tmux
, etc.
- Caveats and troubleshooting
- exec tmux replaces the login shell. That’s desirable for an always-on workflow, but if you rely on running commands automatically from .bash_profile or .bashrc for non-interactive tasks, verify behavior first.
- If you need scp/git-over-ssh to continue to work, ensure
[ -t 1 ]
or similar check so automatic tmux startup doesn’t run for non-interactive connections. - If two people attach to the same session simultaneously, they will share the same terminal. This is normal and useful for pair-editing but can be surprising.
- If your tmux session dies unexpectedly on disconnect, inspect server logs and tmux logs. Usually processes in tmux continue unless they get SIGHUP from some external cause.
- Example: final recommended
~/.bash_profile
snippet Here’s a single snippet to copy-paste into~/.bash_profile
; it is safe for most environments:
# Auto-attach to tmux on SSH interactive login
if [[ $- == *i* ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ] && [ -t 1 ]; then
session="main-$(hostname -s)"
# Use exec to replace login shell; remove exec if you want to be able to Ctrl-C out
exec tmux new -As "$session"
fi
Snippets for bash, zsh and fish with tmux to start only sometimes
Below are ready-to-copy snippets for bash, zsh and fish that will offer to attach/create a tmux session on SSH interactive logins — but won’t force it every time. Each snippet:
- runs only on interactive SSH logins
- avoids starting tmux if already inside one
- checks for a TTY (so scp/rsync/git-over-ssh won’t be affected)
- prompts (with a short timeout) so you can skip easily
- can be disabled entirely by setting NO_AUTO_TMUX in your environment
Bash (put in ~/.bash_profile or ~/.profile)
# Offer to attach/create tmux on interactive SSH login (bash)
if [[ $- == *i* ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ] && [ -t 1 ] && [ -z "$NO_AUTO_TMUX" ]; then
session="main-$(hostname -s)"
printf "Attach to tmux session '%s'? [Y/n] (auto Y in 5s) " "$session"
# read one char with 5s timeout
read -t 5 -n 1 answer
printf "\n"
answer=${answer:-Y}
case "$answer" in
[Yy]) tmux new -As "$session" ;;
*) ;; # skip
esac
fi
Zsh (put in ~/.zprofile or ~/.zshrc; ~/.zprofile for login shells)
# Offer to attach/create tmux on interactive SSH login (zsh)
if [[ -o interactive ]] && [ -n "$SSH_CONNECTION" ] && [ -z "$TMUX" ] && [ -t 1 ] && [ -z "$NO_AUTO_TMUX" ]; then
session="main-$(hostname -s)"
printf "Attach to tmux session '%s'? [Y/n] (auto Y in 5s) " "$session"
# zsh: read one key with timeout
read -k 1 -t 5 answer
printf "\n"
answer=${answer:-Y}
case "$answer" in
[Yy]) tmux new -As "$session" ;;
*) ;; # skip
esac
fi
Fish (put in ~/.config/fish/config.fish)
# Offer to attach/create tmux on interactive SSH login (fish)
if status --is-interactive; and set -q SSH_CONNECTION; and not set -q TMUX; and test -t 1; and not set -q NO_AUTO_TMUX
set session main-(hostname -s)
printf "Attach to tmux session '%s'? [Y/n] (auto Y in 5s) " $session
# read one char with timeout (-t 5) and max chars (-n 1)
read -t 5 -n 1 answer
printf "\n"
if test -z "$answer" -o "$answer" = "Y" -o "$answer" = "y"
tmux new -As $session
end
end
Notes and tips
- Session naming: these snippets use
session="main-$(hostname -s)"
so each host gets its own session. Change “main” if you prefer something else. - tmux command:
tmux new -As name
will attach to the existing session or create it if missing. - To skip on a particular login: press
Ctrl-C
(before the timeout) or press ‘n’ when prompted. - To globally disable the prompt (e.g., from an automated login or a wrapper), set
NO_AUTO_TMUX
(e.g.,NO_AUTO_TMUX=1 ssh host
, orexport NO_AUTO_TMUX
in a wrapper env). - If you prefer the login shell to be replaced by tmux (so
Ctrl-D
exits the session), changetmux new -As "$session"
to exectmux new -As "$session"
in the snippet.