Emergency server help: get in touch

Harden SSH AlmaLinux 9: Secure Setup in 15 Minutes

Keys only, root locked down, a non-standard port that does not break SELinux, and rate-limiting that stops the log spam. Every step is safe to apply on a live server if you keep one session open.

Published Updated 3 min read

Before you touch anything

Open a second SSH session and leave it connected. Every change below is applied with sshd -t (config test) before a reload, and a reload never drops existing sessions, so if you lock yourself out you still have the first window to undo it.

Check that the server is actually using sshd_config and not a drop-in you did not know about:

sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|^port|pubkeyauthentication'
ls /etc/ssh/sshd_config.d/

On AlmaLinux 9 the file /etc/ssh/sshd_config.d/50-redhat.conf exists and is read before the main file. Anything you set in the main file that conflicts with it loses, because sshd keeps the first value it sees. Put your hardening in its own drop-in with a lower number so it wins.

1. Install your key, then disable passwords

From your workstation:

ssh-keygen -t ed25519 -C "you@workstation"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@server

Log in once with the key to prove it works. Then create /etc/ssh/sshd_config.d/10-hardening.conf:

PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2

prohibit-password lets root in with a key only, which is what most cPanel and DirectAdmin servers need. If you have a sudo user and never need root over SSH, use PermitRootLogin no instead. Test and reload:

sshd -t && systemctl reload sshd

Try a password login from another terminal; it should be refused immediately.

2. Change the port without fighting SELinux

Moving off port 22 does not make the server secure, but it removes 95% of the automated noise from your logs and from your brute-force blocker. Pick a port above 1024 that nothing else uses, for example 2222 is too common; 48222 is fine.

SELinux only allows sshd to bind to ports labelled ssh_port_t. Add the label first or sshd will fail to start:

dnf -y install policycoreutils-python-utils
semanage port -a -t ssh_port_t -p tcp 48222
firewall-cmd --permanent --add-port=48222/tcp && firewall-cmd --reload
echo "Port 48222" >> /etc/ssh/sshd_config.d/10-hardening.conf
sshd -t && systemctl restart sshd

Connect on the new port in a new terminal before you close the old one. Only then remove port 22 from the firewall (firewall-cmd --permanent --remove-service=ssh). If you use CSF instead of firewalld, add the port to TCP_IN in /etc/csf/csf.conf and run csf -r.

3. Rate-limit and ban

With passwords off, brute force cannot succeed, but it still costs CPU and fills /var/log/secure. Use whichever blocker the server already has: CSF+LFD (LF_SSHD = "5" in csf.conf), cPHulk on cPanel, or fail2ban on a plain box:

dnf -y install fail2ban
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled  = true
port     = 48222
maxretry = 4
findtime = 10m
bantime  = 24h
EOF
systemctl enable --now fail2ban

Do not run two blockers at once; they fight over iptables chains.

4. Restrict who can log in

If only two people should ever SSH in, say so:

AllowUsers root deploy

Add it to the same drop-in. Anyone else gets “Permission denied” before authentication even starts. For root, also trim /root/.ssh/authorized_keys — old keys from previous admins and providers’ automation are the most common leftover.

Verify

sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|^port|maxauthtries|allowusers'
ss -ltnp | grep sshd
grep -c 'Failed password' /var/log/secure

The last number should stop growing within an hour. The server-security-audit script checks all of the above and flags anything that drifts later.

Harden SSH AlmaLinux 9 at a glance

Harden SSH AlmaLinux 9 summary card: Open a second SSH session and leave it connected.
In short: Open a second SSH session and leave it connected.

Official documentation: AlmaLinux wiki, Linux man pages.

Related guides: KernelCare on cPanel and DirectAdmin servers: setup, verification and rollback · Replacing cxs: malware scanning with LMD (maldet), ClamAV and ImunifyAV on hosting servers · Incident response after a cPanel root-escalation CVE: rotating keys, hunting .sorry, auditing sessions.

Free website test

Is your website set up right?

Check SSL, security headers, redirects, robots.txt, sitemap, llms.txt and security.txt in one test. It takes about 30 seconds.