Skip to content
Commitpedia
Log in Join & edit

Harden a fresh Linux server in 30 minutes

The baseline for any new Debian, Ubuntu or RHEL-family server: updates on, a non-root user with sudo, SSH keys only, a firewall that allows what you need, and fail2ban. In that order, without locking yourself out.

Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?

Edit history of Harden a fresh Linux server in 30 minutes: 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
4 min

A server that is reachable from the internet gets its first password-guessing attempts within minutes. These five steps are the minimum every server should have before it does anything else. They take about half an hour and work on Debian 12, Ubuntu 22.04 and newer, RHEL 9, Rocky Linux and AlmaLinux; where the two families differ, both commands are shown.

Careful: steps 3 and 4 change how you log in. Do them from one SSH session and test every change by opening a second terminal and logging in again before you close the first. As long as the first session stays open, you can undo anything.

Step 1: Update everything and turn on automatic security updates

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
# Debian / Ubuntu
sudo apt update && sudo apt full-upgrade -y
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades     # answer Yes

# RHEL / Rocky / Alma
sudo dnf upgrade -y
sudo dnf install -y dnf-automatic
sudo systemctl enable --now dnf-automatic-install.timer

Reboot if a new kernel was installed (/var/run/reboot-required exists on Debian and Ubuntu; needs-restarting -r on RHEL family). Automatic updates install security fixes daily; they do not reboot by themselves unless you configure it, so check for a pending reboot once a month.

Step 2: Create your own user with sudo

Working as root means one typo can take the server down and every action is anonymous in the logs. Create a normal account and give it sudo:

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
# Debian / Ubuntu
sudo adduser deploy
sudo usermod -aG sudo deploy

# RHEL / Rocky / Alma
sudo useradd -m deploy
sudo passwd deploy
sudo usermod -aG wheel deploy

Then copy your SSH public key to the new account from your laptop (ssh-copy-id deploy@server, see the SSH keys article) and confirm ssh deploy@server followed by sudo -v works. Do not continue until it does.

Step 3: SSH: keys only, no root login

Modern OpenSSH reads extra files from /etc/ssh/sshd_config.d/, so put your settings in a new file instead of editing the main one. Cloud images often ship a file there (for example 50-cloud-init.conf) that re-enables password login; the number at the front decides the order and the first value of each option wins, so name yours to sort first.

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
X11Forwarding no
EOF

sudo sshd -t                                   # syntax check, prints nothing when fine
sudo sshd -T | grep -iE 'permitrootlogin|passwordauthentication|kbdinteractive'   # effective values

sudo systemctl restart ssh      # Debian / Ubuntu
sudo systemctl restart sshd     # RHEL / Rocky / Alma

Now, in a new terminal, log in as deploy with your key. If it works, also confirm that passwords are really off: ssh -o PubkeyAuthentication=no deploy@server must fail with Permission denied (publickey). If anything is wrong, fix it in the still-open first session.

Step 4: Firewall: deny by default, allow what you run

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
# Debian / Ubuntu: ufw
sudo ufw allow OpenSSH
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
sudo ufw status verbose

# RHEL / Rocky / Alma: firewalld is already active and allows ssh
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=https     # only what you actually serve
sudo firewall-cmd --reload

Add ports as you install services, not in advance. If you moved SSH to another port in step 3, allow that port before enabling the firewall. Test with a new SSH login again.

Step 5: fail2ban: slow down password guessing

Even with passwords disabled, bots keep hammering port 22 and fill the logs. fail2ban bans an address after a few failures:

Check before you run this

  • Runs with administrator rights. Make sure you understand every line.
# Debian / Ubuntu
sudo apt install -y fail2ban
# RHEL / Rocky / Alma
sudo dnf install -y epel-release && sudo dnf install -y fail2ban

sudo tee /etc/fail2ban/jail.local >/dev/null <<'EOF'
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
backend = systemd
EOF

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Add your own office or home address to ignoreip so a forgotten passphrase never bans you. The fail2ban article in this topic covers tuning and unbanning.

Ten more minutes well spent

  • timedatectl: make sure the clock is synchronized (System clock synchronized: yes); TLS, logs and two-factor codes depend on it.
  • sudo ss -ltnp: look at every listening port and ask whether it must be reachable from outside. Databases and admin panels should listen on 127.0.0.1 or be limited to a source network in the firewall.
  • Remove what you do not use: apt purge / dnf remove old web or mail servers that came with the image.
  • Set up off-server backups and test a restore once. Hardening reduces risk; backups are what save you when it fails anyway.
  • Run the SSH audit script in this topic to confirm the sshd settings took effect.

Official documentation

Did this work for you?

No votes yet. Be the first.

If it did not work, the report form below tells the editors what went wrong.

See also

  • 0177 Users, groups and sudo on Debian, Ubuntu and RHEL How Linux accounts and groups work, how to create users, and how sudo gives admin rights through the sudo group on Debian/Ubuntu… Beginner · Explains an idea · Linux Article Users, sudo & hardening 15 Oct 2026
  • 0178 Create a sudo user with an SSH key and disable password login A bash script that creates an admin user in the sudo or wheel group, installs their SSH public key and can switch… Advanced · Step by step · Linux Script Keys & config · Users, sudo & hardening 15 Oct 2026
  • 0249 Set up and harden a fresh Linux server in one afternoon Take a new Ubuntu, Debian or Rocky/Alma server from first login to a safer baseline: sudo admin, SSH keys only, firewall, automatic… Beginner · Guided project · Linux Article Networking & firewalls · Packages & updates · Users, sudo & hardening 15 Oct 2026
  • 0317 Fix: Permission denied when running a script (chmod +x) bash: ./script.sh: Permission denied means the file exists but you may not execute it. Usually the execute bit is missing; sometimes the… Beginner · Fixes an error · Linux, macOS Article Basics · Users, sudo & hardening 15 Oct 2026
  • 0322 Fix: user is not in the sudoers file sudo refuses because your account is not allowed to use it. Add the user to the sudo group (Debian, Ubuntu) or wheel… Beginner · Fixes an error · Linux, macOS Article Server hardening · Users, sudo & hardening 15 Oct 2026
  • 0353 fail2ban: block repeated failed logins Install fail2ban, enable the sshd jail with sane ban times, whitelist your own address, read the ban list, unban someone, and add… Intermediate · Step by step · Linux Article Server hardening · SSH 15 Oct 2026

Repos in the wild

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Dominik +5,144 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?