DeployWise
HomeGuidesUbuntu VPS Initial Setup
UbuntuVPSSecurityServer Setup

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.

30 min read
Updated 2026

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:

Create a non-root user (never use root for daily tasks)
Set up SSH key authentication (eliminate password guessing)
Disable root login (removes the most common attack vector)
Configure UFW firewall (allow only needed ports)
Install fail2ban (auto-block repeated failed login attempts)
Set up unattended upgrades (security patches applied automatically)
Configure system timezone (ensures logs and cron jobs are correct)
Add swap space (prevents out-of-memory crashes)

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:

bash
sudo apt update
sudo apt upgrade -y

Set your timezone (this ensures cron jobs and logs use the correct time):

bash
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:

bash
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):

bash
# 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:

bash
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:

bash
# 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:

bash
# 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):

bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Test SSH key login from your local machine:

bash
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:

bash
sudo nano /etc/ssh/sshd_config

Find and modify these lines (search with Ctrl+W):

sshd_config
# 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:

bash
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:

bash
# 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:

bash
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:

bash
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:

bash
# 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):

fail2ban
# 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:

bash
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:

bash
sudo swapon --show

If there's no output, swap isn't configured. Create a 2GB swap file:

bash
# 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:

bash
# 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:

bash
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Key settings to check:

config
# 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):

bash
sudo visudo

Add this line at the end (replace "deploy" with your username):

sudoers
# 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:

1
Add your VPS to DeployWise
Go to Dashboard > Servers > Add Server. Enter your VPS IP, username (deploy), and port (22)
2
Paste your private SSH key
Copy ~/.ssh/id_ed25519 from your local machine and paste it in DeployWise. It's stored encrypted.
3
Verify the connection
DeployWise tests SSH access using your key. If connection fails, check your firewall (UFW) and SSH config.
4
Connect your Git repository
Link a GitHub repo. DeployWise pulls code, builds it, and deploys to your VPS via SSH.
5
Deploy automatically
Every git push triggers a deployment. DeployWise uses PM2 to manage your Node.js app and Nginx as a reverse proxy.

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

System packages updated (apt upgrade)
Timezone set correctly (timedatectl)
Non-root user created with sudo privileges
SSH key authentication working
Root login disabled (sshd_config)
Password authentication disabled (sshd_config)
UFW firewall enabled with rules for SSH, HTTP, HTTPS
Fail2ban installed and monitoring SSH
Swap file configured (if needed)
Unattended upgrades enabled
VPS added to DeployWise with SSH key
Test deployment run successfully

Monitoring and maintenance

After setup, monitor your server regularly:

sudo fail2ban-client status sshd
View blocked IP addresses from failed logins
sudo ufw status
Check active firewall rules
free -h
Monitor RAM and swap usage
df -h
Check disk space
sudo systemctl status fail2ban
Ensure fail2ban is running
sudo systemctl status unattended-upgrades
Check if automatic updates are working

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

Related guides