Most security breaches don't exploit zero-days. They exploit known misconfigurations — default passwords, unrestricted SSH, missing patches. This checklist covers every step you should take before a Linux server goes live in production. Commands are tested on Ubuntu 22.04 LTS and work on Debian 12.
Apply all steps before your server goes live. Re-applying security controls to a running production server is risky and much harder to do safely.
1. Access Control
✅ SSH key-only authentication
# Edit /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
PermitRootLogin no # Use sudo from a regular user
MaxAuthTries 3
ClientAliveInterval 300 # Disconnect idle sessions after 5 min
AllowUsers your-username # Whitelist specific users
sudo systemctl restart sshd
✅ Use ed25519 keys (not RSA 2048)
ssh-keygen -t ed25519 -C "your@email.com"
✅ Create a non-root sudo user
adduser deploy
usermod -aG sudo deploy
# Copy your public key to the new user
su - deploy
mkdir ~/.ssh && chmod 700 ~/.ssh
echo "YOUR_PUBLIC_KEY" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
✅ Change the default SSH port (optional but reduces noise)
# /etc/ssh/sshd_config
Port 2222 # Or any port above 1024
# Update your firewall rule to match the new port
On VeloxaHost, skip this step unless your server has a dedicated IPv4 address. The first port of your server's block on the region's shared IPv4 address forwards to port 22, so moving sshd to another port breaks SSH over the shared address (ssh -p <port> root@<shared-ip>). Also create the sudo user below and confirm you can log in with it before setting PermitRootLogin no: servers are reached as root to begin with.
2. Firewall
✅ Enable UFW with default deny
sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow only what you need
sudo ufw allow from YOUR_IP to any port 22 # SSH from your IP only
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
sudo ufw status verbose
VeloxaHost's network-level firewall blocks traffic before it reaches your instance's kernel — once you attach one: until then, traffic is allowed (only outbound TCP port 25 is blocked by default). Create one under Firewalls → New Firewall and attach it on the server's page. UFW adds a second layer at the OS. Run both.
3. Brute Force Protection
✅ Install and configure fail2ban
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Minimal jail.local configuration:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
maxretry = 3
sudo systemctl enable --now fail2ban
See the full setup guide: fail2ban complete setup →
4. Automatic Security Updates
✅ Enable unattended-upgrades
sudo apt install unattended-upgrades apt-listchanges -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
Verify it's working:
sudo systemctl status unattended-upgrades
cat /etc/apt/apt.conf.d/20auto-upgrades
The output should include:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
5. Audit Logging
✅ Install auditd
sudo apt install auditd audispd-plugins -y
sudo systemctl enable --now auditd
✅ Add critical audit rules
# /etc/audit/rules.d/hardening.rules
# Log all authentication events
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k privileged
# Log sudo usage
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -k privileged
# Log SSH logins
-w /var/log/auth.log -p wa -k auth
sudo augenrules --load
✅ View audit logs
# Recent logins
ausearch -k auth -ts recent
# All sudo commands
ausearch -k privileged -ts today
6. Kernel Security Parameters
✅ Harden /etc/sysctl.conf
cat >> /etc/sysctl.d/99-hardening.conf <<'EOF'
# Disable IP forwarding (unless this is a router)
net.ipv4.ip_forward = 0
# Prevent SYN flood attacks
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
# Log martian packets (packets with impossible source addresses)
net.ipv4.conf.all.log_martians = 1
# Disable IPv6 if not in use
net.ipv6.conf.all.disable_ipv6 = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-hardening.conf
7. Minimize Attack Surface
✅ Disable unused services
# List all running services
systemctl list-units --type=service --state=running
# Disable anything you don't need
sudo systemctl disable --now avahi-daemon
sudo systemctl disable --now bluetooth
sudo systemctl disable --now cups
✅ Remove unnecessary packages
sudo apt autoremove --purge -y
sudo apt clean
8. Secrets & Application Security
✅ Never hardcode credentials
- Load all secrets from environment variables or a secrets manager
- Use
.envfiles withchmod 600 .env - Rotate secrets immediately if they're ever committed to git
✅ Check for exposed sensitive files
# Find world-readable .env files
find / -name ".env" -perm /o+r 2>/dev/null
# Find SUID binaries (potential privilege escalation)
find / -perm -4000 -type f 2>/dev/null
9. Monitoring & Alerting
✅ Set up CPU and memory alerts
In VeloxaHost console, go to Alerts in the sidebar and create alert rules for the following (rules are checked every 5 minutes and cover CPU, memory, disk and server status):
- CPU usage > 85% (application malfunction or crypto mining)
- Memory usage > 90% (OOM risk)
- Disk usage > 80% (application or logs filling up)
✅ Watch auth.log for failed logins
# Live tail of authentication events
sudo tail -f /var/log/auth.log | grep -i "fail\|invalid\|error"
# Count failed login attempts by IP
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head -20
Final Checklist
- ✅ SSH key-only, no root login, no password auth
- ✅ Non-root sudo user created
- ✅ UFW firewall — deny-all inbound, allowlist only needed ports
- ✅ fail2ban — 3 attempts triggers 1-hour ban
- ✅ unattended-upgrades — daily security patch install
- ✅ auditd — all privileged actions logged
- ✅ sysctl hardening — SYN flood protection, redirects disabled
- ✅ Unnecessary services disabled
- ✅ No hardcoded secrets anywhere
- ✅ Monitoring alerts configured
Attach a VeloxaHost network-level firewall to your instances, then add your OS-level hardening and you have a defense-in-depth setup. Deploy a hardened instance →