For our Blog Visitor only Get Additional 3 Month Free + 10% OFF on TriAnnual Plan YSBLOG10
Grab the Deal

How to Fix SSH on Linux Server? Practical Recovery Guide

To fix SSH on a Linux server, verify network reachability, confirm the SSH daemon (sshd) is running, ensure the correct port is open in the firewall and cloud security groups, inspect logs for errors, validate sshd_config syntax and permissions, then safely restart the service. If locked out, use a provider console or rescue mode to recover access.

Secure Shell (SSH) is the lifeline to any Linux server. When it breaks, work stops. In this guide, I’ll show you how to fix SSH on a Linux server step-by-step—covering connection timeouts, “Permission denied (publickey)”, service failures, misconfigurations, SELinux, Fail2ban, and cloud firewall issues—using safe, proven methods from years of server administration.

Whether you manage a VPS, dedicated server, or cloud instance, these checks will help you diagnose and resolve SSH problems quickly without risking lockouts. If you use a managed VPS from YouStable, our support can also restore access and harden your SSH configuration for you.

Quick Checks for Common SSH Errors

1) Confirm network reachability and DNS

If you can’t connect at all, ensure the server is online and the hostname resolves correctly.

# From your local machine
ping -c3 your-server.com
dig +short A your-server.com
traceroute your-server.com  # or mtr your-server.com

If DNS is wrong, connect via the server’s public IP instead of the hostname and fix DNS later.

2) Test port reachability (default 22)

Check if the SSH port is open and reachable. Some admins move SSH to a non-standard port.

nc -vz your-server.com 22
# or
nmap -p 22 your-server.com

If connection is refused or filtered, jump ahead to firewall and cloud security group fixes.

3) Verify the SSH service (sshd) is running

Use the provider’s web/VNC console or a KVM to run commands on the box if you’re locked out.

# Systemd-based distros (Ubuntu, Debian, RHEL, CentOS, AlmaLinux, Rocky)
sudo systemctl status ssh     # Debian/Ubuntu service name: ssh
sudo systemctl status sshd    # RHEL/CentOS/Alma/Rocky service name: sshd

# Start and enable if needed
sudo systemctl enable --now sshd || sudo systemctl enable --now ssh

# Check listening port
sudo ss -tlnp | grep sshd     # or: sudo netstat -tlnp | grep sshd

If it isn’t listening, review logs and configuration next.

Fix Connection Refused or Timeout

Ensure sshd is listening on the correct port

Check and correct the Port directive in /etc/ssh/sshd_config, then test configuration before restarting.

sudo grep -i '^Port' /etc/ssh/sshd_config
# Test config (no output = OK)
sudo sshd -t
# Restart service
sudo systemctl restart sshd || sudo systemctl restart ssh
# Confirm listening port
sudo ss -tlnp | grep sshd

If you changed the port, remember to specify it when connecting: ssh -p 2222 user@host.

Open the port in the server firewall (UFW, firewalld, iptables)

Allow SSH in your host firewall. Replace 22 with your custom port if changed.

# UFW (Ubuntu)
sudo ufw allow 22/tcp
sudo ufw status

# firewalld (RHEL/Alma/Rocky/CentOS Stream/Fedora)
sudo firewall-cmd --permanent --add-service=ssh
# If using a non-standard port:
# sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

# iptables (legacy)
sudo iptables -I INPUT -p tcp --dport 22 -j ACCEPT
sudo service iptables save || sudo iptables-save | sudo tee /etc/iptables.rules

Check cloud security groups and provider firewalls

On AWS, GCP, Azure, or many VPS providers, a network firewall may block SSH regardless of the OS firewall. Allow TCP 22 (or your custom port) from your IP or trusted ranges in the provider’s console.

Review Fail2ban, CSF, and intrusion tools

If you tried many times, your IP may be banned. Unban or temporarily disable to test.

sudo fail2ban-client status sshd
sudo fail2ban-client unban <your.ip.address>

# CSF (ConfigServer Firewall)
sudo csf -g <your.ip.address>    # find
sudo csf -dr <your.ip.address>   # remove/deny rule
sudo csf -tr <your.ip.address>   # temporary allow

Fix Authentication Failures

Password vs key authentication

Know what’s allowed by sshd_config. Many servers disable passwords for security and require SSH keys.

sudo egrep -i '^(PasswordAuthentication|PubkeyAuthentication|PermitRootLogin)' /etc/ssh/sshd_config
sudo sshd -T | egrep 'passwordauthentication|pubkeyauthentication|permitrootlogin'

If you must temporarily enable passwords to restore access, set PasswordAuthentication yes, restart SSH, log in, then re-enable keys and disable passwords again as a best practice.

Fix “Permission denied (publickey)” by correcting permissions

SSH will ignore keys if file permissions or ownership are too open or incorrect.

# As the target user (or via sudo specifying user paths)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh
ls -ld ~/.ssh; ls -l ~/.ssh/authorized_keys

# Confirm the server sees your key attempt (on the client)
ssh -vvv user@server

Ensure your public key (~/.ssh/id_rsa.pub or id_ed25519.pub) is in ~/.ssh/authorized_keys on the server, exactly one line per key.

Reset a user password or add a key via console

If completely locked out, use the provider console/KVM or rescue mode to add your key or reset a password safely.

# Create user and add a key (replace <user> and pubkey)
sudo useradd -m -s /bin/bash <user>
sudo mkdir -p /home/<user>/.ssh
echo "ssh-ed25519 AAAA... your_email" | sudo tee /home/<user>/.ssh/authorized_keys
sudo chown -R <user>:<user> /home/<user>/.ssh
sudo chmod 700 /home/<user>/.ssh
sudo chmod 600 /home/<user>/.ssh/authorized_keys
sudo usermod -aG sudo <user>  # Debian/Ubuntu
sudo usermod -aG wheel <user>  # RHEL/Alma/Rocky

Root login policies

For security, PermitRootLogin should be no or prohibit-password. Use a sudo-capable user to administer. If you must enable root temporarily, revert after recovery and secure with keys or 2FA.

Fix and Safeguard sshd_config

Create backups and validate syntax

Always back up before editing. Validate syntax to avoid lockouts.

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M)
sudo nano /etc/ssh/sshd_config   # or your editor
sudo sshd -t                     # syntax check
sudo systemctl restart sshd || sudo systemctl restart ssh

Know effective settings and rollback plan

List effective settings and keep an active session while restarting to avoid being locked out.

sudo sshd -T | less
# If broken, revert quickly:
sudo mv /etc/ssh/sshd_config.bak.* /etc/ssh/sshd_config
sudo systemctl restart sshd || sudo systemctl restart ssh

Fix host key and known_hosts mismatches

If you reinstalled or rebuilt, the server’s host keys may change, causing client warnings. Verify fingerprints via console, then update known_hosts.

# On server (list fingerprints)
sudo ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub
sudo ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key.pub

# On client (remove old entry and reconnect)
ssh-keygen -R your-server.com
ssh user@your-server.com

SELinux or AppArmor Interference

SELinux port and context issues (RHEL/Alma/Rocky/CentOS/Fedora)

If you change the SSH port, allow it in SELinux. Also restore file contexts for user SSH directories.

# Permit non-standard SSH port
sudo semanage port -l | grep ssh
sudo semanage port -a -t ssh_port_t -p tcp 2222 2>/dev/null || \
sudo semanage port -m -t ssh_port_t -p tcp 2222

# Restore contexts
sudo restorecon -Rv /etc/ssh /home/*/.ssh

# Temporary test (not a fix): set SELinux permissive
sudo setenforce 0  # Remember to re-enable: setenforce 1

AppArmor profiles (Ubuntu/Debian)

Verify the sshd AppArmor profile isn’t denying required paths. Check dmesg or logs and adjust or temporarily set to complain mode only for testing.

sudo aa-status
# Switch to complain mode for testing
sudo aa-complain /etc/apparmor.d/usr.sbin.sshd

Logs and Deep Diagnostics

Read server logs for SSH errors

Log messages often pinpoint the root cause: bad permissions, banned IP, config syntax, or missing keys.

sudo journalctl -u ssh -e     # Debian/Ubuntu
sudo journalctl -u sshd -e    # RHEL/Alma/Rocky
sudo tail -f /var/log/auth.log /var/log/secure

Temporarily increase logging for clarity

Set LogLevel DEBUG in sshd_config, restart, reproduce the issue, collect logs, then revert to INFO.

sudo sed -i 's/^#\?LogLevel.*/LogLevel DEBUG/' /etc/ssh/sshd_config
sudo systemctl restart sshd || sudo systemctl restart ssh
# After diagnosing:
sudo sed -i 's/^LogLevel.*/LogLevel INFO/' /etc/ssh/sshd_config
sudo systemctl restart sshd || sudo systemctl restart ssh

Use client-side debug output

Run verbose mode to see key negotiation, auth methods, and disconnect reasons.

ssh -vvv -p 22 user@your-server.com

Emergency Access and Recovery Options

Use cloud provider console or KVM

Most providers offer a built-in console you can open from the dashboard to regain terminal access even if SSH is down. Fix firewall rules, revert sshd_config, or restart the service from there.

Boot into rescue/single-user mode

In rescue mode, mount your root filesystem, chroot if needed, and repair SSH configuration, users, keys, and firewall without the network actively blocking you.

# Common recovery tasks
sudo nano /etc/ssh/sshd_config
sudo sshd -t
sudo systemctl restart sshd || sudo systemctl restart ssh
# Regenerate host keys if missing
sudo ssh-keygen -A
# Reinstall server package if corrupted
sudo apt-get update && sudo apt-get install --reinstall openssh-server
sudo dnf reinstall -y openssh-server

Hardening SSH After You Fix It

Use key-only authentication and disable passwords

Keys are safer and stop most brute-force attacks. Set PubkeyAuthentication yes and PasswordAuthentication no, confirm access with a second session, then restart sshd.

Optional: Change the SSH port (security by reduction of noise)

Moving from 22 to a high port reduces bot noise but isn’t a true defense. If you change it, update SELinux, host firewall, and cloud security groups consistently.

Add Fail2ban and 2FA for stronger protection

Enable Fail2ban to throttle brute-force attempts. Consider 2FA (e.g., Google Authenticator, Duo) for privileged accounts. Always keep backups of working sshd_config files.

Adopt configuration management and backups

Use Ansible, Puppet, or Chef to standardize SSH settings across servers. Store known-good configs in version control. Managed VPS from YouStable can offload patching, SSH hardening, and 24/7 incident response so you stay focused on your apps.

Common Error Patterns and How to Resolve Them

Error: Connection refused

Likely causes: sshd not running, wrong port, host firewall blocking, or cloud security group denies. Start sshd, open the port, and verify with ss -tlnp and nc/nmap.

Error: Connection timed out

Network path or firewall issue. Check provider firewalls, routing, security groups, and confirm public IP and DNS records are correct.

Error: Permission denied (publickey)

Fix file permissions, ensure correct public key in authorized_keys, and confirm that PubkeyAuthentication is enabled. Use ssh -vvv to see which key is offered.

Error: Remote host identification has changed

Host keys changed (e.g., rebuild). Verify fingerprints via console, then run ssh-keygen -R hostname on the client and reconnect to trust the new key.

FAQs

Why does SSH say “Connection refused” on my Linux server?

Because sshd isn’t listening or a firewall is blocking the port. Start/enable sshd, confirm the listening port with ss -tlnp, and allow it in UFW/firewalld and your cloud security groups. If you changed the port, connect with -p and adjust SELinux accordingly.

How do I fix “Permission denied (publickey)”?

Place your public key into ~/.ssh/authorized_keys on the server, set correct permissions (700 on .ssh, 600 on authorized_keys), ensure ownership, and verify PubkeyAuthentication yes. Use ssh -vvv to confirm the correct key is being offered by your client.

How can I restart SSH safely without locking myself out?

Keep an existing session open, back up sshd_config, run sshd -t to validate syntax, then restart sshd. Test a new connection in another terminal before closing the original session.

What if I changed the SSH port and now I can’t connect?

Open the new port in UFW/firewalld and your cloud security groups, update SELinux with semanage port, verify sshd listens on the new port, and connect with ssh -p <port>. If stuck, use the provider console to revert the change.

Can I reinstall or regenerate SSH safely?

Yes. Reinstall openssh-server and regenerate host keys with ssh-keygen -A from console or rescue mode. Expect a host key change warning on the client; verify fingerprints, remove the old entry with ssh-keygen -R, then reconnect.

Deepika Verma

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top