SSH Multiplexing: Speed Up SSH with ControlMaster

By 

•

Published on

•

8 min read

Three SSH terminal sessions sharing one encrypted connection to a server

When you connect to the same server repeatedly, such as when deploying code, running commands in multiple terminals, or transferring files back and forth, each new SSH connection needs a TCP handshake, key exchange, and authentication. On a fast local network this is barely noticeable, but over a high-latency connection or when scripting dozens of commands in a row, that overhead accumulates quickly.

SSH multiplexing lets you reuse an existing connection for additional sessions. Commands and file transfers that use the same control socket skip the initial connection setup and authentication, which can make repeated connections noticeably faster.

This guide explains how to configure SSH multiplexing and manage multiplexed connections from the command line.

How Multiplexing Works

When you open an SSH connection with multiplexing enabled, the SSH client creates a Unix socket file on your local machine at the path you specify. This client is called the master. Subsequent ssh, scp , and rsync commands that use the same control socket open separate channels over the existing connection instead of creating new TCP connections.

With ControlPersist enabled, the master can stay alive in the background after you close the first session. Sessions close independently, but they all depend on the master: if its network connection drops, every session using it is affected.

The examples below use the OpenSSH client on Linux or macOS. You need a remote account that you can already connect to with SSH. Multiplexing reduces connection setup time; it does not remove network latency from commands or increase the available bandwidth.

Configuring ControlMaster in ~/.ssh/config

To enable multiplexing, add a host block to your local SSH config file . First, make sure its directory exists and is accessible only to your user:

Terminal
mkdir -p ~/.ssh
chmod 700 ~/.ssh

Open ~/.ssh/config in a text editor and add the following block. Replace 203.0.113.10 and deployer with your server address and remote username:

~/.ssh/configini
Host deploy
    HostName 203.0.113.10
    User deployer
    ControlMaster auto
    ControlPath ~/.ssh/cm-%C
    ControlPersist 10m

The three directives work together:

  • ControlMaster auto - Reuse an existing master when one is available, or create a new one when it is not.
  • ControlPath ~/.ssh/cm-%C - Store the control socket in your private .ssh directory. The %C token hashes connection details into a short filename, avoiding long socket paths and separating connections to different hosts, ports, or users. In current OpenSSH, the hash includes the local hostname, remote hostname, port, remote username, and ProxyJump setting.
  • ControlPersist 10m - Keep the master running until it has had no client sessions for ten minutes. An open shell counts as a session even when you are not typing. Set this to yes to keep the master running indefinitely until you close it or the connection ends. The default, no, does not keep the master in the background after the initial session closes.

Connect using the alias you just configured:

Terminal
ssh deploy

The first connection creates the master. Open another terminal and run ssh deploy again to reuse it. You can also close the first shell and reconnect within ten minutes without repeating authentication.

To enable multiplexing for all hosts instead, place these defaults at the end of ~/.ssh/config:

~/.ssh/configini
Host *
    ControlMaster auto
    ControlPath ~/.ssh/cm-%C
    ControlPersist 10m

SSH uses the first value it finds for each setting, so put any host-specific exceptions before Host *. For the full option descriptions, see the OpenSSH configuration manual .

Enabling Multiplexing Per-Command

If you do not want to edit ~/.ssh/config, you can pass the settings directly on the command line with the -o flag. Using the private directory created above, connect with:

Terminal
ssh -o ControlMaster=auto -o 'ControlPath=~/.ssh/cm-%C' -o ControlPersist=10m user@example.com

Replace user@example.com with your remote account. Repeat the same command to reuse the connection. This is useful for testing settings before adding them to the config file, or for scripts that need their own connection settings.

You can pass the same socket path to rsync , which must be installed on both computers. This example copies the contents of ./dist/ to /var/www/, where matching files may be overwritten. Preview the transfer first with --dry-run:

Terminal
rsync -rv --dry-run -e 'ssh -o ControlPath=~/.ssh/cm-%C' ./dist/ user@example.com:/var/www/

The -r option copies directories recursively, and -v lists the files rsync would transfer. Remove --dry-run when you are ready to copy the files. The remote account needs write access to the destination. If the master is still running and the socket path matches, rsync reuses it; otherwise, SSH opens a normal connection.

Managing the Master Connection

The -O flag lets you send control commands to a running master without opening a new shell session. These examples use the deploy alias configured earlier. If you started the master with command-line options instead, pass the same ControlPath and destination to the control command.

To check whether a master is active for a host:

Terminal
ssh -O check deploy
output
Master running (pid=48231)

The output gives the process ID of the master that answered. If the socket is missing, SSH exits with a non-zero status and reports No such file or directory. This checks the local master process, not whether a remote command will succeed.

To stop accepting new multiplexed sessions while allowing existing sessions to continue, run:

Terminal
ssh -O stop deploy

New connections will establish their own master when ControlMaster auto is set. The old master removes its control socket, so it no longer answers ssh -O commands, but it can finish its existing sessions and expire according to ControlPersist.

To terminate a master immediately, use exit. This also disconnects sessions and file transfers that use it, so finish any work in those sessions first:

Terminal
ssh -O exit deploy

The ssh manual lists the available control commands.

Agent Forwarding with Multiplexing

Multiplexed sessions share the master’s SSH agent and X11 display when forwarding is requested. They cannot forward a different agent or display through the same master.

If you need agent forwarding, enable ForwardAgent yes in that host’s configuration so both the master and later sessions request it. For a command-line test, start a new connection with:

Terminal
ssh -A -o ControlMaster=auto -o 'ControlPath=~/.ssh/agent-%C' -o ControlPersist=10m deploy

The separate agent-%C path avoids reusing a master that was started without forwarding. Repeat the command for additional sessions. Passing -A to a later session alone does not enable forwarding on a master that was started without it.

Warning
Enable agent forwarding only on servers you trust. Someone with root access on the remote server can use your forwarded agent to authenticate with its loaded keys while the agent is available, even though the private keys stay on your computer. Once a master forwards your agent, every session that shares the connection can use it, including sessions you start without -A.

For more on forwarding and key management, see the SSH command guide .

Troubleshooting

New connections do not multiplex
Check the settings SSH actually uses for the host:

Terminal
ssh -G deploy | grep -E '^(hostname|user|port|controlmaster|controlpath|controlpersist) '

ssh -G prints the effective configuration without connecting. Confirm that controlmaster is auto and controlpath points inside your private .ssh directory. ControlPersist appears in seconds, so 10m shows as 600. A missing directory can cause a socket creation error. Create it with the commands in the configuration section before trying again.

For connection details, enable verbose output:

Terminal
ssh -v deploy

Look for messages about trying an existing master or creating the control socket.

ssh fails with “ControlPath too long”
The full socket path exceeds the Unix socket limit (104 bytes on macOS, 108 on Linux), and SSH refuses to connect instead of falling back to a normal connection. Keep the socket in a short directory such as ~/.ssh and use %C, which always produces a 40-character filename.

ssh -O check reports “No such file or directory”
The master may have expired, or the socket path does not match. Use the same host, port, username, and socket pattern that you used when starting it. Changing an alias alone does not necessarily change %C if the connection details remain the same.

Permission denied when opening the control socket
Inspect the owner and permissions of the exact socket shown by ssh -G. Run SSH as your regular user, and keep control sockets in a directory owned by that user. Deleting every cm-* socket can prevent other running masters from being reached, so avoid blanket cleanup commands.

A master is unresponsive after a network change or server restart
All sessions depend on the same network connection, which can fail after a reboot or network interruption. To open a fresh connection without using the socket, run:

Terminal
ssh -S none deploy

-S none disables connection sharing for this invocation. With ControlMaster auto, SSH can remove a stale socket when it finds that no process is listening. If manual cleanup is still needed, identify the exact socket and confirm its master is no longer running before removing it.

Additional sessions are refused
The server’s MaxSessions setting limits concurrent shell, command, and subsystem sessions on one connection. Its default is 10, and setting it to 1 prevents multiple sessions from sharing the connection. Close unused sessions or use ssh -S none deploy for a separate connection. See the server configuration manual for details.

Conclusion

Start with a short ControlPersist timeout on a host you use regularly, and check the master with ssh -O check before relying on it in scripts. To simplify the first connection too, set up key-based authentication and install your public key with ssh-copy-id .

Tags

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page