Skip to content
Back to Blog
Security10 min read

Server Security Checklist: Common Mistakes Admins Must Avoid

Even experienced admins make critical server security mistakes. Learn the most common configuration errors, authentication failures, and monitoring gaps—and discover the correct approach to secure your infrastructure.

Written by Abdul AbrorTechnical Hosting Support Engineer
Server Security Checklist: Common Mistakes Admins Must Avoid
On this page

Server security isn't just about applying patches and setting passwords. Years of supporting hosting environments have shown me that even experienced administrators make predictable, dangerous mistakes—often not from ignorance, but from rushed deployments, inherited configurations, or outdated habits. This guide walks through the most common server security mistakes I've seen repeatedly and shows you the correct approach for each.

Authentication and Access Control Mistakes

Mistake 1: Using Password Authentication for SSH

Password authentication remains enabled on countless production servers. Attackers run automated brute-force attempts against SSH ports constantly, and weak passwords fall quickly.

The correct approach:

Disable password authentication entirely and use SSH key pairs:

# Generate a strong SSH key pair (on your local machine)
ssh-keygen -t ed25519 -C "admin@yourserver"

# Copy the public key to your server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-ip

# On the server, edit SSH configuration
sudo nano /etc/ssh/sshd_config

Set these directives:

PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes

Restart SSH:

sudo systemctl restart sshd

Test your key-based login from a separate terminal session before closing your current one.

Mistake 2: Allowing Root Login

Permitting direct root SSH access creates unnecessary risk. If an attacker compromises your credentials, they immediately have full system control.

The correct approach:

Create a dedicated user account with sudo privileges:

# Create a new user
sudo adduser adminuser

# Add to sudo group (Debian/Ubuntu)
sudo usermod -aG sudo adminuser

# Or wheel group (CentOS/RHEL/AlmaLinux)
sudo usermod -aG wheel adminuser

Then disable root login in /etc/ssh/sshd_config:

PermitRootLogin no

This creates an audit trail—you'll see which user account performed administrative actions.

Mistake 3: Not Using Two-Factor Authentication

Relying solely on SSH keys or passwords leaves accounts vulnerable if credentials are compromised or keys are stolen.

The correct approach:

Implement two-factor authentication using Google Authenticator:

# Install required packages (Ubuntu/Debian)
sudo apt install libpam-google-authenticator

# Run as your user account (not root)
google-authenticator

Follow the prompts to generate a QR code, then edit /etc/pam.d/sshd and add:

auth required pam_google_authenticator.so

In /etc/ssh/sshd_config, set:

ChallengeResponseAuthentication yes
UsePAM yes

Restart SSH and test thoroughly before closing your session.

Firewall and Network Security Mistakes

Mistake 4: Running Without a Firewall

Many administrators assume their hosting provider's network firewall is sufficient and skip configuring host-based firewalls. This leaves services exposed if network-level protections fail or are misconfigured.

The correct approach:

Implement a host-based firewall using ufw (Uncomplicated Firewall) or firewalld:

# Ubuntu/Debian with ufw
sudo apt install ufw

# Allow SSH first (critical!)
sudo ufw allow 22/tcp

# Allow other required services
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Enable the firewall
sudo ufw enable

# Check status
sudo ufw status verbose

For CentOS/RHEL/AlmaLinux with firewalld:

sudo systemctl start firewalld
sudo systemctl enable firewalld

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

Implement default-deny policies: block everything except explicitly allowed services.

Mistake 5: Leaving Unnecessary Ports Open

Default server configurations often expose services like MySQL or Redis to the internet when they should only accept local connections.

The correct approach:

Audit listening services:

sudo ss -tulpn

For database services that don't need remote access, bind them to localhost only. In MySQL's /etc/mysql/mysql.conf.d/mysqld.cnf:

bind-address = 127.0.0.1

For Redis in /etc/redis/redis.conf:

bind 127.0.0.1

Restart services after changes and verify they're no longer exposed:

sudo systemctl restart mysql
sudo systemctl restart redis

Mistake 6: Using Default SSH Port

While security through obscurity isn't a complete defense, changing the default SSH port dramatically reduces automated attack attempts in server logs.

The correct approach:

Change the SSH port in /etc/ssh/sshd_config:

Port 2222

Update your firewall rules before restarting SSH:

sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
sudo systemctl restart sshd

Document the new port and update your SSH client configuration in ~/.ssh/config:

Host yourserver
    HostName server-ip
    Port 2222
    User adminuser

Update and Patch Management Mistakes

Mistake 7: Delaying Security Updates

Postponing security updates "until a maintenance window" allows known vulnerabilities to remain exploitable. I've seen servers compromised because critical patches sat unapplied for weeks.

The correct approach:

Enable automatic security updates for critical patches:

# Ubuntu/Debian
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow 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";

For CentOS/RHEL/AlmaLinux, configure yum-cron or dnf-automatic:

sudo yum install yum-cron
sudo systemctl enable yum-cron
sudo systemctl start yum-cron

Edit /etc/yum/yum-cron.conf and set:

apply_updates = yes

Manually review updates weekly and schedule maintenance for major version upgrades.

Mistake 8: Running Outdated Operating Systems

Continuing to run operating system versions past their end-of-life date leaves servers without security patches. This is especially common with older CentOS 6 or Ubuntu 16.04 installations.

The correct approach:

Plan upgrades well before EOL dates:

  • Review your distribution's support lifecycle
  • Test application compatibility on newer versions
  • Schedule migrations during low-traffic periods
  • Never skip major versions during upgrades

For in-place upgrades (Ubuntu example):

# Ensure current system is fully updated first
sudo apt update && sudo apt upgrade
sudo apt dist-upgrade

# Then upgrade
sudo do-release-upgrade

For production systems, provision a new server with the current OS version and migrate rather than upgrading in place.

File System and Permission Mistakes

Mistake 9: Incorrect File Permissions

Overly permissive file permissions (777, world-writable directories) are common in rushed troubleshooting but create security holes.

The correct approach:

Follow the principle of least privilege:

# Web application files
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;

# Configuration files with sensitive data
sudo chmod 600 /etc/myapp/config.ini
sudo chown appuser:appuser /etc/myapp/config.ini

# SSH keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Audit for dangerous permissions:

# Find world-writable files
sudo find / -type f -perm -002 -ls 2>/dev/null

# Find files with SUID bit set
sudo find / -perm -4000 -ls 2>/dev/null

Mistake 10: Not Securing Sensitive Configuration Files

Leaving database credentials, API keys, and other secrets in world-readable files or version control repositories is surprisingly common.

The correct approach:

# Store credentials in protected files
sudo mkdir -p /etc/myapp
sudo nano /etc/myapp/.env

# Set strict permissions
sudo chmod 600 /etc/myapp/.env
sudo chown appuser:appuser /etc/myapp/.env

Add sensitive files to .gitignore:

.env
*.key
*.pem
config/secrets.yml

For committed secrets, rotate them immediately—removing them from history isn't sufficient since they may have been cloned.

Logging and Monitoring Mistakes

Mistake 11: Not Monitoring Authentication Logs

Failing to review authentication logs means you won't notice brute-force attempts, successful breaches, or suspicious access patterns until damage is done.

The correct approach:

Regularly review authentication logs:

# Recent SSH logins
sudo lastlog

# Failed login attempts
sudo grep "Failed password" /var/log/auth.log | tail -20

# Successful logins
sudo grep "Accepted" /var/log/auth.log | tail -20

Implement fail2ban to automatically block repeated failed attempts:

sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Create /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 3600
findtime = 600

Mistake 12: Insufficient Disk Space for Logs

Log rotation failures due to full disks can mask security events and cause service disruptions.

The correct approach:

Configure proper log rotation in /etc/logrotate.d/:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 appuser appuser
}

Monitor disk usage:

# Check disk space
df -h

# Find largest directories
sudo du -sh /var/log/* | sort -h

Set up alerting when disk usage exceeds thresholds.

Service Configuration Mistakes

Mistake 13: Using Default Credentials

Default passwords for databases, control panels, and applications remain unchanged in countless deployments.

The correct approach:

Immediately change all default credentials during initial setup:

# MySQL root password
sudo mysql_secure_installation

# Create application-specific database users
mysql -u root -p
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'strong-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

Use a password manager to generate and store strong unique passwords. Never reuse passwords across services.

Mistake 14: Running Services as Root

Running application processes as the root user means any vulnerability in the application grants full system access.

The correct approach:

Create dedicated service accounts:

# Create a system user for the application
sudo useradd -r -s /bin/false appuser

# Set ownership
sudo chown -R appuser:appuser /opt/myapp

Configure systemd service files to use the dedicated user:

[Service]
User=appuser
Group=appuser
ExecStart=/opt/myapp/bin/start

Drop privileges in application code if the service must bind to privileged ports.

Backup and Recovery Mistakes

Mistake 15: Not Testing Backup Restoration

Creating backups without verifying you can restore them is like having a parachute you've never tested. I've seen admins discover corrupted backups only during emergencies.

The correct approach:

Schedule regular restoration tests:

# Automate backup verification
#!/bin/bash
BACKUP_FILE="/backups/db-$(date +%Y%m%d).sql.gz"

# Attempt restoration to test database
gunzip -c $BACKUP_FILE | mysql -u root -p test_restore_db

if [ $? -eq 0 ]; then
    echo "Backup verification successful"
    mysql -u root -p -e "DROP DATABASE test_restore_db;"
else
    echo "ALERT: Backup verification failed" | mail -s "Backup Failure" [email protected]
fi

Document restoration procedures and practice them quarterly.

Mistake 16: Storing Backups Only on the Same Server

Keeping backups exclusively on the server they're backing up means ransomware, hardware failure, or compromise destroys both production data and backups simultaneously.

The correct approach:

Implement the 3-2-1 backup rule: three copies, two different media types, one offsite.

# Sync backups to remote storage
rsync -avz --delete /backups/ user@backup-server:/remote-backups/

# Or use cloud storage
aws s3 sync /backups/ s3://mybucket/backups/

Encrypt backups before offsite transfer:

tar czf - /var/www | gpg --encrypt --recipient [email protected] > backup.tar.gz.gpg

Conclusion

Server security failures rarely result from sophisticated zero-day exploits—they come from mundane configuration mistakes: weak authentication, missing updates, overly permissive access, and inadequate monitoring. Every mistake in this guide represents real security incidents I've helped investigate and remediate.

The correct approaches outlined here aren't theoretical best practices—they're practical, proven configurations that significantly reduce your attack surface. Start with authentication hardening and firewall rules, then systematically address monitoring, updates, and backups. Security isn't a one-time checklist but an ongoing practice of verification, testing, and improvement.

Your server security is only as strong as your weakest configuration. Review this checklist, identify the gaps in your current setup, and address them before attackers do.

FAQ

How often should I audit server security configurations?

Perform comprehensive security audits quarterly and after any significant infrastructure changes. Run automated vulnerability scans weekly and review authentication logs daily.

What's the minimum security checklist for a new server?

At minimum: disable password authentication, enable host firewall, install security updates, remove unnecessary services, implement fail2ban, configure log rotation, and set up offsite backups.

Should I use SELinux or AppArmor?

Yes, use whichever is default for your distribution. SELinux ships with RHEL/CentOS/AlmaLinux; AppArmor comes with Ubuntu/Debian. Don't disable mandatory access controls—learn to work with them.

How do I balance security with administrative convenience?

Use SSH key forwarding and jump hosts rather than weakening authentication. Script repetitive secure tasks. The short-term convenience of weak security never justifies the long-term risk.

What should I do if I discover my server was compromised?

Immediately isolate the server from the network, preserve logs for forensics, notify stakeholders, restore from known-good backups to a new instance, and conduct a thorough post-incident review to prevent recurrence.