You just got a fresh VPS. It's running, your app is deployed, and everything works. But here's the problem — so can attackers. A default Linux server is like a house with all the windows open. Within minutes of going online, bots are already trying to brute-force your SSH login.
Server security isn't optional. Here's how to lock things down properly, step by step.
The First 10 Minutes: Critical Setup
These steps should happen immediately after provisioning your server. Every minute your server runs with default settings is a minute it's vulnerable.
1. Update Everything
sudo apt update && sudo apt upgrade -y
Outdated packages are the #1 attack vector. Security patches fix known vulnerabilities that attackers actively exploit.
2. Create a Non-Root User
Never run your applications as root. Create a dedicated user:
adduser deploy
usermod -aG sudo deploy
Test that sudo works:
su - deploy
sudo whoami # Should output: root
From now on, use this user for everything.
3. Secure SSH Access
SSH is the front door to your server. Lock it down:
Disable root login and password authentication:
sudo nano /etc/ssh/sshd_config
Change these settings:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
Important: Before disabling password auth, make sure your SSH key is already added:
# On your local machine
ssh-copy-id deploy@your-server-ip
# Or manually add your public key
mkdir -p ~/.ssh
echo "your-public-key-content" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Restart SSH:
sudo systemctl restart sshd
Change the default SSH port (optional but reduces automated attacks by 99%):
Port 2222 # Pick any unused port between 1024-65535
4. Set Up a Firewall
UFW (Uncomplicated Firewall) is the simplest way to manage firewall rules on Ubuntu:
# Allow SSH (use your custom port if changed)
sudo ufw allow 22/tcp
# Allow web traffic
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable the firewall
sudo ufw enable
# Check status
sudo ufw status verbose
Rule of thumb: Only open ports you actively need. Everything else stays closed.
Automated Intrusion Prevention
Install Fail2Ban
Fail2Ban monitors log files and bans IPs that show malicious behavior (like repeated failed login attempts):
sudo apt install fail2ban -y
Create a local configuration:
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
banaction = ufw
[sshd]
enabled = true
port = 22
logpath = %(sshd_log)s
maxretry = 3
bantime = 86400
This bans any IP that fails SSH login 3 times within 10 minutes, for 24 hours.
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Check banned IPs
sudo fail2ban-client status sshd
Keep Software Updated Automatically
Security patches shouldn't wait for you to remember. Enable automatic security updates:
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
Verify it's working:
cat /etc/apt/apt.conf.d/20auto-upgrades
Should show:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Secure Your Web Server
Nginx Security Headers
Add these headers to your Nginx configuration to protect against common web attacks:
server {
# ... your existing config ...
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# Hide Nginx version
server_tokens off;
}
Rate Limiting
Prevent brute-force attacks on login pages and APIs:
# Define rate limit zone (in http block)
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# Apply to sensitive endpoints
location /wp-login.php {
limit_req zone=login burst=3 nodelay;
# ... proxy or fastcgi config ...
}
File Permissions
Incorrect file permissions are a common security hole:
# Web files: owner can read/write, group and others read only
find /var/www/html -type f -exec chmod 644 {} \;
find /var/www/html -type d -exec chmod 755 {} \;
# Sensitive config files
chmod 600 /var/www/html/.env
chmod 600 /var/www/html/wp-config.php
Never set 777 permissions on anything. If an app "needs" 777, fix the ownership instead:
sudo chown -R www-data:www-data /var/www/html
Monitor for Suspicious Activity
Check Auth Logs Regularly
# Failed login attempts
grep "Failed password" /var/log/auth.log | tail -20
# Successful logins
grep "Accepted" /var/log/auth.log | tail -20
# Currently logged-in users
who
Set Up Log Monitoring
Install Logwatch for daily email summaries:
sudo apt install logwatch -y
# Test it
sudo logwatch --detail high --range today --output stdout
Configure daily email reports:
sudo nano /etc/logwatch/conf/logwatch.conf
MailTo = you@yourdomain.com
Detail = Med
Range = yesterday
Database Security
If you're running MySQL or PostgreSQL:
# MySQL: Run the security script
sudo mysql_secure_installation
This will:
- Set a root password
- Remove anonymous users
- Disable remote root login
- Remove test databases
Never expose your database port to the internet. Keep it listening on localhost only:
# /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = 127.0.0.1
Backup Strategy
Security includes recovery. Set up automated backups:
#!/bin/bash
# backup.sh — Run daily via cron
DATE=$(date +%Y-%m-%d)
BACKUP_DIR="/home/deploy/backups"
# Database backup
mysqldump -u root --all-databases | gzip > $BACKUP_DIR/db-$DATE.sql.gz
# Files backup
tar -czf $BACKUP_DIR/files-$DATE.tar.gz /var/www/html/
# Keep only last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete
# Add to cron (runs at 3 AM daily)
crontab -e
0 3 * * * /home/deploy/backup.sh
Critical: Store backups off-server too. Use rsync or rclone to copy to a separate location.
Security Checklist
Run through this after every new server setup:
- System packages updated
- Non-root user created
- SSH key authentication only (passwords disabled)
- Root SSH login disabled
- Firewall enabled (only needed ports open)
- Fail2Ban installed and configured
- Automatic security updates enabled
- Web server security headers added
- File permissions corrected
- Database secured and localhost-only
- Automated backups configured
- SSL/HTTPS enabled
Stay Secure Without the Headache
Server security is an ongoing process, not a one-time setup. But getting these fundamentals right blocks the vast majority of attacks. Most compromised servers weren't hacked by sophisticated exploits — they were breached through default passwords, outdated software, or open ports.
At DeployBase, security is built into our infrastructure. Every VPS comes with firewall management, DDoS protection, and automated security patching. Our managed hosting plans include Fail2Ban configuration, SSL certificates, and daily backups — so you can focus on building your application instead of hardening your server.
Get secure VPS hosting at DeployBase → — because your server's security shouldn't keep you up at night.




