The SSH connection unexpectedly closed because the TCP connection was terminated. This usually happens when an idle session times out or network connectivity is lost.
The 'Write failed: Broken pipe' error occurs when the SSH client tries to send data to the server, but the underlying TCP connection has been closed. A broken pipe means the receiving end (the SSH server) has closed the connection without the client expecting it. This typically results from inactivity timeout, network interruptions, firewall rules terminating idle connections, or server-side SSH daemon configuration.
The ServerAliveInterval setting tells your SSH client to send keep-alive packets to the server at regular intervals, preventing idle timeout disconnections.
For a single connection:
ssh -o ServerAliveInterval=60 user@hostFor all future connections, edit your ~/.ssh/config file:
Host *
ServerAliveInterval 60
ServerAliveCountMax 120This tells SSH to send a keep-alive packet every 60 seconds, and disconnect only after 120 failed attempts (120 minutes of no response).
TCPKeepAlive works at the TCP layer to prevent connection drops before SSH keep-alives kick in.
Add to ~/.ssh/config:
Host *
TCPKeepAlive yes
ServerAliveInterval 60
ServerAliveCountMax 120TCPKeepAlive yes is usually the default, but explicitly setting it ensures TCP-level keep-alives are enabled.
If the broken pipe happens despite client-side settings, or if you administer the SSH server, configure server-side keep-alives.
Edit /etc/ssh/sshd_config on the server:
ClientAliveInterval 120
ClientAliveCountMax 720This tells the SSH daemon to:
- Send a keep-alive packet every 120 seconds
- Only drop the connection after 720 failed attempts (about 24 hours)
After editing, restart the SSH daemon:
sudo systemctl restart sshd
# or on older systems:
sudo service ssh restartVerify your settings are working by leaving an SSH session idle and checking it doesn't disconnect.
Check client configuration:
ssh -G user@host | grep -i aliveCheck server configuration (requires server access):
sudo grep -i ClientAlive /etc/ssh/sshd_configConnect and wait 5+ minutes without activity. If it disconnects, proceed to the next step.
If the issue persists despite proper SSH keep-alive settings, the problem may be an intermediary network device (firewall, NAT, proxy, or ISP).
Diagnose with verbose output:
ssh -vvv user@hostWatch the logs for timeout messages. If the disconnect happens at a consistent interval (e.g., every 15 minutes), it's likely a firewall or ISP setting.
Solutions:
- Contact your ISP or network administrator about idle connection timeouts
- Adjust firewall rules to increase timeout thresholds
- For cloud environments (AWS, Azure, GCP), check security group rules and network ACLs
- Consider using an SSH jumphost or bastion with longer timeout settings
If keep-alive settings don't solve the problem, use tmux or screen to maintain a persistent session that survives SSH disconnects.
Using tmux:
# Create a new session
tmux new-session -s work
# Detach (keeps running)
Ctrl+B D
# Reconnect later
tmux attach-session -t workUsing screen:
# Create a new session
screen -S work
# Detach (keeps running)
Ctrl+A D
# Reconnect later
screen -r workWith tmux/screen, your session persists on the server even if the SSH connection breaks.
Idle timeout sources: The broken pipe error can originate from multiple layers: (1) The SSH server itself (sshd_config settings), (2) A NAT device or firewall between you and the server, (3) An HTTP proxy if connecting through one, (4) Your ISP's CGNAT (Carrier-Grade NAT) timeout, typically 30-60 minutes. If you're behind a proxy, check the Apache reqtimeout_module setting, which may be terminating connections aggressively.
Root cause identification: The key to solving this is determining where the connection closes. Use ssh -vvv user@host to see detailed logs. If sshd logs (in /var/log/auth.log or /var/log/secure) show the connection was closed cleanly, it's likely client-side or firewall timeout. If logs are silent, the network device likely closed the connection.
UsePrivilegeSeparation note: On very old SSH servers (pre-OpenSSH 7.0), some users reported success by adjusting the UsePrivilegeSeparation setting in sshd_config, though this is rarely needed on modern systems.
Long-lived connections: For truly long-lived or interactive sessions, combine ServerAliveInterval with tmux/screen. This provides both keep-alive protection and session recovery if the connection does eventually drop.
Load key "/home/user/.ssh/id_rsa": invalid format
How to fix 'Load key invalid format' in SSH
Bad owner or permissions on /home/user/.ssh/config
How to fix "Bad owner or permissions on .ssh/config" in SSH
Error connecting to agent: Connection refused
How to fix "Error connecting to agent: Connection refused" in SSH
Connection closed by UNKNOWN port 65535
How to fix 'Connection closed by UNKNOWN port 65535' in SSH
Offending ECDSA key in /home/user/.ssh/known_hosts:line
How to fix "Offending ECDSA key in known_hosts" in SSH