How to automatically start tmux on SSH session?

Server-side configuration:

To automatically start tmux on your remote server when ordinarily logging in via SSH (and only SSH), edit the ~/.bashrc of your user or root (or both) on the remote server accordingly:

if [[ -n "$PS1" ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" ]]; then
  tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux
fi

This command creates a tmux session called ssh_tmux if none exists, or reattaches to a already existing session with that name. In case your connection dropped or when you forgot a session weeks ago, every SSH login automatically brings you back to the tmux-ssh session you left behind.

Connect from your client:

Nothing special, just ssh user@hostname.


Alright, I found a mostly satisfactory solution. In my local ~/.bashrc, I wrote a function:

function ssh () {/usr/bin/ssh -t "$@" "tmux attach || tmux new";}

which basically overwrites the ssh terminal function to call the built-in ssh program with the given arguments, followed by "tmux attach || tmux new".

(The $@ denotes all arguments provided on the command line, so ssh -p 123 user@hostname will be expanded to ssh -t -p 123 user@hostname "tmux attach || tmux new")

(The -t argument is equivalent to RequestTTY Force and is necessary for the tmux command.)


Connect:

ssh user@host -t "tmux new-session -s user || tmux attach-session -t user"

During session:

Use Ctrl+d to finish session (tmux window closes) or Ctrl+b d to temporary detach from session and connect to it again later.

Remember! If your server restarted session lost!

When you are inside tmux anytime you can use Ctrl+b s to see sessions list and switch current to another.

Fix your .bashrc:

I recommend you to define universal function in your .bashrc:

function tmux-connect {
    TERM=xterm-256color ssh -p ${3:-22} $1@$2 -t "tmux new-session -s $1 || tmux attach-session -t $1"
}

It uses 22 port by default. Define your fast-connect aliases too:

alias office-server='tmux-connect $USER 192.168.1.123'
alias cloud-server='tmux-connect root my.remote.vps.server.com 49281'

Login without password:

And if you don't want to type password everytime than generate .ssh keys to login automatically:

ssh-keygen -t rsa
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa

Put your public key to the remote host:

ssh-copy-id -p <port> user@hostname

Additional tips:

If you want to use temporary session-id which corresponds with a local bash session use as tmux id:

SID=$USER-$BASHPID
ssh user@host -t "tmux new-session -s $SID || tmux attach-session -t $SID"

Don't do this on the server-side!

That is potentially dangerous because you can end up being locked-out of the remote machine. And no shell hacks / aliases / etc. are required, either.

Instead...

... make use of ~/.ssh/config like so:

tmux 3.1 or newer¹ on the remote machine

Into your local ~/.ssh/config, put²:

Host myhost
  Hostname host
  User user
  RequestTTY yes 
  RemoteCommand tmux new -A -s foobar
  • As pointed out by @thiagowfx, this has the side effect of making it impossible to use, e.g. ssh myhost ls /tmp and should therefore not be used with Host * ... what I like to do is to have a Host myhost section with RemoteCommand tmux ... and then in addition to that I'll have a Host MYHOST section without it.
  • Instead of RequestTTY yes you could call ssh with the -t switch; thank you, @kyb.
  • Off-topic, but if you're dealing with non-ASCII characters, I'd recommend to change that into tmux -u … for explicitly enabling Unicode support even on machines that don't have the proper environment variables set.

tmux 3.0a or older on the remote machine

Almost the same as above, but change the last line to³:

  RemoteCommand tmux at -t foobar || tmux new -s foobar

¹ repology.org has a list of distros and their tmux versions

² new is short for new-session.

³ at is short for attach-session.


Only if, for some reason, you really, really can't do it client-side:

Using the remote's authorized_keys file

If you would rather not have an ~/.ssh/config file for whatever reason, or want the remote machine to force the connecting machine to connect to / open the session, add this to your remote ~/.ssh/authorized_keys:

command="tmux at -t foobar || tmux new -s foobar" pubkey user@client

This will, of course, work from all clients having the corresponding private key installed, which some might consider an upside –– but: should anything go wrong, it might not be possible to connect anymore without (semi-)physical access to the machine!

Tags:

Ssh

Tmux