• Latest
  • Trending
  • All
Securing Ubuntu 24.04 LTSSysAdmin Hardening Checklist - PeopleAreGeek

Securing a Linux Ubuntu 24.04 Server: SysAdmin Hardening Checklist

June 14, 2026
ssh command cheatsheet

SSH Command Cheatsheet: Connect, Keys, scp, Tunnels (2026)

June 16, 2026
chmod-chown-cheatsheet

chmod and chown Cheatsheet: Linux Permissions, Decoded (2026)

June 16, 2026
systemctl-journalctl-cheatsheet

systemctl + journalctl Cheatsheet: Services and Logs (2026)

June 16, 2026
grep-cheatsheet

The grep Cheatsheet: Search a File, Search a Tree (2026)

June 16, 2026
rsync-cheatsheet

The rsync Cheatsheet: Mirror, Sync, Copy Over SSH (2026)

June 16, 2026
curl-cheatsheet

curl Cheatsheet: Download Files and Test APIs (2026)

June 16, 2026
iptables-vs-nftables-cheatsheet cheatsheet

iptables vs nftables: Linux Firewall Cheatsheet, Side by Side

June 16, 2026
nmcli-cheatsheet cheatsheet

nmcli Cheatsheet: Wi-Fi and Network Connections From the Linux Terminal

June 16, 2026
powershell-networking-cheatsheet cheatsheet

PowerShell Networking Cheatsheet: Test-NetConnection, IP, DNS (2026)

June 16, 2026
tar command cheatsheet

The tar Command Cheatsheet: Create, Extract, Stop Guessing (2026)

June 16, 2026
Linux find command cheatsheet

The find Command Cheatsheet: Every Recipe You Actually Use (2026)

June 15, 2026
Linux networking commands cheatsheet, ip and ss

Linux Networking Commands in 2026: the ip and ss Cheatsheet

June 15, 2026
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools
Tuesday, June 16, 2026
  • Login
People Are Geek
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools
No Result
View All Result
People Are Geek
No Result
View All Result
Home Security Tools

Securing a Linux Ubuntu 24.04 Server: SysAdmin Hardening Checklist

by People Are Geek
June 14, 2026
in Security Tools
0
Securing Ubuntu 24.04 LTSSysAdmin Hardening Checklist - PeopleAreGeek
0
SHARES
9
VIEWS
Share on FacebookShare on Twitter

SysAdmin checklist Ubuntu 24.04 LTS · 18 min read · Updated May 2026

A fresh Ubuntu box boots fine. It’s also wide open, which nobody tells you. So here’s the run-through I do on every new 24.04 LTS VPS before I trust it with anything that matters. SSH locked to keys on a port the scanners aren’t camped on. UFW with the fewest rules I can get away with. fail2ban swatting the brute-force bots, unattended security updates ticking over, AppArmor actually enforcing instead of just sulking in complain mode, and auditd so that six months from now I can answer “who touched what” without guessing. It’s 30 commands. You paste them in order, and after each one I hand you the check that proves it took. Block out 30 to 45 minutes. By the end, the endless background hum of automated attacks just bounces off.

Stacked defense layers an automated attack meets on a hardened Ubuntu 24.04 server, outside in: the UFW firewall edge with default deny incoming and only SSH plus 80 and 443 open; the SSH door with keys only, a custom port, no root login and fail2ban banning IPs that keep failing; accounts where day-to-day work runs as an admin user with sudo and root retires after one login; patched software with the 20 to 60 stale packages cleared on day one and unattended-upgrades applying security fixes; AppArmor process containment with profiles flipped from complain to enforce; and a watch and recover layer with auditd, NTP-synced time and a known-good snapshot, all sitting above the server and its data
What the checklist actually builds: six layers, and a bot has to get through every one of them.

The 10-step checklist

  1. First root access and admin user creation
  2. Initial system updates
  3. SSH hardening (keys, custom port, no root login)
  4. UFW firewall with minimal rules
  5. fail2ban against SSH brute-force
  6. Automatic updates (unattended-upgrades)
  7. AppArmor in enforce mode
  8. Audit logs with auditd
  9. Time synchronisation and NTP
  10. Final verification and snapshot
  11. FAQ
Before you start. I’m assuming a fresh Ubuntu 24.04 LTS VPS (OVH, Hetzner, Scaleway, Contabo, AWS Lightsail) and you’re driving the whole thing over SSH from your laptop. Do not close your SSH session until step 3 is done. I locked myself out exactly this way once. Fat-fingered sshd_config, no second terminal open, and that was a fun hour on the rescue console. Keep that first session breathing. It’s your lifeline.
1

First root access and admin user creation

Log in as root, just this once. Then build yourself a plain user for the day-to-day and drop it in the sudo group. Living as root full-time? That’s how one stray typo wipes the wrong thing while you’re still reaching for the coffee.

# On your local machine
ssh root@YOUR_IP

# On the server (as root)
adduser admin           # create the admin user
usermod -aG sudo admin  # add to sudo group
mkdir -p /home/admin/.ssh
chmod 700 /home/admin/.ssh
cp /root/.ssh/authorized_keys /home/admin/.ssh/
chown -R admin:admin /home/admin/.ssh
su – admin sudo whoami # must print: root exit
2

Initial system updates

A brand-new server usually shows up with 20 to 60 packages already stale. Patch the lot before you install a single thing of your own. You don’t want to build on top of holes that already have public exploits.

apt update
apt upgrade -y
apt dist-upgrade -y
apt autoremove -y
apt autoclean
apt list –upgradable # Must print: Listing… Done (and nothing else)

See a “Pending kernel upgrade” message? Reboot now (reboot), wait for it to come back, then carry on. Soldiering ahead on the old kernel just stores up a weird problem for later.

3

SSH hardening (keys, custom port, no root login)

This is the big one. It’s also the step that’ll lock you out cold if you rush it. A few edits to /etc/ssh/sshd_config: kill direct root login, switch password auth off entirely so it’s keys or nothing, then move SSH off port 22 to somewhere the scanners aren’t hammering around the clock.

# Backup the config before editing
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# Edit the config
nano /etc/ssh/sshd_config

# Lines to set or add:
Port 2222                           # custom port (pick any 1024-65535)
PermitRootLogin no                  # no more direct root login
PasswordAuthentication no           # SSH keys only
PubkeyAuthentication yes
MaxAuthTries 3                      # 3 attempts max per connection
ClientAliveInterval 300             # auto-disconnect after 5 min
ClientAliveCountMax 2
LoginGraceTime 30
AllowUsers admin                    # restrict to the admin user only

Validate the syntax before you restart sshd. Always. One bad line in that file and the restart kicks you off with no way back in:

sshd -t
# No output means OK; if there is one, fix it before continuing

# Restart SSH
systemctl restart ssh
Critical. Open a brand-new SSH session on the new port and prove it actually logs you in before you close the root one you’re sitting in. If the new session bounces, the old one is still right there to roll back the change. That open terminal is the only thing standing between you and a rescue console at 2am.
# From your local machine, in a new terminal
ssh admin@YOUR_IP -p 2222
whoami # must print: admin sudo -i # must prompt for your admin password and elevate to root
4

UFW firewall with minimal rules

UFW is just a friendlier face glued onto nftables/iptables. It’s the one I reach for on nearly every box. The whole idea fits in one breath: slam the door on everything inbound, then crack open only the few ports you genuinely need, one at a time, by hand.

apt install -y ufw
ufw default deny incoming
ufw default allow outgoing

# Open the custom SSH port (mandatory before enabling)
ufw allow 2222/tcp comment 'SSH custom port'

# Open application ports as needed
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'

# Enable the firewall
ufw enable     # answer y
ufw status verbose # Must show “Status: active” and the rules above

Database behind the app? Postgres, MySQL, a Redis cache, whatever it is. Never hang 5432, 3306 or 6379 out on the open internet. An unauthenticated Redis goes from “public” to “owned” in hours, sometimes less, and I’ve watched it happen. Tunnel into it over SSH from the app side, or wire up a WireGuard link. Just keep it off the public interface.

5

fail2ban against SSH brute-force

Keys-only SSH doesn’t stop the bots from trying. They keep knocking by the thousand, and every rejected attempt still burns a sliver of CPU while it junks up your logs. fail2ban watches for any IP that fails too many times inside a window, then drops a firewall ban on it without you lifting a finger. You set the thresholds once and mostly never look again.

apt install -y fail2ban

# Create the local config (jail.local takes precedence over jail.conf)
cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = 2222
backend = systemd
EOF

systemctl enable --now fail2ban
fail2ban-client status sshd # Must show “Currently failed””Total failed””Currently banned”

Banned your own IP after fumbling the login a few times? Happens to all of us. Spring it loose with fail2ban-client set sshd unbanip 1.2.3.4.

6

Automatic updates (unattended-upgrades)

Ubuntu ships security fixes a couple of times a week, and nobody sane is SSHing in to run apt upgrade by hand every other day. So you let it patch the security stuff on its own while the big distro upgrades, the kind that genuinely break things, stay off the table. Honestly, I think this is the highest payoff-per-minute thing on the whole list. I might be talking myself into it because it’s so little effort, but the math has held up for me across years of boxes.

apt install -y unattended-upgrades apt-listchanges

# Enable Ubuntu's default config
dpkg-reconfigure -plow unattended-upgrades
# Answer Yes to the question

# Verify the config file
nano /etc/apt/apt.conf.d/50unattended-upgrades

Open 50unattended-upgrades and double-check the security sources are really switched on:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}";
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
unattended-upgrade –dry-run –debug 2>&1 | head -20 # Must list the packages that would be updated
7

AppArmor in enforce mode

Mandatory Access Control on Ubuntu goes through AppArmor. Each service gets a profile spelling out exactly which files and syscalls it may touch, and anything that strays outside the box gets slapped down. It ships on 24.04 and it’s already running. The catch nobody mentions: a chunk of those profiles sit in “complain” mode, which logs the violation and then shrugs and lets it through anyway. So we flip them to “enforce” and give them teeth.

apt install -y apparmor apparmor-utils apparmor-profiles apparmor-profiles-extra

# Current status
aa-status

# Switch all profiles to enforce
aa-enforce /etc/apparmor.d/*
aa-status | head -5 # The line “profiles are in enforce mode” must show a number > 30

Something falls over the moment enforce kicks in? Don’t go ripping the whole subsystem out, that’s overkill. Pull up journalctl -u apparmor and it’ll tell you precisely what got denied. From there you either patch that one profile or, if you’re in a hurry, drop just that profile back to complain while you sort it: aa-complain /etc/apparmor.d/usr.sbin.service-name.

8

Audit logs with auditd

auditd is the flight recorder. It quietly logs the sensitive stuff: reads of critical files and every sudo command, plus the config changes you’d otherwise never catch. You won’t give it a second thought until the day someone asks “who edited /etc/passwd yesterday at 2pm?” and instead of shrugging, you just pull the exact answer.

apt install -y auditd audispd-plugins

# Minimal rules: watch critical files
cat > /etc/audit/rules.d/hardening.rules <<'EOF'
# User account modifications
-w /etc/passwd -p wa -k user_modification
-w /etc/shadow -p wa -k user_modification
-w /etc/group -p wa -k user_modification
-w /etc/sudoers -p wa -k sudoers_modification
-w /etc/sudoers.d/ -p wa -k sudoers_modification

# SSH modifications
-w /etc/ssh/sshd_config -p wa -k ssh_config

# Abnormal network egress
-a always,exit -F arch=b64 -S socket -F a0=10 -k network_socket

# Lock the rules (no modification without reboot)
-e 2
EOF

systemctl enable --now auditd
systemctl restart auditd
auditctl -l | head # Must list the rules above

Need to read back what happened? ausearch -k user_modification pulls the events by tag. Or aureport -au if you just want the authentication summary.

9

Time synchronisation and NTP

People skip this one and then spend an afternoon baffled about why nothing works. Let the clock drift past a few seconds and TLS certs suddenly read as invalid, so your own outbound HTTPS calls bounce. On top of that, trying to line up these logs against your other machines turns into a guessing game. Good news: Ubuntu 24.04 already runs systemd-timesyncd, so this is really just pointing it at the right zone and confirming it’s awake.

timedatectl set-timezone Europe/Paris   # or your time zone
timedatectl set-ntp true

# Verify
timedatectl status
timedatectl status | grep -E “(synchronized|NTP)” # Must show “System clock synchronized: yes” and “NTP service: active”
10

Final verification and snapshot

Before you sign off on this box as production-ready, fire the whole batch at once and actually read the output, top to bottom:

# Consolidated checks (";" separator so everything runs even if one command fails)
echo "=== SSH ==="                  ; grep -E "^(Port|PermitRoot|PasswordAuth)" /etc/ssh/sshd_config
echo "=== UFW ==="                  ; ufw status numbered | head -10
echo "=== fail2ban ==="             ; fail2ban-client status sshd
echo "=== unattended-upgrades ===" ; systemctl is-active unattended-upgrades
echo "=== AppArmor ==="             ; aa-status | head -3
echo "=== auditd ==="               ; systemctl is-active auditd
echo "=== Updates ==="              ; apt list --upgradable 2>/dev/null | wc -l
echo "=== Uptime ==="               ; uptime

Once every line reads the way it should, go grab a server snapshot from your provider (OVH calls it “Backup snapshot”, Hetzner just “Snapshot”, AWS “AMI”, Scaleway “Snapshot” again). Two minutes, tops. What you get back is a clean, known-good image to roll to the day you inevitably break something down the road. I take one right here, every single time.

And if this box actually matters in production, this isn’t the finish line. Bolt on uptime monitoring (SecurityWatch or UptimeRobot) plus something that keeps eyes on the app and the host underneath it (Netdata, Grafana Cloud Free, or Prometheus + node_exporter). Harden a server and then never look at it again, and you’ll learn it died from an angry user, days after the fact.

Numbered strip of the first 30 minutes on a fresh Ubuntu 24.04 server, the 10 checklist steps in order with one command chip each: 1 create the admin user with adduser, 2 patch everything stale with apt, 3 lock down SSH via sshd_config, 4 close the firewall with ufw, 5 ban the bots with fail2ban, 6 put updates on autopilot with unattended-upgrades, 7 give AppArmor teeth with aa-enforce, 8 start the flight recorder with auditd, 9 sync the clock with timedatectl, 10 verify then take a snapshot; a warning banner reminds you not to close the first root session until step 3 checks out
The whole run on one strip. Keep that first root session open until step 3 checks out.

Monitor security across multiple servers?

SecurityWatch watches uptime, TLS certs and HTTP headers across every target you give it, plus it flags config drift, all from the browser. When something slips, it pings you on Slack or Discord. Free, runs right in your browser, and the watchlist lives in localStorage.

Launch SecurityWatch →

Routine maintenance after hardening

Nobody wants to hear this part: all of it rots if you walk away. Here’s the rhythm I keep on a 24.04 LTS box in 2026. Every week, a quick glance at fail2ban-client status sshd and journalctl -p err -b. Every month, check aa-status, ufw status and apt list --upgradable. Every quarter, eyeball /etc/passwd for users you don’t recognise. Skim /etc/cron.d/ for jobs you never scheduled. Run last -n 50 and look hard at any login that feels off. Anything weird on that list isn’t a “remind me next month.” It’s a “drop what I’m doing and dig in today.”

Recommended security gearWe may earn a commission, at no extra cost to you.
Yubikey Security KeyCheck price on Amazon →Password ManagerCheck price on Amazon →Usb Data BlockerCheck price on Amazon →Webcam Cover SlideCheck price on Amazon →

FAQ

Why change the SSH port if I am already using keys?

It’s not one or the other. The port move stacks on top of your keys, it doesn’t stand in for them. Bots sweeping the whole IPv4 range fling something like 90 percent of their attempts straight at port 22, so kicking SSH up to a high port drags my logs from ten thousand failed hits a day down to a handful, and sshd quits burning cycles saying no. Is it security through obscurity? Yeah, totally, I won’t pretend it’s clever. But bolted onto keys it costs me nothing and it quietly works, so on it goes every time.

UFW or nftables directly, which to choose?

UFW, for pretty much everything. The config reads clean and the syntax is genuinely hard to fumble, and that covers a normal app server with room to spare. Go down to raw nftables only when you truly need the fancy stuff UFW can’t express, like port knocking or GeoIP filtering or really tight rate limiting. And honestly you don’t have to choose: drop raw rules into /etc/ufw/before.rules and you extend UFW without tearing it out.

Can automatic updates break my server?

It can. It very rarely does. Out of the box unattended-upgrades only pulls from the -security sources, so you’re getting critical patches and none of the big version jumps that actually wreck things. On an LTS the odds of it biting you are genuinely tiny. The one knob I do turn on anything important: kill the automatic reboot (Automatic-Reboot "false") and reboot the thing myself in a maintenance window, so it doesn’t drop mid-afternoon with users still on it.

AppArmor or SELinux?

On Ubuntu? AppArmor, no contest. Could you swap in SELinux instead? Sure, technically. But you’d rip out AppArmor and rewrite every profile from scratch first, and for most setups that’s a mountain of effort that gets you nothing real. SELinux earns its keep over on the RHEL side of the world (CentOS Stream, Rocky, and friends), where it’s the native choice and the whole distro is already wired around it. Just go with whatever your distro ships and expects.

Should I encrypt the disks of a VPS?

On a VPS, where someone else owns the hypervisor, LUKS buys you less than you’d hope. The key has to live somewhere, and that somewhere is usually decrypted in RAM the second the box boots, so a datacenter operator who can reach the storage can still read your data. Mostly theatre in that setting, honestly. Where disk encryption genuinely pulls its weight is bare metal, or a secondary data volume locked with dm-crypt and a key you keep well off the machine.

How do I audit the server 6 months after hardening?

A handful of free tools carry this, and they’re the only ones I bother with. Lynis (apt install lynis; lynis audit system) hands you a hardening score plus a punch list of everything that’s still soft. OpenSCAP with the “Standard System Security Profile for Ubuntu” comes out only when you’re in a regulated shop and need the paper trail. For sniffing out rootkits, that’s chkrootkit and rkhunter. I run Lynis once a quarter, and the rootkit scanners stay in the drawer until something actually feels wrong.

PeopleAreGeek tools to go further

SecurityWatch (multi-site monitoring) SecuChecker (WordPress audit) HTTP Headers Checker SSL Certificate Checker TLS Version Selector Companion: WordPress Security Audit in 10 Steps Developer Error Fix Hub

Sources & further reading

  • Ubuntu, Security
  • CIS Benchmarks
ShareTweetPin
People Are Geek

People Are Geek

I'm Stephane, a network and systems engineer with over 15 years of hands-on experience on production infrastructure, virtualization (ESXi, Proxmox), networking, and self-hosting. Earlier in my career I built and ran a Linux resource site that became a well-known reference for sysadmins. Today I focus on cybersecurity, and I also work as a technical trainer, teaching networking and security to people who do it for a living. Everything on People Are Geek comes from real-world practice, not theory. I build every tool on this site myself, and I write about what I've actually deployed, broken, and fixed. If it's here, I've used it.

People Are Geek

Copyright © 2017 JNews.

Navigate Site

  • About PeopleAreGeek
  • Affiliate Disclosure
  • All Tools and Articles
  • Contact
  • Cookie Policy
  • Hyper-V Hub: Tools, Error Fixes and Lab Guides
  • Linux Hub: Cross-Distro Reference, Articles, Tools
  • Privacy Policy
  • Sample Page
  • Terms of Service
  • VMware vSphere & ESXi Hub: Tools, Error Fixes and Guides

Follow Us

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools

Copyright © 2017 JNews.