How to Secure an AlmaLinux SSH Server (12 Hardening Steps)
Harden OpenSSH on AlmaLinux 9 and 10 with key authentication, a safe sshd drop-in file, firewalld source rules, SELinux, fail2ban and log monitoring, without locking yourself out.
/etc/ssh/sshd_config.d/00-hardening.conf with PermitRootLogin no, PasswordAuthentication no and AllowGroups sshusers. Validate with sudo sshd -t, reload sshd, limit SSH to trusted networks in firewalld, keep SELinux enforcing and add fail2ban. Test from a second session before you close the first.Make SSH the Hardest Door on Your Server
SSH is your main management path, so it is also the first thing attackers probe. This guide gives you a tested order of changes for AlmaLinux, including the drop-in file precedence and SELinux details that generic guides skip.
Keys, Not Passwords
Named admin users with SSH keys, no root login.
Layered Controls
sshd settings, firewalld, SELinux and fail2ban work together.
Verify Everything
Check the effective config and test failures on purpose.
Before You Start
| Requirement | Why it matters |
|---|---|
| AlmaLinux 9 or 10 server | Commands target the drop-in configuration used by current releases. AlmaLinux 8 notes are included where they differ. |
| A user with sudo rights | You will edit system files and restart services. |
| Console or hypervisor access | Your recovery path if SSH stops working. |
| A second SSH session | For testing changes before you close the first one. |
| Your admin IP or subnet | Needed for the firewall rule and the fail2ban allow-list. |
Check your OpenSSH version and release first:
cat /etc/almalinux-release
ssh -V
sudo ls -la /etc/ssh/sshd_config.d/Each step below states what it changes and how to undo it.
Step 1: Back Up and Plan Recovery
Back up the SSH configuration
sudo cp -a /etc/ssh /root/ssh-backup-$(date +%F)Take a VM snapshot as well if you use a hypervisor. If anything goes wrong, you can restore the folder from the console.
Step 2: Create a Named Admin User and SSH Group
Shared and root logins make it hard to track who did what. Create a named administrator and a dedicated group that will be the only one allowed to use SSH.
Create the user and group
sudo useradd -m -G wheel adminuser
sudo passwd adminuser
sudo groupadd sshusers
sudo usermod -aG sshusers adminuser
id adminuserReplace adminuser with your own account name. Members of wheel can use sudo. The id command should list both wheel and sshusers.
Step 3: Set Up SSH Key Authentication
Run these commands on your workstation, not on the server.
Create and copy an Ed25519 key
ssh-keygen -t ed25519 -C "adminuser@workstation"
ssh-copy-id adminuser@SERVER-IPSet a strong passphrase when asked. Then test the key login and the sudo rights of the new user:
ssh adminuser@SERVER-IP
sudo whoamiThe second command should print root. Do not continue until both commands work. If the server uses a custom port, add -p PORT, as explained in our guide to SSH with a different port.
Step 4: Write the Hardening Drop-In File
Current AlmaLinux releases read extra settings from /etc/ssh/sshd_config.d/*.conf. OpenSSH uses the first value it finds for most options, and files are read in alphabetical order. Cloud images and the distribution itself ship files such as 01-permitrootlogin.conf or 50-redhat.conf, so name your file 00-hardening.conf to make sure that yours wins.
Create the file
sudo nano /etc/ssh/sshd_config.d/00-hardening.confPaste these settings:
# /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
AllowGroups sshusers
MaxAuthTries 3
LoginGraceTime 30
MaxStartups 10:30:60
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
LogLevel VERBOSE| Setting | What it does |
|---|---|
PermitRootLogin no | Blocks direct root logins. Use a named user and sudo. |
PasswordAuthentication no | Requires keys. Removes the main brute-force target. |
KbdInteractiveAuthentication no | Stops password-like prompts. On AlmaLinux 8 use ChallengeResponseAuthentication no. |
AllowGroups sshusers | Only members of this group can log in over SSH. |
MaxAuthTries 3 / LoginGraceTime 30 | Limits guessing attempts per connection and the time to log in. |
MaxStartups 10:30:60 | Starts dropping unauthenticated connections when many arrive at once. |
ClientAliveInterval / ClientAliveCountMax | Disconnects dead or idle sessions after about 10 minutes. |
X11Forwarding, AllowAgentForwarding, AllowTcpForwarding set to no | Removes features that attackers can abuse. Set AllowTcpForwarding back to yes if you rely on SSH tunnels or jump hosts. |
LogLevel VERBOSE | Logs the key fingerprint used to log in, which helps investigations. |
AllowGroups sshusers, any user who is not in that group is refused, including you. Confirm with id adminuser before you reload sshd.Step 5: Validate and Reload sshd
Check the syntax and the effective values
sudo sshd -t
sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|allowgroups|maxauthtries|logingracetime)'No output from sshd -t means the syntax is valid. The second command shows the values that sshd will really use, so confirm that they match your file. If a value is wrong, another drop-in file is winning.
Reload the service and test from a second terminal
sudo systemctl reload sshd
sudo systemctl status sshdKeep your first session open. In a new terminal, run ssh adminuser@SERVER-IP. Only close the first session after the second one works.
Step 6: Restrict SSH in firewalld
A strong SSH configuration still accepts connections from the whole internet. Allow SSH only from your management network.
Allow your trusted subnet
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'
sudo firewall-cmd --reloadReplace 192.168.1.0/24 with your own admin network. Test a new SSH connection from that network.
Remove the open SSH service
Only after the test succeeds, remove the rule that allows SSH from everywhere:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-allIf you work from changing addresses, use a VPN or bastion host with a fixed address instead of opening SSH to the world. Add --zone=ZONE to the commands if your interface is not in the default zone.
Step 7: Keep SELinux Enforcing and Handle Custom Ports
SELinux should stay in enforcing mode. Check it, and do not disable it to fix an SSH problem:
getenforce
sudo restorecon -Rv ~/.sshThe restorecon command repairs file labels if a copied authorized_keys file is refused. If you decide to move SSH to a custom port, you must also allow the port in firewalld and label it with semanage port -a -t ssh_port_t. We cover both in the post-install configuration guide and in how to SSH with a different port. A custom port reduces scan noise, but it is not a replacement for the controls in this guide.
Step 8: Install fail2ban
Fail2ban watches the logs and blocks addresses that fail to log in repeatedly. It is available from EPEL.
Install it and create an sshd jail
sudo dnf install -y epel-release
sudo dnf install -y fail2ban
sudo nano /etc/fail2ban/jail.d/sshd.local[sshd]
enabled = true
backend = systemd
maxretry = 4
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24The ignoreip line stops fail2ban from banning your own admin network. If SSH uses a custom port, add port = 2222 to the jail.
Start and check it
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdTo remove a ban by mistake, run sudo fail2ban-client set sshd unbanip IP-ADDRESS.
Step 9: Review the Crypto Policy
AlmaLinux uses a system-wide cryptographic policy that also controls which algorithms OpenSSH allows. Check it:
update-crypto-policies --showThe default policy is a sound balance for most servers. Avoid hand-editing cipher lists in sshd_config, because the policy keeps them consistent. A stricter policy such as FUTURE can break older clients and other services, so test it first:
sudo update-crypto-policies --set FUTURE
sudo systemctl reload sshdReturn to the default with sudo update-crypto-policies --set DEFAULT if something fails. Apply this step only if your policy or compliance rules require it.
Step 10: Monitor SSH Logs
sudo journalctl -u sshd --since "1 hour ago"
sudo journalctl -u sshd | grep -E "Failed|Invalid user" | tail -20
last -n 10If the rsyslog service is installed, authentication events are also written to /var/log/secure. Review the logs regularly, forward them to a central log server and watch for logins from unknown addresses.
Step 11: Audit with ssh-audit
The open-source ssh-audit tool reports weak algorithms and risky settings. Install it from EPEL if it is available, or follow the project’s instructions, and scan your server:
ssh-audit SERVER-IPRead each warning and fix only what the crypto policy and your clients allow.
Step 12: Verify and Maintain
Prove that the protections work by testing the failures on purpose, from a second terminal:
# Password login must be refused
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no adminuser@SERVER-IP
# Root login must be refused
ssh root@SERVER-IP
# Your key login must still work
ssh adminuser@SERVER-IPKeep OpenSSH updated, and back up the final configuration:
sudo dnf upgrade -y openssh openssh-server
sudo systemctl restart sshd
sudo cp -a /etc/ssh /root/ssh-hardened-$(date +%F)Add this checklist to your regular maintenance. For the rest of the server, follow our AlmaLinux server hardening checklist.
Troubleshooting
Permission denied (publickey)
Check the key, the user name and the ~/.ssh permissions (700 for the folder and 600 for authorized_keys). Run ssh -vvv and read the server log.
Locked out after AllowGroups
The user is not in sshusers. Use the console to run sudo usermod -aG sshusers USER.
My settings are ignored
Another drop-in file wins. Rename yours with a 00- prefix and compare against sudo sshd -T.
sshd will not reload
Run sudo sshd -t to find the error, then read sudo journalctl -xeu sshd.
I banned myself
Unban with sudo fail2ban-client set sshd unbanip IP, and add your admin network to ignoreip.
authorized_keys refused (SELinux)
Run sudo restorecon -Rv /home/USER/.ssh as root to restore the labels.
If you cannot log in at all, use the VM console, restore the backup from Step 1 and restart sshd.
Frequently Asked Questions
How do I secure SSH on AlmaLinux?
Use SSH key authentication, disable password and root logins, restrict access with AllowGroups, limit SSH to trusted networks in firewalld, keep SELinux enforcing, add fail2ban and monitor the logs.
Where should I put SSH hardening settings on AlmaLinux 9 and 10?
Use a drop-in file in /etc/ssh/sshd_config.d/, named so that it is read first (for example 00-hardening.conf), and confirm the effective values with sudo sshd -T.
Why do my sshd_config changes not take effect?
OpenSSH uses the first value it finds for most options. A drop-in file that is read earlier can override your setting, so check the files in /etc/ssh/sshd_config.d/ and run sudo sshd -T.
Is it safe to disable SSH password authentication?
Yes, after you confirm that key login works for every administrator. Keep a console or second session open while you test.
Do I need to change the SSH port on AlmaLinux?
No. A custom port reduces scan noise but is not real security. If you use one, allow it in firewalld and label it in SELinux.
How do I install fail2ban on AlmaLinux?
Enable EPEL with sudo dnf install epel-release, then run sudo dnf install fail2ban, create an sshd jail and enable the service.
Does this guide work on AlmaLinux 8?
Most steps do. On AlmaLinux 8, the keyboard-interactive option is named ChallengeResponseAuthentication, and some package versions differ.
Conclusion
Securing an AlmaLinux SSH server is a set of small changes that add up: named users and keys, a hardening drop-in with the first-value-wins rule in mind, firewalld rules that limit who can connect, SELinux kept on, fail2ban for repeated failures and logs that you actually read. Make one change at a time, verify the effective settings with sshd -T and always test from a second session.
/etc/ssh → Create user and sshusers group → Set up keys → 00-hardening.conf → sshd -t and sshd -T → Reload and test → Restrict firewalld → Keep SELinux enforcing → fail2ban → Review logs and audit.Keep Learning with VMoreCloud
Find more Linux, security, virtualization and Windows Server tutorials.
Sources & Further Reading
- OpenSSH sshd_config manual
- Red Hat: Security Hardening for RHEL 10 (cryptographic policies, SELinux and firewalld concepts)
- AlmaLinux Wiki
- Fail2ban project
- ssh-audit project
Technical note: this guide follows the OpenSSH manual pages and Red Hat and AlmaLinux documentation. Option names, file names and defaults differ between releases and OpenSSH versions, so test on a non-production server first and keep console access available. Only change systems that you are authorized to administer.

