SSH Broken Pipe Error: Causes and Fixes

You connect to a server, leave the terminal idle for a few minutes, and return to find the session frozen or closed with client_loop: send disconnect: Broken pipe. The login worked, but something between the client and server discarded the quiet connection, or the network disappeared long enough for SSH to give up.
A common cause is an idle timeout on a router, firewall, VPN, or NAT gateway. A Wi-Fi interruption or a server reboot can produce the same symptom. In this guide, we will explain how to configure SSH keepalives, find the cause of a disconnect, and protect long-running commands.
Quick Reference
For a printable quick reference, see the SSH cheatsheet .
| Task | Setting or command |
|---|---|
| Test client keepalives once | ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@example.com |
| Configure client keepalives | ServerAliveInterval 60 and ServerAliveCountMax 3 |
| Show the effective client settings | ssh -G example.com | grep -i serveralive |
| Debug a disconnect | ssh -vvv user@example.com |
| Validate the server configuration | sudo sshd -t |
| Read SSH server logs on Ubuntu or Debian | sudo journalctl -u ssh.service -u ssh.socket -b |
| Keep a command alive after disconnecting | Run it inside tmux |
Test SSH Keepalives from the Client
Start with a one-time connection that sends a keepalive after 60 seconds without incoming data:
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@example.comServerAliveInterval=60 tells the client to send a message through the encrypted SSH channel when it has received no data for 60 seconds. This exchange can prevent a router or firewall from dropping an idle connection. ServerAliveCountMax=3 sets the limit for unanswered requests, so an unresponsive server is detected after roughly three minutes instead of leaving the session hanging indefinitely.
Leave this test session idle longer than it would normally survive. If it remains connected, make the settings permanent on the client.
The interval must be shorter than the network device’s idle timeout. If the connection drops in less than a minute, try ServerAliveInterval=15 instead. With a count of 3, that also reduces the time allowed for an unresponsive connection to roughly 45 seconds.
Configure Keepalives in ~/.ssh/config
On your local machine, create the ~/.ssh directory if it does not exist, set its permissions, and open the SSH client configuration file:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/configAdd the settings to the host that drops connections. If you already have a block for that host, update it instead of adding a second one:
Host production
HostName example.com
User deploy
ServerAliveInterval 60
ServerAliveCountMax 3You can then connect with the short host name:
ssh productionThe host-specific block is the safer starting point because it changes only the troublesome connection. If several networks and servers have the same problem, put the settings in a wildcard block at the bottom of the file:
Host *
ServerAliveInterval 60
ServerAliveCountMax 3OpenSSH uses the first value it finds for each setting. Put specific host blocks before Host * so the defaults do not override them.
Protect the file and inspect the values OpenSSH will use for a host:
chmod 600 ~/.ssh/config
ssh -G production | grep -i serveraliveFor the configuration above, the output should be:
serveralivecountmax 3
serveraliveinterval 60The values confirm that keepalives are enabled at a 60-second interval with a limit of three unanswered requests. Our guide to the SSH config file covers host aliases, keys, ports, and precedence in more detail.
Check Why the Connection Closed
Keepalives can prevent idle network timeouts, but they cannot keep a session connected through a server reboot or a network outage. Run the client with verbose logging when the disconnect is repeatable:
ssh -vvv user@example.comLook at the last lines after the failure. Broken pipe means SSH could no longer write to the connection; it does not tell you what caused the failure.
Once keepalives are enabled, a connection that stops answering ends with a different message:
Timeout, server example.com not responding.The client sent ServerAliveCountMax keepalives without receiving a reply, then closed the session. The keepalives worked; the network path or the server stopped answering. Compare the client messages with the server logs at the same timestamp.
On Ubuntu and Debian, inspect the current boot logs for both the service and socket units:
sudo journalctl -u ssh.service -u ssh.socket -bOn Fedora, RHEL, and derivatives, use the sshd unit:
sudo journalctl -u sshd.service -bUse sudo journalctl -b to check the wider system log for an out-of-memory event or other failures around the same timestamp. A normal SSH configuration reload does not usually end established sessions. If every client disconnects at once, check the server and the network they share. If only one laptop drops when it changes Wi-Fi networks or reconnects to a VPN, check that laptop’s network connection first.
Configure Server-Side Keepalives
When you administer the server, you can configure it to send keepalives to quiet clients. These settings go on the remote server, not in your local ~/.ssh/config.
First, check whether /etc/ssh/sshd_config includes a directory for configuration snippets:
sudo grep -nE '^[[:space:]]*Include[[:space:]]' /etc/ssh/sshd_configOn Ubuntu, the default configuration includes Include /etc/ssh/sshd_config.d/*.conf. If your server includes that path, open a drop-in file:
sudo nano /etc/ssh/sshd_config.d/10-keepalive.confAdd the following settings:
ClientAliveInterval 60
ClientAliveCountMax 3If your configuration does not include this directory, edit the existing global settings in /etc/ssh/sshd_config instead, before any Match blocks. As with the client configuration, the first value obtained for most settings takes precedence.
ClientAliveInterval tells the server to request a response after receiving no data from the client for the specified interval. ClientAliveCountMax controls how many unanswered requests it permits before disconnecting the client. A healthy client answers automatically, even when you are not typing. These options do not impose a timeout for an idle user.
Validate the configuration before applying it:
sudo sshd -tNo output means the configuration passed the check. If an error appears, correct it before reloading SSH. Then inspect the effective keepalive settings:
sudo sshd -T | grep -E '^clientalive(interval|countmax) 'The output should show clientaliveinterval 60 and clientalivecountmax 3. If the values differ, check for an earlier setting or a drop-in file that is not being included.
If the server uses Match rules, plain sshd -T does not show the settings for a particular login. Use sudo sshd -T -C user=deploy,addr=198.51.100.10,host=client.example.com, replacing the examples with the remote username and the client’s source address and hostname as seen by the server.
Keep the current SSH session open, then reload the service. On Ubuntu and Debian, run:
sudo systemctl reload sshOn Fedora, RHEL, and derivatives, run:
sudo systemctl reload sshdThe new settings apply to new connections. Open a second terminal, connect again, and test the session before closing the original one. Client-side keepalives are usually enough, so you do not need to configure both ends for every connection.
ServerAliveInterval vs TCPKeepAlive
OpenSSH enables TCPKeepAlive by default, but operating-system TCP probes are not a replacement for ServerAliveInterval. TCP keepalives commonly wait much longer before sending anything, and their timing is controlled by kernel settings. SSH server-alive messages travel inside the encrypted connection and use the interval you specify.
Do not disable TCPKeepAlive as a first fix. Add ServerAliveInterval for predictable application-level checks, then leave the TCP behavior at its default unless you have a measured reason to change it.
Protect Long-Running Commands with tmux
A keepalive can reduce idle disconnects, but it cannot preserve a connection through every network change or a laptop losing power. To protect a long-running command, start it inside a tmux session on the server after logging in:
tmux new -s maintenanceStart the command inside that session. To detach, press Ctrl+B, release both keys, then press d. If SSH drops, reconnect and attach to the existing session:
tmux attach -t maintenanceThe program keeps running in the server’s tmux session when the SSH connection closes. This does not protect it from a server reboot or the tmux session being terminated. See the tmux getting-started guide
for installation, window, pane, and session commands.
Troubleshooting
The connection still drops with ServerAliveInterval set
Run ssh -G production | grep -i serveralive to confirm the effective settings. If you use SSH connection sharing
, test with ssh -S none production to open a fresh connection instead of reusing a master connection with older settings. If the values are correct, compare the disconnect time with the client and server logs. Keepalives cannot prevent a full network outage or a server reboot.
SSH disconnects while output is actively printing
An idle timeout is unlikely because the connection already carries traffic. Check Wi-Fi, VPN, and packet loss on the client, then check the server logs for resource exhaustion or terminated SSH processes.
The server closes sessions after an exact fixed period
Check for ChannelTimeout in sudo sshd -T output on OpenSSH versions that support it, adding the -C options described above when the server uses Match rules. Unlike client-alive probes, a setting such as ChannelTimeout session=5m can close an inactive session even when the client is responding. Bash can also log out an idle shell through its TMOUT variable. Run printf '%s\n' "${TMOUT-unset}" in the remote Bash shell to inspect it, and check with the administrator before changing an intentional timeout policy.
The error appears immediately during login
Keepalive settings will not help an authentication or listening-port failure. Use the SSH connection refused guide
for network and service errors, or the SSH permission denied guide
for key authentication failures.
Conclusion
Start with client keepalives and check the logs if the connection still drops. Before starting a long-running job, open a tmux session on the server so you can reconnect to it after a network interruption.
Tags
Linuxize Weekly Newsletter
A quick weekly roundup of new tutorials, news, and tips.
About the authors

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