linux-server-security.md

Hardening a Linux Server: My Checklist After 50+ Deployments

2025-07-22LinuxDevOpsSecurity

Why Hardening Matters

Every server connected to the internet is probed within minutes of coming online. Automated bots scan for open SSH ports, weak passwords, and known vulnerabilities constantly. In my early days, I learned this the hard way — a server I deployed for a personal project was compromised within 48 hours because I left the default SSH configuration intact.

Since then, I have developed a checklist that I run on every new server before it sees any real traffic. Here is the distilled version.

Step 1: SSH First

SSH is the most attacked service on any Linux server. The first thing I do is change the default port, disable root login, and set up key-based authentication only.

# Disable password auth
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

# Change port (pick something obscure)
echo "Port 48291" >> /etc/ssh/sshd_config
systemctl restart sshd

I also create a non-root user with sudo access for daily operations. The root account should never be used for anything other than absolute emergencies.

Step 2: Firewall Setup

Every server should have a firewall that denies everything by default and only allows the specific ports you need. I use UFW for simplicity on Ubuntu/Debian systems.

ufw default deny incoming
ufw default allow outgoing
ufw allow 48291/tcp   # SSH (custom port)
ufw allow 80/tcp      # HTTP
ufw allow 443/tcp     # HTTPS
ufw enable

The key principle: if a port is not explicitly allowed, it should be blocked. No exceptions.

Step 3: Automatic Updates

Unpatched systems are the most common attack vector. I set up unattended-upgrades for security patches and configure a weekly cron job for full system updates.

Step 4: Fail2Ban and Monitoring

Fail2Ban monitors log files for suspicious activity and automatically bans IP addresses that show malicious signs — too many failed logins, port scanning, etc. Combined with a simple monitoring setup, you get decent protection without paying for enterprise tools.

The Human Factor

Tools and checklists are important, but the biggest security risk is always human error. I keep a documented runbook for every server, use infrastructure-as-code where possible, and never make manual changes in production without recording them. Automation is not just about efficiency — it is about eliminating the class of mistakes that come from tired humans typing commands at 2 AM.