Skip to content
Back to Blog
Security8 min read

Server Security Hardening: 8 Commands to Run in 2026

Lock down your Linux server with eight essential command-line steps covering SSH keys, firewall rules, user permissions, and audit logging.

Written by Abdul AbrorTechnical Hosting Support Engineer
Server Security Hardening: 8 Commands to Run in 2026
On this page

Most breached servers I've seen shared one trait: they ran default configs. SSH on port 22 with password auth, no firewall rules, root login enabled. Hardening a fresh Linux box takes ten minutes and stops ninety percent of automated attacks before they start.

This guide walks through eight commands that lock down SSH access, configure a stateful firewall, disable unnecessary services, enforce permission policies, and capture security events. Run these on any Debian, Ubuntu, CentOS, AlmaLinux, or Rocky server before you point a domain at it.

1. Disable root SSH and enforce key-only authentication

Password-based SSH is the easiest door to kick in. Brute-force bots hammer port 22 around the clock.

First, generate an SSH key pair on your local machine if you don't already have one:

ssh-keygen -t ed25519 -C "[email protected]"

Copy the public key to your server:

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

Confirm you can log in with the key, then edit /etc/ssh/sshd_config:

sudo nano /etc/ssh/sshd_config

Set these directives:

PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

Restart SSH:

sudo systemctl restart sshd

Test the connection in a new terminal before closing your current session. If the key login fails, you still have the original session to fix it.

2. Change the default SSH port

Port 22 attracts every script kiddie on the planet. Moving SSH to a high port—say 2222 or 49152—drops automated scan traffic to near zero.

In /etc/ssh/sshd_config, change:

Port 49152

Restart SSH:

sudo systemctl restart sshd

From now on, connect with:

ssh -p 49152 user@your-server-ip

Remember to open the new port in your firewall before closing the old one, or you'll lock yourself out.

3. Configure UFW or firewalld with a default-deny policy

A firewall with no rules is a firewall that does nothing. Start with deny-all, then whitelist only the ports you need.

UFW (Ubuntu, Debian)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 49152/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw enable

Check status:

sudo ufw status verbose

firewalld (CentOS, AlmaLinux, Rocky)

sudo firewall-cmd --set-default-zone=drop
sudo firewall-cmd --zone=public --add-port=49152/tcp --permanent
sudo firewall-cmd --zone=public --add-service=http --permanent
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --reload

Verify:

sudo firewall-cmd --list-all

Drop any port you don't recognize. If you're running a web server, 80 and 443 stay open. Everything else should have a reason.

4. Install and enable fail2ban

fail2ban watches logs for repeated failed login attempts and bans the offending IP for a configurable period.

Install it:

sudo apt install fail2ban -y       # Debian/Ubuntu
sudo yum install fail2ban -y       # CentOS/RHEL

Create a local config:

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

Under [sshd], confirm:

enabled = true
port = 49152
maxretry = 3
bantime = 3600

Start and enable:

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check banned IPs:

sudo fail2ban-client status sshd

In support tickets I handled, fail2ban typically blocks dozens of IPs within the first day on a new server.

5. Disable unused network services

Every listening port is a potential attack surface. List what's running:

sudo ss -tulnp

You'll see SSH, your web server, maybe MySQL. Anything else? Investigate it.

Disable services you don't need:

sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now cups

Common unnecessary services on a typical VPS: Avahi (Zeroconf/Bonjour), CUPS (printing), Bluetooth, and sometimes Postfix if you're using an external SMTP relay.

6. Lock down file permissions on sensitive configs

World-readable config files leak credentials. SSH keys, database passwords, and application secrets should be locked to the owning user.

Set restrictive permissions on common targets:

sudo chmod 700 ~/.ssh
sudo chmod 600 ~/.ssh/authorized_keys
sudo chmod 600 /etc/ssh/sshd_config
sudo chmod 640 /etc/mysql/my.cnf
sudo chown root:root /etc/ssh/sshd_config

For web application config files (like WordPress wp-config.php):

sudo chown www-data:www-data /var/www/html/wp-config.php
sudo chmod 640 /var/www/html/wp-config.php

Run a quick audit:

sudo find /etc -type f -perm -o+w -ls

That finds world-writable files in /etc. Investigate any hits.

7. Enable automatic security updates

Patching is the most effective defense and the one admins skip most often. Automate it.

Debian/Ubuntu (unattended-upgrades)

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

Edit /etc/apt/apt.conf.d/50unattended-upgrades to enable automatic reboots if needed:

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";

CentOS/AlmaLinux/Rocky (dnf-automatic)

sudo yum install dnf-automatic -y
sudo systemctl enable --now dnf-automatic.timer

Edit /etc/dnf/automatic.conf and set:

apply_updates = yes

Automatic updates won't break a well-architected stack, but test them on a staging server first if you're cautious.

8. Configure auditd to log security events

auditd records file access, system calls, and privilege escalation attempts. It's your black box after an incident.

Install:

sudo apt install auditd -y         # Debian/Ubuntu
sudo yum install audit -y          # CentOS/RHEL

Add rules to watch sensitive files. Edit /etc/audit/rules.d/audit.rules:

-w /etc/passwd -p wa -k passwd_changes
-w /etc/shadow -p wa -k shadow_changes
-w /etc/ssh/sshd_config -p wa -k sshd_config_changes
-w /var/log/auth.log -p wa -k auth_log_changes

Reload rules:

sudo augenrules --load
sudo systemctl restart auditd

Search logs for specific events:

sudo ausearch -k passwd_changes

auditd logs fill up fast on busy servers. Rotate them regularly and ship to a central log collector if you manage multiple boxes.

What about SELinux or AppArmor?

If your distro ships with SELinux (RHEL family) or AppArmor (Ubuntu), leave it enabled. Both frameworks confine processes to predefined policies, limiting damage if an application gets compromised.

Check SELinux status:

sudo sestatus

If it's disabled, enable it by editing /etc/selinux/config:

SELINUX=enforcing

For AppArmor:

sudo aa-status

Don't disable MAC (mandatory access control) frameworks just because they trigger permission errors. Fix the policy instead.

How do I verify the changes stuck?

Reboot the server and run through this checklist:

  • Can you SSH in with your key on the custom port?
  • Does password auth fail?
  • Is the firewall active and showing your rules?
  • Are fail2ban and auditd running?
  • Do unused services stay stopped?
sudo systemctl is-active sshd ufw fail2ban auditd
sudo ufw status
sudo fail2ban-client ping

If any service is inactive, re-enable it and check logs:

sudo journalctl -u servicename -n 50

Start with SSH and the firewall

You don't need to run all eight commands in one sitting, but SSH and firewall config should happen before you install anything else. Disable root login, enforce keys, set a default-deny firewall policy, and you've already blocked most opportunistic attacks. The rest—fail2ban, auditd, automatic updates—add layers that catch what slips through. Run these eight commands on every new server and you'll spend less time cleaning up compromised boxes.

FAQ

Do I need all eight steps on a single-site VPS?

Yes. Automated scanners don't care if you're running one site or fifty. The attack surface is the same.

Will automatic updates break my production server?

Rarely, and only if your stack depends on a specific kernel or library version. Staging environments catch those issues. The risk of running unpatched software is higher.

Can I skip changing the SSH port if I use key-only auth?

You can, but moving the port cuts log noise by ninety-five percent and reduces CPU load from failed login attempts. It's a thirty-second change.

How often should I review audit logs?

Weekly at minimum. After any suspicious activity, immediately. Automate alerts for critical events like changes to /etc/passwd or sudo usage by non-admin accounts.

What if I lock myself out while hardening SSH?

Use your hosting provider's web console or recovery mode to regain access. Always test SSH changes in a second terminal before closing your active session.