Hardening a Linux Server: My Checklist After 50+ Deployments
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.