Using Tmux for Persistent Sessions on a VPS: Session Management, Scripting, and Troubleshooting

SSH sessions drop when your connection drops. A long-running database migration, a package update, or a file transfer that gets interrupted means starting over. Tmux keeps your session alive on the server independently of your SSH connection. This article covers session management, scripting with tmux for automation, and solving common problems that trip up new users.

Installation and Basic Concepts

# Ubuntu/Debian
sudo apt install tmux -y

# Verify
which tmux && tmux -V

Three concepts you need to understand before using tmux:

ConceptDefinitionAnalogy
SessionA collection of windows managed togetherA project workspace
WindowA single screen within a session (like a browser tab)Browser tab
PaneA split within a windowSplit screen in an IDE

You can have multiple sessions, each with multiple windows, each with multiple panes. Sessions persist across SSH disconnects — reattach and everything is exactly as you left it.

Session Management: The Essential Commands

These are the commands you will use every day. Memorize the first three:

# Start a new session (named sessions are easier to track)
tmux new -s webserver

# Detach from current session (keeps it running)
Ctrl+b, d

# List active sessions
tmux ls

# Reattach to a session
tmux attach -t webserver

# Kill a session
tmux kill-session -t webserver

# Rename a session
tmux rename-session -t old-name new-name

Window and Pane Management

Windows and panes let you organize multiple tasks within one SSH connection. Instead of opening 3 SSH terminals, you open 3 tmux windows in one session.

ActionShortcutDescription
New windowCtrl+b, cCreate a new window
Next windowCtrl+b, nSwitch to next window
Previous windowCtrl+b, pSwitch to previous window
Rename windowCtrl+b, ,Rename current window
Split verticallyCtrl+b, %Split pane vertically
Split horizontallyCtrl+b, "Split pane horizontally
Navigate panesCtrl+b, arrow keysMove between panes
Close paneCtrl+b, xClose current pane
Zoom paneCtrl+b, zToggle pane fullscreen

Productivity Configuration: .tmux.conf

The default tmux prefix (Ctrl+b) is awkward. Most users remap it to Ctrl+a (closer to the home row). Here is a practical ~/.tmux.conf that improves the defaults:

# ~/.tmux.conf
# Remap prefix to Ctrl+a
unbind C-b
set -g prefix C-a
bind C-a send-prefix

# Split panes using | and -
bind | split-window -h
bind - split-window -v

# Vim-style pane navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# Mouse support (scroll, select pane, resize)
set -g mouse on

# Start window numbering at 1
set -g base-index 1
setw -g pane-base-index 1

# Increase scrollback buffer
set -g history-limit 10000

# Status bar
set -g status-bg black
set -g status-fg white
set -g status-left '#[fg=green]#S '
set -g status-right '#[fg=yellow]%Y-%m-%d %H:%M '

# Reload config without restarting
bind r source-file ~/.tmux.conf \; display "Config reloaded"

After saving, reload with Ctrl+a, r (or restart tmux).

Scripting with tmux: Automating Multi-Window Workflows

Tmux is scriptable. You can create a session with multiple windows pre-configured for a specific project:

#!/bin/bash
# ~/bin/tmux-dev.sh - Start a development workspace
SESSION="dev"

# If session exists, attach to it
if tmux has-session -t "$SESSION" 2>/dev/null; then
    tmux attach -t "$SESSION"
    exit 0
fi

# Create a new session with first window
tmux new-session -d -s "$SESSION" -n "editor"

# Window 1: editor (already created)
tmux send-keys -t "$SESSION:editor" "cd ~/projects/myapp && nvim ." C-m

# Window 2: server logs
tmux new-window -t "$SESSION" -n "logs"
tmux send-keys -t "$SESSION:logs" "cd ~/projects/myapp && tail -f logs/app.log" C-m

# Window 3: git
tmux new-window -t "$SESSION" -n "git"
tmux send-keys -t "$SESSION:git" "cd ~/projects/myapp && git status" C-m

# Window 4: database
tmux new-window -t "$SESSION" -n "db"
tmux send-keys -t "$SESSION:db" "sudo -u postgres psql myapp_db" C-m

# Window 5: monitoring
tmux new-window -t "$SESSION" -n "monitor"
tmux split-window -h -t "$SESSION:monitor"
tmux send-keys -t "$SESSION:monitor.1" "htop" C-m
tmux send-keys -t "$SESSION:monitor.2" "watch -n 2 'df -h / && free -h'" C-m

# Attach to the session
tmux attach -t "$SESSION"

Run this script on any SSH login and your entire development workspace is restored in seconds.

Copy Mode and Scrollback

With mouse support enabled, scrolling with your mouse wheel works out of the box. For keyboard-based copy/paste, use copy mode:

  • Enter copy mode: Ctrl+a, [
  • Navigate: Use arrow keys, Page Up/Down, or Ctrl+u/Ctrl+d for half-page scroll
  • Start selection: Press Space, then move cursor
  • Copy selection: Press Enter
  • Paste: Ctrl+a, ]

Troubleshooting Common Issues

Scrolling produces garbage characters

This happens when mouse support is not enabled. Add set -g mouse on to your ~/.tmux.conf and reload. If you are using tmux inside tmux (nested sessions), the inner session steals mouse events — use a different prefix for the inner session.

Session lost after server reboot

Tmux sessions are in-memory. A server reboot destroys them. Use tmux-resurrect (a tmux plugin) to save and restore sessions across reboots:

# Install tmux plugin manager
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

# Add to ~/.tmux.conf
set -g @plugin 'tmux-plugins/tmux-resurrect'

# Prefix + Ctrl+s to save
# Prefix + Ctrl+r to restore

“.tmux.conf not being read”

Check that the file is at ~/.tmux.conf (not ~/.tmux.conf.d/). Run tmux source-file ~/.tmux.conf to apply changes without restarting the session. If the config has syntax errors, tmux will print them to stderr.

Panes resize unpredictably

When you detach and reattach from a different terminal size, tmux resizes panes to fit the new dimensions. Use set -g window-size latest to make the newest client size the reference, or set -g window-size manual to lock pane sizes.

Performance Considerations on a Small VPS

Tmux itself is lightweight — a single session consumes about 5–10 MB of RAM. However, the processes running inside tmux consume memory. If you have 10 sessions with htop, tail -f, and a database shell running in each, the total process overhead can reach 200–500 MB. On a 1 GB VPS, limit yourself to 2–3 active sessions and close unused windows.

ComponentMemory per instanceNotes
tmux server (daemon)~5 MBShared across all sessions
Each session~2–3 MBOverhead for session state
Each window~1 MBTerminal buffer and state
htop~15 MBInteractive process monitor
tail -f~2 MBLog tailing
Vim/Neovim (with plugins)~50–100 MBDepends on plugins loaded

Persistent Sessions for Long-Running Tasks

For unattended long-running tasks (database migrations, large file transfers, package builds), use tmux in combination with a log file:

# Start a tmux session for a long import
tmux new -s import

# Inside the session, run the import with logging
mysql -u root mydb < /backup/dump.sql 2>&1 | tee /var/log/import.log

# Detach (Ctrl+a, d)

# Check progress from another SSH session
tmux capture-pane -t import -p | tail -5

# Or tail the log
tail -f /var/log/import.log

This pattern is safer than nohup or screen because you can reattach to see the exact state of the process, including any interactive prompts that might be waiting for input.

When you need a VPS robust enough to run multiple development sessions, database shells, and monitoring tools simultaneously, compare VPS plans with adequate RAM for your workflow. For more server management tips, browse our VPS tutorials.

Leave a Reply