VPS Setup
Overview
This guide covers the initial security setup for a fresh VPS. A new VPS typically comes with password authentication enabled and no protection against attacks. We’ll secure it by:
- Updating the system packages
- Creating a non-root user with sudo access
- Setting up SSH key authentication (more secure than passwords)
- Configuring automatic security updates (keeps the system patched)
- Installing Fail2Ban (blocks brute-force attacks)
After completing this guide, your VPS will have a solid security foundation for hosting services.
Prerequisites
- A VPS running Ubuntu Server (commands should be similar on other Debian-based distributions)
- Root or sudo access
- SSH client on your local machine (Terminal on macOS/Linux, or Windows Terminal)
Initial System Update
Before doing anything else, update your system’s package list and install pending updates. This ensures you start with the latest security patches.
sudo apt update && sudo apt upgrade -y
What is
sudo? It’s short for “superuser do” — it runs commands with administrator privileges. You’ll usesudofrequently when configuring your server.
Create a Non-Root User
Many VPS providers give you a default user (like ubuntu or root). It’s best practice to create your own non-root user for daily use.
Check if a user already exists
whoami
If you see root or a provider-created username, you can either use that or create a new one.
Create a new user
sudo adduser <username>
Set a password and fill in the optional details (you can press Enter to skip them).
Give the user sudo access
sudo usermod -aG sudo <username>
This allows the user to run commands with sudo (administrator privileges).
Switch to the new user
su - <username>
From here, all commands assume you’re logged in as this non-root user.
SSH Setup
SSH keys are more secure than passwords because they can’t be guessed or brute-forced. The key pair consists of a private key (stays on your machine) and a public key (goes on the server).
Generate a Key Pair
On your local machine, generate an ed25519 key:
ssh-keygen -t ed25519
Press Enter to accept the default location. Optionally set a passphrase for extra security.
This creates two files:
~/.ssh/id_ed25519- your private key (never share this)~/.ssh/id_ed25519.pub- your public key (safe to share)
Copy the Public Key to VPS
ssh-copy-id <username>@<vps-ip>
This appends your public key to the server’s ~/.ssh/authorized_keys file. You’ll need to enter your password one last time.
If
ssh-copy-idfails (e.g., your VPS only supports key authentication from the provider), copy the contents of~/.ssh/id_ed25519.pubmanually and append it to the server’s~/.ssh/authorized_keysfile:cat ~/.ssh/id_ed25519.pub # Copy the output, then paste it into the VPS: echo "<paste-your-public-key-here>" >> ~/.ssh/authorized_keys
Configure SSH Client
Add this to ~/.ssh/config on your local machine to simplify connections:
Host *
AddKeysToAgent yes
IdentitiesOnly yes
ServerAliveInterval 60
Host vps
HostName <vps-ip>
User <username>
Port 22
IdentityFile ~/.ssh/id_ed25519
# UseKeychain yes # macOS only — uncomment to store key in macOS Keychain
Host github.com
HostName github.com
User git
| Setting | Purpose |
|---|---|
AddKeysToAgent yes | Automatically add keys to SSH agent |
IdentitiesOnly yes | Only use explicitly configured keys |
ServerAliveInterval 60 | Send keepalive every 60 seconds to prevent disconnection |
Why isn’t
IdentityFilein theHost *block? Putting it there would force ALL SSH connections to use that key, which can break connections to other servers. Keep it specific to each host.
macOS users: Uncomment
UseKeychain yesto store your key passphrase in the macOS Keychain, so you don’t need to enter it every time.
Now you can connect with just:
ssh vps
No password needed.
Disable Password Authentication
Now that SSH keys are working, disable password-based login for better security. This prevents brute-force attacks.
Edit the SSH server config:
sudo vim /etc/ssh/sshd_config
Find and change these lines (remove the # if they’re commented out):
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
What do these do?
PermitRootLogin no: Blocks direct root login. Always use your user account withsudoinstead.PasswordAuthentication no: Disables password login — only SSH keys work.ChallengeResponseAuthentication no: Disables another password-based auth method.
Restart SSH to apply:
sudo systemctl restart sshd
⚠️ Important: Test that SSH keys work before closing your current session! Open a new terminal and run
ssh vpsto verify. If something went wrong, you can still use the existing session to fix the config.
Timezone
Set the server timezone so logs show the correct local time:
sudo timedatectl set-timezone Asia/Jakarta
Verify with:
timedatectl
Replace Asia/Jakarta with your timezone. List available timezones with timedatectl list-timezones.
Auto Security Updates
Security vulnerabilities are discovered regularly. Unattended-upgrades automatically installs security patches so you don’t have to manually update.
Install and configure:
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
Select “Yes” when prompted to enable automatic updates.
The system will now:
- Check for security updates daily
- Install them automatically
- Keep your system patched without intervention
Configuration (Optional)
Config file location: /etc/apt/apt.conf.d/50unattended-upgrades
To enable automatic reboots when required (e.g., kernel updates), add:
Unattended-Upgrade::Automatic-Reboot "true";
View update logs at: /var/log/unattended-upgrades/unattended-upgrades.log
Fail2Ban
Fail2Ban monitors log files for failed login attempts. When it detects repeated failures from an IP address, it bans that IP by adding a firewall rule.
This protects against brute-force SSH attacks where attackers try thousands of password combinations.
Install and Enable
sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Check Status
View all active jails:
sudo fail2ban-client status
View SSH jail specifically (shows banned IPs):
sudo fail2ban-client status sshd
Unban an IP
If you accidentally get banned (e.g., too many failed logins):
sudo fail2ban-client set sshd unbanip <ip>
Custom Settings (Optional)
The default settings work well for most cases. To customize, create a local config:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo vim /etc/fail2ban/jail.local
| Setting | Default | Description |
|---|---|---|
maxretry | 5 | Number of failures before ban |
bantime | 10m | How long the ban lasts |
findtime | 10m | Time window for counting failures |
Example: With defaults, 5 failed logins within 10 minutes triggers a 10-minute ban.
SSH jail (sshd) is enabled by default - no extra configuration needed.