SSH Hardening Guide: Best Practices for Linux Servers

SSH makes remote Linux server administration easy, but defaults are not always safe. A poorly configured SSH server can be an easy target for brute-force attacks, exposed accounts, and unauthorized access.
This guide covers practical SSH hardening best practices for Linux servers. We will adjust sshd_config, test the configuration before restarting the service, and add protections that reduce the attack surface without making the server hard to manage.
Quick Reference
For a printable quick reference, see the SSH cheatsheet .
| Setting | Value | Purpose |
|---|---|---|
PasswordAuthentication | no | Force key-based authentication |
KbdInteractiveAuthentication | no | Disable keyboard-interactive password prompts |
PermitRootLogin | no | Disable root SSH login |
AllowUsers | deploy admin | Restrict SSH access to listed users |
PermitEmptyPasswords | no | Block empty passwords |
LoginGraceTime | 30 | Shorten the authentication window |
MaxAuthTries | 3 | Limit failed login attempts |
X11Forwarding | no | Disable X11 forwarding |
AllowAgentForwarding | no | Disable agent forwarding |
AllowTcpForwarding | no | Disable SSH tunnels for users who do not need them |
ClientAliveInterval | 300 | Set idle timeout interval |
ClientAliveCountMax | 2 | Disconnect after 2 missed keep-alives |
Prerequisites
- A server running Linux with SSH access
- Root or sudo privileges
- A working SSH key pair (see how to generate SSH keys )
All SSH server settings are configured in /etc/ssh/sshd_config. Some distributions also load files from /etc/ssh/sshd_config.d/, which is useful when you want to keep local changes separate from package defaults.
Before editing the SSH configuration, create a backup:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backupAfter each change, test the configuration before restarting SSH:
sudo sshd -tIf the command prints no output, the configuration syntax is valid. Then restart the SSH service:
sudo systemctl restart sshOn some distributions the service is named sshd:
sudo systemctl restart sshdUse Key-Based Authentication
Password authentication is vulnerable to brute-force attacks. Key-based authentication is more secure because it requires possession of the private key.
First, make sure you have copied your SSH key to the server and can log in without a password.
Then disable password authentication in /etc/ssh/sshd_config:
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yesThis forces users to authenticate with SSH keys and disables keyboard-interactive password prompts. Keep password authentication enabled until you have confirmed that your key login works from a new terminal session.
Disable Root Login
Allowing direct root login over SSH is a security risk. Attackers commonly target the root account in brute-force attacks.
Disable root login in /etc/ssh/sshd_config:
PermitRootLogin noIf you need root access, log in as a regular user and use sudo
or su
.
If you still need root login with keys only, use:
PermitRootLogin prohibit-passwordThis allows root login only with SSH keys, not passwords.
Restrict SSH by Firewall
If only a few IP addresses need SSH access, restrict the SSH port at the firewall. This is usually stronger than only changing the SSH port because unwanted hosts cannot reach the daemon at all.
With UFW, allow SSH from a trusted IP address:
sudo ufw allow from 203.0.113.10 to any port 22 proto tcpIf you manage the server from more than one location, add each trusted IP address before removing broader SSH rules. Do not close the current SSH port until you have tested a new connection.
Change the Default Port
The default SSH port is 22. Changing it does not provide real security, but it reduces noise from automated bots that scan port 22.
Change the port in /etc/ssh/sshd_config:
Port 2222Make sure to open the new port in your firewall before restarting SSH:
sudo ufw allow 2222/tcpFor more details, see our guide on how to change the SSH port .
Limit User Access
By default, all system users can log in via SSH. You can restrict access to specific users with the AllowUsers directive:
AllowUsers deploy adminOnly the listed users will be able to connect. All others will be denied.
To restrict access by group instead:
AllowGroups sshusersDisable Empty Passwords
Make sure accounts with empty passwords cannot log in via SSH:
PermitEmptyPasswords noSet Login Grace Time
The LoginGraceTime setting controls how long the server waits for a user to authenticate before disconnecting. The default is 120 seconds, which is too long:
LoginGraceTime 30Limit Authentication Attempts
Reduce the number of authentication attempts per connection to slow down brute-force attacks:
MaxAuthTries 3Disable X11 Forwarding
If you do not need to forward graphical applications over SSH, disable X11 forwarding:
X11Forwarding noOpenSSH disables X11 forwarding by default on many systems, but setting it explicitly keeps the intended policy clear.
Disable Agent Forwarding
Agent forwarding lets a remote server use your local SSH agent for onward connections. Disable it unless users need to connect from this server to other hosts with forwarded credentials:
AllowAgentForwarding noDisable TCP Forwarding
If your users do not need to create SSH tunnels, disable TCP forwarding:
AllowTcpForwarding noThis blocks SSH port forwarding requests. It does not stop users with shell access from running their own forwarding tools, but it removes the built-in SSH tunneling path.
Use Strong Key Types
When generating SSH keys, use Ed25519 or RSA with at least 4096 bits. Ed25519 is the recommended choice for new keys:
ssh-keygen -t ed25519For RSA:
ssh-keygen -t rsa -b 4096Older key types like DSA and ECDSA with small key sizes should be avoided.
Set Idle Timeout
Disconnect idle SSH sessions after a period of inactivity. This prevents abandoned sessions from remaining open:
ClientAliveInterval 300
ClientAliveCountMax 2This sends a keep-alive message every 300 seconds (5 minutes) and disconnects after 2 missed responses, giving a total timeout of 10 minutes.
Set Up Fail2Ban
Fail2Ban monitors authentication logs and bans IP addresses that show malicious activity, such as repeated failed login attempts. It is most useful on public SSH servers that still receive frequent connection attempts.
Install Fail2Ban:
sudo apt install fail2banCreate a jail override file:
sudo nano /etc/fail2ban/jail.d/sshd.localAdd the SSH jail configuration:
[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3
bantime = 3600
findtime = 600This configuration bans an IP address for 1 hour after 3 failed login attempts within 10 minutes. The default sshd jail usually knows where your distribution writes SSH authentication logs, so you do not need to set logpath unless your server uses a custom logging setup.
If you changed SSH to a custom port, set port to that value in the jail file:
port = 2222Start and enable Fail2Ban:
sudo systemctl enable fail2ban
sudo systemctl start fail2banTo check the status of the SSH jail:
sudo fail2ban-client status sshdDisplay a Warning Banner
You can display a legal warning banner before authentication. Create a banner file:
sudo nano /etc/ssh/bannerAdd your warning text:
Authorized access only. All activity is monitored and logged.Then enable it in /etc/ssh/sshd_config:
Banner /etc/ssh/bannerTroubleshooting
SSH does not restart after editing sshd_config
Run sudo sshd -t to find syntax errors. If you need to revert quickly, restore the backup with sudo cp /etc/ssh/sshd_config.backup /etc/ssh/sshd_config, then test the configuration again before restarting SSH.
Password login still works after setting PasswordAuthentication no
Check whether KbdInteractiveAuthentication is still enabled. On PAM-based systems, keyboard-interactive authentication can still ask for a password, so set both PasswordAuthentication no and KbdInteractiveAuthentication no.
The service name is different on your system
Ubuntu and Debian commonly use ssh.service, while RHEL, Fedora, and many other distributions use sshd.service. Check the active unit with systemctl status ssh or systemctl status sshd.
You changed the port but cannot connect
Make sure the firewall allows the new port before restarting SSH. If you use Ubuntu socket activation, ssh.socket may still listen on port 22 unless the socket configuration is updated.
Fail2Ban does not show bans for SSH
Check the jail status with sudo fail2ban-client status sshd. If the jail is active but no failures are detected, review your authentication logs with sudo journalctl -u ssh or sudo journalctl -u sshd and confirm that Fail2Ban is using the correct backend for your distribution.
FAQ
Should I change the SSH port?
Changing the port reduces automated scanning noise but does not provide real security. It is useful as part of a defense-in-depth strategy, not as a standalone measure.
Can I lock myself out by disabling password authentication?
Yes. Before disabling password authentication, make sure you can log in with your SSH key. Keep a console connection available as a backup.
Is Fail2Ban necessary if I use key-only authentication?
It is not strictly necessary, but it still helps. Fail2Ban reduces log noise and blocks IPs that repeatedly attempt to connect, even if they cannot authenticate.
What is the most important hardening step?
Disabling password authentication and using key-based authentication. This eliminates the most common attack vector: brute-force password guessing.
How do I check my current SSH configuration?
Run sudo sshd -T to display the effective SSH server configuration, including all defaults and overrides.
Conclusion
SSH hardening starts with safe configuration changes: key-based authentication, no direct root login, limited users, firewall restrictions, timeouts, and tested sshd_config edits. Apply the settings that fit your server, and always test a new SSH session before closing the old one.
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 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.
View author page