Overview
Use this checklist before deploying any server to production. Each item includes a brief rationale and verification command where applicable.
Operating System Configuration
-
Update all packages — Apply latest security patches
# Ubuntu/Debian sudo apt update && sudo apt upgrade -y # RHEL/CentOS sudo dnf update -y -
Remove unnecessary packages — Reduce attack surface
sudo apt autoremove -y dpkg --list | grep -i "telnet\|ftp\|rsh" -
Disable unused services — Only run what's needed
systemctl list-unit-files --type=service --state=enabled sudo systemctl disable <service-name> -
Configure automatic security updates — Unattended upgrades for critical patches
sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades -
Set hostname and timezone — Consistent identification and log correlation
hostnamectl set-hostname prod-web-01 timedatectl set-timezone UTC -
Configure NTP synchronization — Accurate timestamps for logs and certificates
timedatectl status | grep "NTP synchronized"
User Access Controls
-
Disable root SSH login — Force use of named accounts
# /etc/ssh/sshd_config PermitRootLogin no -
Enforce SSH key-only authentication — No password login over SSH
PasswordAuthentication no PubkeyAuthentication yes -
Configure SSH on non-standard port — Reduce automated scanning noise
Port 2222 # or your chosen port -
Set SSH idle timeout — Auto-disconnect inactive sessions
ClientAliveInterval 300 ClientAliveCountMax 2 -
Create individual admin accounts — No shared credentials
useradd -m -G sudo -s /bin/bash admin-dylan -
Enforce password complexity — Minimum length and character requirements
# /etc/security/pwquality.conf minlen = 14 minclass = 3 -
Configure sudo logging — Track privileged operations
# /etc/sudoers.d/logging Defaults logfile="/var/log/sudo.log" -
Set account lockout policy — Brute force protection
# /etc/pam.d/common-auth auth required pam_faillock.so deny=5 unlock_time=900
Network Security
-
Configure firewall (UFW/iptables) — Default deny, explicit allow
sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 2222/tcp # SSH sudo ufw allow 443/tcp # HTTPS sudo ufw enable -
Disable unused network protocols — Remove IPv6 if not needed
# /etc/sysctl.conf net.ipv6.conf.all.disable_ipv6 = 1 -
Enable SYN flood protection — Kernel-level DDoS mitigation
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 -
Disable ICMP redirects — Prevent route manipulation
net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 -
Enable IP spoofing protection — Reverse path filtering
net.ipv4.conf.all.rp_filter = 1 -
Disable IP forwarding — Unless acting as a router
net.ipv4.ip_forward = 0
File System Security
-
Set proper file permissions — Restrict sensitive files
chmod 600 /etc/shadow chmod 644 /etc/passwd chmod 700 /root -
Configure /tmp with noexec — Prevent execution from temp directories
# /etc/fstab tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0 -
Enable file integrity monitoring — Detect unauthorized changes
sudo apt install aide sudo aideinit -
Set sticky bit on world-writable dirs — Prevent file deletion by non-owners
chmod +t /tmp /var/tmp -
Disable core dumps — Prevent memory exposure
# /etc/security/limits.conf * hard core 0
Logging & Monitoring
-
Configure centralized logging — Forward to SIEM/log aggregator
# /etc/rsyslog.d/50-remote.conf *.* @@siem.internal:514 -
Enable audit logging — Track system calls and file access
sudo apt install auditd sudo systemctl enable auditd -
Monitor authentication logs — Watch for brute force attempts
tail -f /var/log/auth.log -
Set log rotation — Prevent disk exhaustion
# /etc/logrotate.d/syslog /var/log/syslog { weekly, rotate 12, compress } -
Configure disk space alerts — Early warning for storage issues
df -h | awk '$5 > 80 {print $0}'
Application Security
-
Run services as non-root — Principle of least privilege
# systemd service file User=appuser Group=appgroup -
Enable AppArmor/SELinux — Mandatory access controls
sudo aa-status # AppArmor sestatus # SELinux -
Configure TLS 1.2+ only — Disable legacy protocols
# nginx ssl_protocols TLSv1.2 TLSv1.3; -
Set security headers — CSP, HSTS, X-Frame-Options
add_header Strict-Transport-Security "max-age=63072000" always; add_header X-Content-Type-Options "nosniff" always;
Verification
-
Run vulnerability scan — Automated assessment
sudo lynis audit system -
Test firewall rules — Verify only expected ports open
nmap -sS -p- localhost -
Verify SSH configuration — Check hardening applied
sshd -T | grep -E "permitrootlogin|passwordauthentication|port" -
Review running processes — Confirm no unauthorized services
ps aux | grep -v "\[" | sort -nrk 3 -
Document changes — Record all modifications for audit trail
Quick Reference
| Area | Key Actions | Priority |
|---|---|---|
| OS Updates | Patch + auto-update | Critical |
| SSH | Key-only, no root, non-standard port | Critical |
| Firewall | Default deny, explicit allow | Critical |
| Users | Individual accounts, sudo logging | High |
| Logging | Centralized + audit | High |
| TLS | 1.2+ only, strong ciphers | High |
| File System | Permissions, integrity monitoring | Medium |