Ubuntu VPS initial server setup: the security guide
You just launched your Ubuntu VPS. Before deploying anything, lock it down. This guide covers the essentials: create a non-root user, set up SSH key authentication, configure your firewall, harden your system, and enable automated security updates — all in 30 minutes.
Why initial setup matters
A fresh Ubuntu VPS comes with default settings that expose it to attack. Within minutes of going online, your server will receive thousands of brute-force login attempts. This guide hardens your server before that happens:
Timeline: Most attacks on new servers happen within the first hour. Complete this guide immediately after launching your VPS.
Step 1: Update packages and set timezone
First, update your system packages to patch known vulnerabilities:
sudo apt update sudo apt upgrade -y
Set your timezone (this ensures cron jobs and logs use the correct time):
sudo timedatectl set-timezone America/New_York # Replace America/New_York with your timezone. List all with: timedatectl list-timezones
Verify the timezone was set:
timedatectl
Step 2: Create a non-root user with sudo privileges
Never use root for daily operations. Create a dedicated user account (replace "deploy" with your preferred username):
# Create a new user sudo adduser deploy # Add the user to the sudo group (grants admin privileges) sudo usermod -aG sudo deploy
When prompted, enter a strong password and fill in optional details (or press Enter to skip them). Verify the user was created:
id deploy
You should see groups=...sudo in the output.
Best practice: All day-to-day work (including deployments) should happen under the non-root user. Use sudo only when necessary (e.g., restarting services, modifying system files).
Step 3: Set up SSH key authentication
SSH keys are far more secure than passwords. If you haven't generated an SSH key yet, do that on your local machine:
# On your local computer (not the VPS): ssh-keygen -t ed25519 -C "your-email@example.com"
Press Enter for default location and optionally set a passphrase. Now copy your public key to your VPS. SSH into your VPS as root, then add your public key:
# On your local computer: ssh-copy-id -i ~/.ssh/id_ed25519 deploy@your-vps-ip # Or manually: cat ~/.ssh/id_ed25519.pub | ssh deploy@your-vps-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Set proper permissions on the VPS (SSH into the server as your new user and run):
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
Test SSH key login from your local machine:
ssh -i ~/.ssh/id_ed25519 deploy@your-vps-ip
Step 4: Disable root login and password authentication
Edit the SSH configuration file to disable root login and password-based authentication:
sudo nano /etc/ssh/sshd_config
Find and modify these lines (search with Ctrl+W):
# Find these lines and change them: PasswordAuthentication yes → PasswordAuthentication no PubkeyAuthentication no → PubkeyAuthentication yes PermitRootLogin yes → PermitRootLogin no # Make sure these lines are present and uncommented: AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 PermitEmptyPasswords no
Save with Ctrl+X, then Y, then Enter. Restart SSH:
sudo systemctl restart sshd
Critical: Keep your current SSH session open. Open a new terminal tab and test SSH access with your key before closing the original session. If you lock yourself out, you may need to contact your hosting provider.
Step 5: Configure UFW firewall
UFW (Uncomplicated Firewall) provides a simple way to allow only necessary ports. Enable it and configure rules:
# Allow SSH (critical — do this before enabling the firewall) sudo ufw allow 22/tcp # Allow HTTP and HTTPS (if running a web server) sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Enable the firewall sudo ufw enable # Check the status sudo ufw status
If you need to allow additional ports (e.g., 3000 for a Node.js app during testing), add them:
sudo ufw allow 3000/tcp # Allow port 3000 sudo ufw allow 5432/tcp # Allow PostgreSQL sudo ufw deny 22/tcp # Deny SSH (example: remove later with delete)
To remove a rule:
sudo ufw delete allow 3000/tcp
Principle: Only open ports you absolutely need. Every open port is a potential attack surface. Close ports as soon as you're done using them.
Step 6: Install and configure fail2ban
Fail2ban monitors log files and automatically blocks IP addresses that make repeated failed login attempts:
# Install fail2ban sudo apt install -y fail2ban # Create a local configuration file sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local # Edit the local config sudo nano /etc/fail2ban/jail.local
Find and modify these settings (search with Ctrl+W):
# Set how many attempts before ban (default is 5, you can change to 3) maxretry = 3 # Set ban duration in seconds (3600 = 1 hour) bantime = 3600 # Set the window for counting attempts (seconds) findtime = 600 # Jail for SSH [sshd] enabled = true
Save and restart fail2ban:
sudo systemctl restart fail2ban # View the status sudo fail2ban-client status sshd
This automatically blocks any IP that fails SSH login 3 times in 10 minutes for 1 hour.
Step 7: Set up swap file (if needed)
Small VPS instances (512MB–1GB RAM) can run out of memory. Swap provides overflow space (it's slower than RAM, but prevents crashes). Check if swap already exists:
sudo swapon --show
If there's no output, swap isn't configured. Create a 2GB swap file:
# Create a 2GB swap file sudo fallocate -l 2G /swapfile # Set correct permissions sudo chmod 600 /swapfile # Format it as swap sudo mkswap /swapfile # Enable swap sudo swapon /swapfile # Make it permanent by adding to /etc/fstab echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab # Verify it's active free -h
Your output should show the swap file in the "Swap" row. For larger instances (2GB+ RAM), swap is usually optional unless you run many background processes.
Step 8: Enable unattended security upgrades
Critical security patches should be applied automatically so your server stays secure even if you forget:
# Install unattended-upgrades sudo apt install -y unattended-upgrades # Enable automatic updates sudo dpkg-reconfigure -plow unattended-upgrades # Check if it's enabled sudo systemctl status unattended-upgrades
To configure what gets updated, edit:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Key settings to check:
# Uncomment to auto-reboot if necessary Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "02:00"; # Reboot at 2 AM # Only update security patches (more conservative) APT::Periodic::Unattended-Upgrade "1"; APT::Periodic::Update-Package-Lists "1";
Save and exit. Your server will now apply security patches automatically.
Step 9: Configure sudo without password prompts (optional)
For automated deployments, you may want to allow specific sudo commands without password prompts. Use visudo (never edit /etc/sudoers directly):
sudo visudo
Add this line at the end (replace "deploy" with your username):
# Allow deploy user to restart nginx without password deploy ALL=(ALL) NOPASSWD:/usr/sbin/systemctl restart nginx # Or allow all sudoers commands without password (less secure, not recommended): # deploy ALL=(ALL) NOPASSWD:ALL
Save with Ctrl+X. Now the deploy user can run sudo systemctl restart nginx without entering a password.
Security note: Only allow specific commands without password, never all sudo commands. Be precise about which actions can bypass the password prompt.
Step 10: How DeployWise connects to your VPS
Once your VPS is hardened, DeployWise connects securely using SSH keys. Here's how it works:
Security: DeployWise never stores your VPS password. All authentication happens via SSH keys, which are stored encrypted in our database. You remain in full control.
Post-setup checklist
Monitoring and maintenance
After setup, monitor your server regularly:
Review logs periodically (especially after anomalies) and keep your system updated. If you notice unusual activity, check fail2ban status and review /var/log/auth.log.
Ready to deploy with a hardened VPS?
DeployWise automates deployments to your secure Ubuntu VPS. Connect your Git repo, push code, and watch it deploy automatically — with full control over your infrastructure.
Launch DeployWise