How to Secure Your Linux Server: A Practical Hardening Guide

Overview

Linux security isn’t a one-time checkbox — it’s a set of deliberate configuration decisions you make when a server is first provisioned and maintain over time. Out of the box, most Linux distributions prioritise compatibility over security, which means sensible defaults for a desktop but dangerous gaps on a public-facing server.

If you’ve just spun up a VPS SSD Hosting instance or a dedicated server, this guide walks you through the baseline hardening steps I’d consider non-negotiable. Some steps take 30 seconds. A few take more thought. All of them matter.

This guide targets Ubuntu 22.04 LTS and Debian 12, but the concepts and most commands apply directly to AlmaLinux 9, Rocky Linux 9, and other common server distributions. Where commands differ, I’ve noted it.

Prerequisites

  • Root or sudo access to the server
  • SSH access from your local machine
  • A non-root user account already created (we’ll cover this if you haven’t done it yet)
  • Ubuntu 22.04 LTS, Debian 12, AlmaLinux 9, or Rocky Linux 9 — commands assume one of these
  • Basic comfort running commands in a terminal
  • A backup of any existing configuration if hardening a live server

Step-by-Step Instructions

Step 1: Update All Packages First

Before anything else, patch the system. Known vulnerabilities in outdated packages are the most common entry point on compromised servers.

On Ubuntu/Debian:

apt update && apt upgrade -y && apt autoremove -y

On AlmaLinux/Rocky Linux:

dnf update -y && dnf autoremove -y

Reboot after a kernel update:

reboot

Step 2: Create a Non-Root User with Sudo Access

Never run day-to-day operations as root. If an attacker gets command execution under your session, root means game over. A sudo user limits the blast radius.

adduser deploy
usermod -aG sudo deploy

On AlmaLinux/Rocky, the sudo group is called wheel:

usermod -aG wheel deploy

Switch to the new user and verify sudo works before you touch SSH config:

su - deploy
sudo whoami

It should return root. If it doesn’t, stop and fix group membership before proceeding.

Step 3: Lock Down SSH

SSH is the most attacked service on any public server. The default configuration is far too permissive.

Open the SSH config file:

sudo nano /etc/ssh/sshd_config

Make the following changes:

# Change the default port (22 is scanned constantly)
Port 2222

# Disable root login entirely
PermitRootLogin no

# Disable password authentication — use keys only
PasswordAuthentication no

# Limit to specific user(s)
AllowUsers deploy

# Disable unused authentication methods
X11Forwarding no
PermitEmptyPasswords no

# Reduce login timeout
LoginGraceTime 30

Warning: Do NOT restart SSH yet. Set up key-based authentication first (Step 4) and confirm it works in a second terminal window before closing your current session. Locking yourself out of a remote server is a real problem, and recovery usually means booting into rescue mode through your hosting control panel.

Step 4: Set Up SSH Key Authentication

On your local machine (not the server), generate a key pair if you don’t have one:

ssh-keygen -t ed25519 -C "your_email@example.com"

Ed25519 is preferred over RSA in 2026. It’s faster and produces shorter keys that are harder to brute-force.

Copy the public key to the server:

ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@your-server-ip

If ssh-copy-id isn’t available (Windows, for example), manually append the contents of id_ed25519.pub to ~/.ssh/authorized_keys on the server.

Now restart SSH:

sudo systemctl restart sshd

In a new terminal window, test login before closing the original:

ssh -p 2222 deploy@your-server-ip

📝 Note: If your server is managed through cPanel/WHM, check whether WHM enforces its own SSH settings under Security Center > SSH Password Authorization Tweak — your manual edits can get overwritten during updates.

Step 5: Configure a Firewall

UFW (Uncomplicated Firewall) ships with Ubuntu and works well for most VPS setups. On AlmaLinux/Rocky, firewalld is the default — I’ll cover both.

UFW (Ubuntu/Debian):

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp    # Your new SSH port
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

firewalld (AlmaLinux/Rocky):

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --remove-service=ssh   # Removes default port 22
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Warning: If you’re on a Host & Tech dedicated server with a hardware firewall in front, make sure the rule changes are consistent at both layers. Blocking port 80 in UFW but leaving it open at the hardware level (or vice versa) creates confusing behaviour that’s hard to debug.

Step 6: Install and Configure Fail2Ban

Fail2Ban monitors log files and temporarily bans IPs that show signs of brute-force attacks. It’s not a silver bullet, but it cuts noise significantly.

sudo apt install fail2ban -y   # Ubuntu/Debian
# or
sudo dnf install fail2ban -y   # AlmaLinux/Rocky

Create a local config file so your changes survive package updates:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Find the [sshd] block and update it:

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600

Start and enable the service:

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

📝 Note: On AlmaLinux/Rocky, the auth log path is /var/log/secure, not /var/log/auth.log. Getting this wrong means Fail2Ban runs silently without actually watching SSH.

Step 7: Enable Automatic Security Updates

Missing a security patch because you forgot to log in for two weeks is an embarrassingly common way servers get compromised. Unattended upgrades cover security patches automatically without touching major version updates.

On Ubuntu/Debian:

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

On AlmaLinux/Rocky, use dnf-automatic:

sudo dnf install dnf-automatic -y
sudo nano /etc/dnf/automatic.conf

Set apply_updates = yes and upgrade_type = security, then enable the timer:

sudo systemctl enable --now dnf-automatic.timer

Step 8: Disable Unused Services

Every running service is a potential attack surface. Check what’s listening:

sudo ss -tulnp

If you see services you don’t recognise or don’t need, stop and disable them:

sudo systemctl stop servicename
sudo systemctl disable servicename

Common culprits on freshly provisioned servers: rpcbind, avahi-daemon, and cups. None of these belong on a headless web server.

Common Issues & Troubleshooting

Locked out of SSH after changing the port

This happens when the firewall rule for the new port wasn’t added before restarting SSH, or when a cloud provider’s security group still only allows port 22. Log into your server through the VNC/console access in your control panel. Re-open the SSH config, verify the port, and add the correct firewall rule before restarting again. On Host & Tech VPS plans, VNC access is available directly from the client portal.

Fail2Ban not banning IPs despite repeated failed logins

Almost always a wrong logpath. Run sudo fail2ban-client status sshd and check the File list line — if the path doesn’t exist or is empty, Fail2Ban can’t read it. On AlmaLinux/Rocky, change logpath to /var/log/secure. Also confirm SSH is actually writing to that log with sudo tail -f /var/log/auth.log while attempting a test login from another terminal.

UFW is active but traffic isn’t being blocked

If your VPS sits behind a network-level firewall (common on cloud infrastructure), UFW rules may not be the layer actually controlling traffic. Check whether your hosting provider has a separate firewall panel. On some setups, iptables rules applied by Docker or other tools can also conflict with UFW in ways that are confusing to trace. Run sudo iptables -L -n -v to see the full rule set.

SSH key authentication failing even after copying the key

The most common cause is wrong permissions on ~/.ssh or ~/.ssh/authorized_keys. SSH silently rejects keys if the permissions are too open. Fix with:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Also check that PubkeyAuthentication yes is set in /etc/ssh/sshd_config — it should be the default, but it occasionally gets commented out.

Unattended upgrades breaking a running application

This is rare for security-only updates, but it does happen with packages like PHP or OpenSSL that have tight version dependencies. I’d recommend reviewing /var/log/unattended-upgrades/unattended-upgrades.log after each run. If a specific package causes repeated issues, you can blacklist it in /etc/apt/apt.conf.d/50unattended-upgrades under the Unattended-Upgrade::Package-Blacklist section.

FAQ

Frequently Asked Questions

What is the first thing I should do to secure a new Linux server?

Update all packages immediately — that’s step one every time. Then create a non-root sudo user, lock down SSH to key-based authentication only, and set up a firewall before you do anything else. Skipping these on a public IP means your server is being actively probed within minutes of going online.

Is changing the SSH port actually worth it for security?

It won’t stop a targeted attack, but it eliminates almost all automated scanning noise. The vast majority of SSH brute-force attempts hit port 22 and nothing else. Changing to a non-standard port like 2222 or 2200 combined with Fail2Ban makes automated attacks essentially irrelevant. It’s a low-effort, meaningful reduction in log clutter and attack surface.

Do I need a firewall if my hosting provider already has one?

Yes. A network-level firewall from your provider and a host-based firewall like UFW serve different purposes. The provider firewall protects traffic entering the network; UFW controls what reaches individual processes on your server. Running both gives you defence in depth — if one is misconfigured, the other still holds. This is especially relevant on shared infrastructure or when you’re running multiple services on one server.

How do I check if my Linux server has already been compromised?

Start with last and lastb to check recent login history, and who to see active sessions. Check /var/log/auth.log (or /var/log/secure on RHEL-based systems) for unusual activity. Look for unexpected cron jobs with crontab -l and ls /etc/cron.*. Rootkits are harder to detect — tools like rkhunter and chkrootkit can help, though a truly compromised kernel may fool them.

Can I run these hardening steps on a managed WordPress hosting plan?

On Host & Tech managed WordPress hosting, the underlying server hardening is handled for you — OS updates, firewall rules, and SSH configuration are managed at the infrastructure level. These steps are primarily for VPS and dedicated server customers who have full root access and are responsible for their own server configuration.

SHARE THIS ARTICLE

Need help with your hosting?

Host & Tech provides 24/7 support for all VPS, dedicated, and shared hosting customers.

Scroll to Top