FR EN
Security — Hardening

Security Checklist
Linux & Windows Servers

CIS Benchmark checkpoints, ANSSI recommendations and DevSecOps best practices to secure your production servers.

AuthorSOL-IT Solutions Informatiques
Version1.0 — 2026
FrameworksCIS Benchmark · ANSSI · OWASP
OS coveredUbuntu/Debian · CentOS/RHEL · Windows Server

Severity Levels

Critical — Fix immediately, direct intrusion risk
High — Fix within 48 hours
Medium — Address in current sprint
Info — Recommended best practice
0%

Compliance Score: Not started

0 / 0 points validated

🔐

1. SSH Configuration

Primary attack surface on any exposed Linux server

CheckpointPriority
Disable root SSH login
PermitRootLogin no
In /etc/ssh/sshd_config — prevents brute force attacks on root
Critical
Key-only authentication
PasswordAuthentication no
Disable SSH passwords, use RSA/Ed25519 keys only
Critical
Change default SSH port
Port 2222
Reduces automated scans on port 22
High
Restrict allowed SSH users
AllowUsers deployer admin
Only listed users can connect via SSH
High
Inactive session timeout
ClientAliveInterval 300 / ClientAliveCountMax 2
Disconnects inactive sessions after 10 minutes
Medium
Use Ed25519 keys (not RSA 1024/2048)
ssh-keygen -t ed25519 -C "deployer@server"
Ed25519 is more secure and faster than RSA
Medium
Disable X11 forwarding
X11Forwarding no
Reduces attack surface
Info
🔥

2. Firewall and Network

Restriction of inbound and outbound network access

CheckpointPriority
Active firewall (UFW / firewalld / iptables)
ufw enable && ufw default deny incoming
Default policy: block everything, allow explicitly
Critical
Open only necessary ports
ufw allow 443/tcp && ufw allow 2222/tcp
80 (redirect → 443), 443 (HTTPS), SSH port only
Critical
Block direct database access
PostgreSQL/MySQL must never be accessible from outside (ports 5432/3306 closed)
Critical
Enable fail2ban
apt install fail2ban && systemctl enable fail2ban
Automatically blocks IPs after X failed attempts
High
Disable IPv6 if unused
net.ipv6.conf.all.disable_ipv6 = 1
In /etc/sysctl.conf — reduces attack surface
Medium
Enable UFW connection logging
ufw logging on
Traceability of connection attempts
Info
👤

3. User and Permission Management

Principle of least privilege

CheckpointPriority
Disable root account (Linux)
passwd -l root
Use sudo instead of direct root
Critical
Create a dedicated deploy user
adduser deployer && usermod -aG sudo deployer
Never deploy with a personal or root user
High
Passwordless sudo only for required commands
deployer ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx
Limit NOPASSWD to specific necessary commands only
High
Check for users with UID 0
awk -F: '$3 == 0 {print}' /etc/passwd
Only root should have UID 0
High
Sensitive file permissions
chmod 600 /etc/ssh/sshd_config && chmod 640 /var/log/auth.log
Config files not readable by ordinary users
Medium
Strong password policy
apt install libpam-pwquality
Minimum 12 characters, complexity requirements, expiration
Medium
🔄

4. Updates and Patches

Most intrusions exploit known unpatched vulnerabilities

CheckpointPriority
System up to date at deployment time
apt update && apt upgrade -y && apt autoremove -y
Always deploy on a patched OS
Critical
Enable automatic security updates
dpkg-reconfigure -plow unattended-upgrades
Security patches applied automatically
High
Remove unnecessary packages
apt-get remove --purge telnet ftp rsh-server
Each installed package is a potential attack surface
Medium
Audit application dependencies (composer audit, npm audit)
composer audit && npm audit
CVEs in application libraries
Medium
🌐

5. Application and Web Security

Nginx, HTTPS, security headers

CheckpointPriority
HTTPS mandatory with TLS 1.2+ only
ssl_protocols TLSv1.2 TLSv1.3;
Disable SSLv3, TLS 1.0 and TLS 1.1 in Nginx/Apache
Critical
HTTP security headers
add_header X-Frame-Options "SAMEORIGIN";
X-Frame-Options, X-XSS-Protection, X-Content-Type-Options, HSTS, CSP
Critical
Hide web server version
server_tokens off;
Don't expose Nginx/Apache version to attackers
High
Environment variables — never in code
API keys, DB passwords, JWT secrets must be in .env (gitignored) or system environment variables
Critical
.env absent from Git repository
echo ".env" >> .gitignore && git rm --cached .env
Verify Git history: no secret should have been committed
Critical
Rate limiting on authentication endpoints
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
Brute force prevention on /login, /api/auth
High
APP_DEBUG=false in production
Never display stack traces and system information to users
High
📊

6. Logs, Audit and Monitoring

Incident detection and traceability

CheckpointPriority
Centralized logs (journald, syslog, ELK...)
journalctl -u nginx --since "1 hour ago"
Application, system and security logs centralized and retained ≥ 90 days
High
Monitor failed SSH connections
grep "Failed password" /var/log/auth.log | tail -20
Alerts on ≥ 10 attempts from the same IP
High
Uptime and resource consumption alerts
CPU > 90%, memory > 85%, disk > 80% → email/Slack notification
Medium
Immutable application audit trail
Every sensitive action (create/update/delete data) must be logged with user, timestamp and IP
Medium
Documented incident response plan
Who to contact, what actions to take in case of intrusion detection
Info
💾

7. Backups and Disaster Recovery

An untested backup is not a backup

CheckpointPriority
Automated daily database backups
pg_dump dbname | gzip > backup_$(date +%Y%m%d).sql.gz
Stored outside the production server (S3, another VPS, NAS)
Critical
Backup retention ≥ 30 days
Ability to restore a previous version in case of ransomware attack or corruption
High
Monthly restore test
Verify that the restore actually works on a test environment
High
Encrypted backups
gpg --symmetric --cipher-algo AES256 backup.sql.gz
Backups contain sensitive data — encrypt them at rest
Medium