Skip to content
Back to Blog
Security11 min read

Server Security Hardening: 8 Steps to Lock Down Linux

Fresh Linux servers ship with defaults built for convenience, not defense. Here are the exact commands and config changes to harden yours before production.

Written by Abdul AbrorTechnical Hosting Support Engineer
Server Security Hardening: 8 Steps to Lock Down Linux
On this page

Fresh Linux servers ship with defaults built for convenience, not defense. Root login over SSH is enabled. The firewall accepts everything. Services you'll never use are listening on public interfaces. Before your server touches production traffic, you need to lock it down.

I've restored compromised servers where the first SSH brute-force took under six hours. The pattern is always the same: default configs, no firewall, root password authentication. This guide walks through eight hardening steps with exact commands. No theory—just the changes that matter.

Create a sudo user and disable root login

Never run SSH as root in production. Create a dedicated user with sudo privileges first.

adduser deploy
usermod -aG sudo deploy

Test that sudo works before you disable root:

su - deploy
sudo whoami
# Should print: root

Once confirmed, edit /etc/ssh/sshd_config and change this line:

PermitRootLogin no

Restart SSH to apply:

sudo systemctl restart sshd

Keep your current root session open until you've verified the new user can log in from a second terminal. If you lock yourself out, your hosting panel's VNC or console access will save you.

Set up SSH key authentication and disable passwords

Password authentication is the entry point for every brute-force attack I've debugged in support tickets. SSH keys fix this.

On your local machine, generate a key pair if you don't have one:

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

Copy the public key to your server:

ssh-copy-id deploy@your_server_ip

Test key-based login in a new terminal before disabling passwords. Once confirmed, edit /etc/ssh/sshd_config:

PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

For extra hardening, restrict which users can SSH in:

AllowUsers deploy

Restart SSH:

sudo systemctl restart sshd

Password auth is now off. Attackers can hammer your SSH port all day and get nowhere.

Change the default SSH port

Port 22 gets constant automated scans. Moving SSH to a non-standard port cuts that noise by ninety percent—I've watched auth logs drop from hundreds of attempts per hour to almost nothing.

Pick a port above 1024 and below 65535. Avoid common alternates like 2222. Edit /etc/ssh/sshd_config:

Port 4822

Restart SSH:

sudo systemctl restart sshd

Update your firewall rules (covered next) before you log out, or you'll lock yourself out. Connect with:

ssh -p 4822 deploy@your_server_ip

This isn't security through obscurity—it's reducing attack surface. Bots scan port 22. They don't scan every high port on every IP.

Configure a firewall with UFW or firewalld

A fresh server usually has iptables installed but no active rules. Everything is allowed. Use UFW (Uncomplicated Firewall) on Ubuntu/Debian or firewalld on CentOS/RHEL.

UFW setup

Install UFW if it's missing:

sudo apt install ufw

Set default policies (deny incoming, allow outgoing):

sudo ufw default deny incoming
sudo ufw default allow outgoing

Allow your SSH port before enabling the firewall:

sudo ufw allow 4822/tcp

If you changed SSH to a non-standard port, use that number. Enable UFW:

sudo ufw enable

Check the status:

sudo ufw status verbose

Add rules for HTTP, HTTPS, or other services as needed:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

firewalld setup

On CentOS or RHEL:

sudo systemctl start firewalld
sudo systemctl enable firewalld

Add your SSH port to the permanent zone:

sudo firewall-cmd --permanent --add-port=4822/tcp
sudo firewall-cmd --reload

Add HTTP and HTTPS:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

List active rules:

sudo firewall-cmd --list-all

Default-deny is now enforced. Only explicitly allowed services are reachable.

Install and configure fail2ban

fail2ban watches your auth logs and bans IPs after repeated failed login attempts. Even with keys-only SSH, it's worth running—it blocks malicious traffic before it hits your service.

Install on Ubuntu/Debian:

sudo apt install fail2ban

On CentOS/RHEL:

sudo yum install epel-release
sudo yum install fail2ban

Create a local config file:

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

Edit /etc/fail2ban/jail.local and set these defaults:

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5

[sshd]
enabled = true
port = 4822

Adjust port to match your SSH config. Start and enable fail2ban:

sudo systemctl start fail2ban
sudo systemctl enable fail2ban

Check banned IPs:

sudo fail2ban-client status sshd

fail2ban will now ban any IP that fails five login attempts in ten minutes.

Disable unnecessary services and open ports

Fresh installs often run services you don't need. Each one is a potential entry point.

List all listening ports:

sudo ss -tulnp

Or use netstat if ss isn't available:

sudo netstat -tulnp

Look for services you didn't install or don't recognize. Common culprits: rpcbind, avahi-daemon, cups (printing service).

Stop and disable unused services. For example, to disable rpcbind:

sudo systemctl stop rpcbind
sudo systemctl disable rpcbind

Repeat for any service you don't need. If you're not sure what a service does, search its name—don't just disable everything.

On a minimal web server, you should only see SSH, HTTP/HTTPS, and maybe a database port (which should be firewalled from public access).

Keep the system updated and enable automatic security patches

Unpatched servers get compromised. Set up automatic security updates so you don't have to remember.

On Ubuntu/Debian, install unattended-upgrades:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Edit /etc/apt/apt.conf.d/50unattended-upgrades and ensure this line is uncommented:

"${distro_id}:${distro_codename}-security";

This enables automatic security patches. Critical updates install overnight without manual intervention.

On CentOS/RHEL, use dnf-automatic:

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

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

apply_updates = yes

Manually update everything right now:

sudo apt update && sudo apt upgrade -y  # Debian/Ubuntu
sudo yum update -y                      # CentOS/RHEL

Reboot if kernel updates were installed:

sudo reboot

Harden shared memory and kernel parameters

Shared memory can be exploited if mounted with execute permissions. Mount it read-only in /etc/fstab:

tmpfs /run/shm tmpfs defaults,noexec,nosuid 0 0

Remount to apply immediately:

sudo mount -o remount /run/shm

Add kernel hardening parameters to /etc/sysctl.conf:

# IP Spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0

# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Log Martians
net.ipv4.conf.all.log_martians = 1

# Ignore ICMP ping requests
net.ipv4.icmp_echo_ignore_all = 1

Apply the changes:

sudo sysctl -p

These settings close common network-level attack vectors. Disabling ICMP responses makes your server harder to discover in scans (though it also breaks ping).

FAQ

Do I really need to change the SSH port?
No, but it dramatically reduces log noise and stops automated scans. Key-based auth is the real defense; a non-standard port is just cleanup.

Will automatic updates break my application?
Security-only updates rarely break anything. If you're running custom-compiled software or ancient dependencies, test updates in staging first.

Can I skip fail2ban if I disabled password auth?
You can, but fail2ban protects more than SSH. It can watch web server logs, email auth, and other services. The overhead is negligible.

What if I lock myself out during hardening?
Use your hosting provider's console or VNC access to regain entry. Always test SSH config changes in a second terminal before closing your active session.

Before you point DNS at the server

These eight steps block the most common attack vectors I see in support tickets: brute-force SSH, exploited services, and kernel-level network abuse. Apply them to every server before you route production traffic.

After hardening, run a port scan from an external machine to verify only your intended services are visible. Check your auth logs daily for the first week to catch any misconfigurations early. Security isn't a checklist you complete once—it's a posture you maintain.