Fix SSH 'Connection Refused' After Server Reboot
The Error
After rebooting a server, SSH connections fail:
ssh: connect to host 192.168.1.50 port 22: Connection refused
Or from a client perspective:
ssh [email protected]
kex_exchange_identification: Connection closed by remote host
You cannot access the server remotely, and if it is a headless cloud instance, this can feel like losing the machine entirely.
Root Cause
"Connection refused" means the TCP connection reached the server but nothing is listening on the SSH port. This differs from "Connection timed out" (which means the packet never arrived). Common causes after a reboot:
- sshd service did not start. It may not be enabled for auto-start, or it failed due to a configuration error.
- Firewall rules were not persisted.
iptablesrules are ephemeral by default and can be lost on reboot. - SSH port was changed but the firewall only allows port 22.
- Host key corruption after an unclean shutdown.
- Cloud security groups or network ACLs were modified while the server was down.
Step-by-Step Fix
1. Verify the server is reachable
ping 192.168.1.50
If ping fails, the issue is network-level (wrong IP, security group, or the server is still booting). For cloud instances, check the console output in your cloud provider's dashboard.
2. Access the server via alternative means
- Cloud console: Use AWS EC2 Instance Connect, GCP Serial Console, or Azure Serial Console.
- KVM/IPMI: Use out-of-band management if available.
- Recovery mode: Boot into single-user or rescue mode from the hypervisor.
3. Check and start the sshd service
sudo systemctl status sshd
# If stopped or failed
sudo systemctl start sshd
# Enable auto-start on boot
sudo systemctl enable sshd
If sshd failed to start, check the logs:
journalctl -u sshd --no-pager -n 30
Common failure reasons include syntax errors in /etc/ssh/sshd_config. Validate the config:
sudo sshd -t
4. Check the SSH port
grep -i "^Port" /etc/ssh/sshd_config
If the port is non-standard (e.g., 2222), make sure you are connecting to the right port:
ssh -p 2222 [email protected]
And verify the service is listening:
sudo ss -tlnp | grep sshd
5. Check the firewall
# iptables
sudo iptables -L -n | grep -E "22|ssh"
# firewalld
sudo firewall-cmd --list-all
# ufw
sudo ufw status
If SSH is blocked, allow it:
# ufw
sudo ufw allow 22/tcp
# firewalld
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
# iptables (and persist)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables-save | sudo tee /etc/iptables/rules.v4
6. Fix host key issues
If host keys were corrupted during an unclean shutdown:
sudo rm /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart sshd
Clients will see a "host key changed" warning. They need to remove the old key:
ssh-keygen -R server.example.com
Prevention Tips
- Always enable sshd at boot. Run
systemctl enable sshdas part of your server provisioning. - Persist firewall rules. Use
iptables-persistent,firewalld, orufwwhich all persist rules across reboots by default. - Test reboot recovery. Periodically reboot non-production servers and verify SSH access comes back automatically.
- Keep a secondary access method. Configure serial console access or an out-of-band management interface so a broken sshd does not leave you locked out.
- Use configuration management. Tools like Ansible can ensure sshd configuration and firewall rules are consistently applied and correct after every reboot.
Was this article helpful?
Related Articles
Rocky Linux 9 Server Hardening: Security Baseline from First Boot
A production security baseline for Rocky Linux 9 — covering SELinux configuration, firewalld rules, SSH hardening, auditd, AIDE integrity checking, and CIS Benchmark compliance checks.
Ubuntu 24.04 LTS Server Setup for Production: From Bare Metal to Hardened Baseline
A complete walkthrough for turning a fresh Ubuntu 24.04 LTS installation into a production-ready server — from initial SSH lockdown to swap configuration and kernel parameter tuning.
Fix Linux 'Too Many Open Files' System-Wide
Resolve the Linux 'too many open files' error by increasing file descriptor limits at the system, user, and process level.
Linux Networking Commands: Cheat Sheet
Linux networking commands cheat sheet for troubleshooting — interfaces, routing, DNS lookups, connections, iptables firewalls, and tcpdump packet capture.
Linux Networking & Firewall: Configuration and Troubleshooting
Configure Linux network interfaces, set up iptables/nftables/firewalld rules, troubleshoot connectivity with ss, ip, dig, and tcpdump, and secure your servers.
Linux Performance Troubleshooting: CPU, Memory, Disk, and Network
Diagnose Linux performance bottlenecks with top, htop, vmstat, iostat, sar, iotop, and strace — a systematic approach to finding and fixing issues.
More in Linux
View all →Linux Control Groups (cgroups V2): Limiting CPU And Memory For Production Workloads
If you're running production workloads without cgroup constraints, you're one runaway process away from a bad day. Here's everything you need to configure...
Alpine Linux apk Reference: Package Management, Repositories, and System Administration
A complete reference for Alpine Linux's apk package manager — adding packages, managing repositories, pinning versions, building custom packages, and running Alpine as a minimal server OS.
Alpine Linux for Docker: Building Minimal, Secure Container Images
How to use Alpine Linux as a Docker base image effectively — understanding musl libc compatibility, multi-stage builds, layer optimization, and the security trade-offs versus glibc-based distributions.
openSUSE MicroOS and Transactional Updates: Atomic System Updates with Btrfs Snapshots
How openSUSE's transactional-update and Btrfs snapshot integration enables atomic, rollback-safe system updates — and how MicroOS takes this to a fully immutable, container-optimized OS.