Linux·7 min read·

Rocky Linux 9 Initial Server Setup for Production Workloads

Build a hardened Rocky Linux 9 baseline: admin users, SSH keys, firewalld rules, fail2ban, and automatic security updates before your app ever ships.

NB

Netbay Engineering

Netbay Engineering

On this page

A fresh Rocky Linux 9 install boots with more listening services than you need and fewer protections than the internet assumes. The distance between "it boots" and "it survives the internet" is about twenty minutes of deliberate work, and every production server should make that trip before DNS points at it. This is the baseline we treat as non-negotiable: an unprivileged admin account, key-only SSH, a minimal firewalld ruleset, fail2ban for brute-force noise, and automatic security updates. None of it is exotic, and every step below is copy-paste ready.

Rocky Linux 9 production hardening pipeline 1. FRESH BOOT root ssh dnf update -y 2. ADMIN USER wheel + sudo key auth seeded 3. SSH LOCKED root login off passwords off 4. FIREWALLD ssh http https reload + verify 5. GUARDS ON fail2ban dnf-automatic Production traffic reaches the app only after every stage is green

First Login and System Update

Connect as root and bring the system current before anything else. RHEL-family cloud images are built once and patched never, so updates are waiting the moment you log in.

bash
ssh root@YOUR_SERVER_IP
dnf update -y
cat /etc/rocky-release

If the kernel was among the updated packages, reboot so you are actually running what you just installed. Deploying onto a stale kernel is how you discover driver and module mismatches during an incident instead of during setup.

Create an Admin User with Key Access

Daily work should never happen as root, and sudo gives you a session trail for free. Create a normal user, add it to the wheel group, and seed its SSH keys from the root account you already log in with. Every command in this post runs in the initial root session; once the new user is proven, switch to it permanently.

bash
adduser deploy
passwd deploy
usermod -aG wheel deploy
cp -a /root/.ssh /home/deploy/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys

Open a second terminal and prove the new user can log in and run sudo -v before you touch the SSH daemon. Locking yourself out of a remote box is the classic initial-setup failure, and the second-session test is the only guard that actually works.

Lock Down SSH

With key login proven, disable root logins and password authentication at the source. On EL9 the clean way is a drop-in under sshd_config.d, which the main config includes first — no sed archaeology on the base file.

bash
cat > /etc/ssh/sshd_config.d/50-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
EOF
sshd -t
systemctl restart sshd

The sshd -t call validates the configuration before the restart, so a typo cannot take away your only way back in. Keep the original root session open until a fresh login as deploy succeeds.

Minimal firewalld Ruleset

Rocky 9 enables firewalld from first boot: ssh is allowed and everything else is dropped. Make the intended workload explicit instead of discovering your firewall policy the first time something cannot connect.

bash
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-all

Every --permanent flag needs a --reload to take effect, and --list-all is the command that tells you the truth about what is open. Database and cache ports stay bound to localhost or a private interface; they never go in this list.

fail2ban and Automatic Security Updates

Brute-force protection and unattended patching turn a hardened box into a self-maintaining one. fail2ban lives in EPEL; dnf-automatic ships in the base repositories.

bash
dnf install -y epel-release
dnf install -y fail2ban fail2ban-firewalld
systemctl enable --now fail2ban
dnf install -y dnf-automatic
sed -i 's/^apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
systemctl enable --now dnf-automatic.timer

With apply_updates enabled, security errata install within a day of publication. If a service demands scheduled maintenance windows, keep the timer and control reboots instead of disabling patching.

The Production Baseline, Summarized

  • Unprivileged sudo user for all daily work
  • Root login and password SSH disabled
  • firewalld exposing only ssh, http, and https
  • fail2ban watching auth logs with firewalld ban actions
  • dnf-automatic applying security errata daily
  • A reboot after the first kernel update

None of this replaces monitoring, backups, or an inventory of what actually runs on the box, but it is the floor under every other hardening decision. Skipping any one of these steps is how new servers end up in incident reports instead of runbooks. You can spin up a Rocky Linux 9 instance on Netbay in under 60 seconds, run this checklist top to bottom, and have a hardened server before your coffee cools — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance