Setting Up Your First VPS

March 14, 2026 • Server Administration • 25 min read

You just rented your first VPS. Maybe it's from Hetzner, DigitalOcean, or some random provider you found on LowEndBox. It doesn't matter where you got it—what matters is what you do with it now.

A fresh VPS is like a blank canvas. It's also like a house with the doors unlocked. The moment you spin it up, bots are already scanning it, trying default passwords, looking for weaknesses. I've watched failed login attempts on a fresh server go from zero to thousands per day within hours.

This guide walks you through hardening a Debian VPS from scratch. We'll cover everything from basic updates to kernel hardening, SSH security, firewall configuration, and automated security updates. By the end, you'll have a server that can defend itself against the automated junk that's constantly probing every IP on the internet.

TL;DR: If you just want to run a script and be done, I've also written an automated server_setup.sh that does all of this for you. But I'd encourage you to read through this first—understanding what you're actually securing matters.

What We'll Cover

1. Update Your System

First things first. When you get a fresh VPS, the first thing you should do is update everything. I don't care if the provider says "pre-configured" or "latest image"—you update anyway. Security patches come out constantly, and your first job is to install them.

sudo apt update
sudo apt upgrade -y

The apt update part refreshes your package lists—it tells your server what's available. Then apt upgrade actually installs the new versions. The -y flag just answers "yes" to all prompts automatically.

Why this matters: Every piece of software on your server potentially has vulnerabilities. The maintainers of Debian are constantly releasing security patches. Keeping your system updated is the single most important thing you can do for security.

2. Configure Swap

Swap is like virtual RAM—it's disk space that your server uses when it runs out of actual memory. Even if you have plenty of RAM, having swap configured prevents your server from crashing when something unexpectedly eats memory. It's a safety net.

Let's check if you already have swap:

sudo swapon --show

If that shows nothing, you need to create swap. A good rule of thumb is to have swap equal to your RAM, or at least 2GB if you have less than that:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Now we make it permanent so it comes back after a reboot:

sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Important: The permissions (chmod 600) are critical. If swap is world-readable, anyone on the server could potentially read sensitive data from it. Never skip this step.

3. Set Up UFW Firewall

A firewall is your first line of defense. It decides what can come into your server and what can't. We're going to use UFW (Uncomplicated Firewall)—it's exactly what it sounds like: a simple interface to the complex iptables firewall built into Linux.

The strategy is simple: block everything by default, then explicitly allow only what you need.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw --force enable
sudo ufw status

Let's break this down:

CRITICAL: Always make sure SSH is allowed BEFORE enabling the firewall. Otherwise you will lock yourself out of your server. If you're using a custom SSH port, remember to allow that port instead.

4. Create a Non-Root User

You're probably tempted to just use root for everything. Don't. Root is the administrator account—it can do literally anything, including destroying your entire server with one command. That's dangerous in two ways: you could accidentally break something, and if someone compromises root, they own everything.

Create a regular user instead:

sudo adduser yourname

Follow the prompts. Pick a strong password (I'll explain why we still need passwords even though we're disabling them later).

Now give this user sudo access—that means they can run commands as root when needed:

sudo usermod -aG sudo yourname

The -aG means "append to group" and sudo is the group that allows administrative commands.

5. Harden SSH

SSH (Secure Shell) is how you connect to your server remotely. By default, it's set up pretty loosely. We're going to lock it down hard:

First, you need to set up SSH key-based authentication. On your local machine (not the server):

ssh-keygen -t ed25519
ssh-copy-id yourname@your-server-ip

If you're on Windows or want more options, check out the GPG guide—you can actually use GPG keys for SSH authentication too.

Now let's harden SSH on the server. We'll create a configuration file that overrides the defaults:

sudo nano /etc/ssh/sshd_config.d/custom.conf

Paste in these settings (change port 2222 to whatever you want, or use 22):

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowTcpForwarding no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
Port 2222

Save and exit (Ctrl+X, then Y, then Enter in nano). Then restart SSH:

sudo systemctl restart ssh
IMPORTANT: Before you log out, open a NEW terminal window and test that you can still connect with your SSH key! If you lock yourself out, you'll need console access through your VPS provider to fix it.

If you changed the port, remember to specify it when connecting:

ssh -p 2222 yourname@your-server-ip
Note: If you changed the SSH port, make sure to update your firewall to allow that port instead of the default 22:
sudo ufw allow 2222/tcp

6. Install Fail2ban

Fail2ban is beautiful in its simplicity. It watches your logs for failed login attempts, and when some IP tries and fails too many times, it bans them automatically. It's like having a bouncer who throws out troublemakers before they can cause problems.

sudo apt install -y fail2ban

Now configure it. We'll create a local configuration that overrides the defaults:

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
port = 2222

Adjust the port number if you changed SSH from the default. This config says: ban anyone who fails to log in 5 times within 10 minutes for 1 hour.

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check if it's running:

sudo fail2ban-client ping

If it replies "pong", you're good. You can see banned IPs with:

sudo fail2ban-client status sshd

7. Kernel Hardening

The Linux kernel is the core of your operating system. We can tune it with sysctl settings to be more secure against network attacks. This is the "hardening" part—making the OS itself more defensive.

sudo nano /etc/sysctl.d/99-custom.conf
# Prevent SYN flood attacks
net.ipv4.tcp_syncookies = 1

# Prevent IP spoofing
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Don't accept source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Ignore broadcast pings (prevents ping floods)
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Don't accept ICMP redirects (security risk)
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Log suspicious packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

Save and apply these settings:

sudo sysctl -p /etc/sysctl.d/99-custom.conf
What these do: SYN cookies prevent your server from being overwhelmed by SYN flood attacks. RP filter prevents IP spoofing. Disabling source routing and ICMP redirects prevents attackers from manipulating how traffic flows through your server. Logging martian packets helps you spot suspicious activity.

8. Automatic Security Updates

You won't remember to log in and run apt update every week. That's okay—let the server do it automatically. We'll use Debian's unattended-upgrades package.

sudo apt install -y unattended-upgrades

Configure it:

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}-security";
    "${distro_id}:${distro_codename}-updates";
};
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-RebootTime "02:00";

This tells the server to automatically install security updates and reboot at 2 AM if needed (kernel updates often require a reboot).

9. Log Monitoring

You can't watch your server 24/7. But you can get daily summaries of what's happening. Logwatch parses your system logs and emails you a digest.

sudo apt install -y logwatch

Create a cron job to run it daily:

sudo nano /etc/cron.daily/logwatch
#!/bin/sh
/usr/sbin/logwatch --output mail --mailto root --detail high
sudo chmod 755 /etc/cron.daily/logwatch
Pro tip: You'll need to forward root's email to your actual email address for this to be useful. You can do that by creating a .forward file in /root/ with your email address.

10. Secure File Permissions

Linux file permissions determine who can read, write, or execute files. We need to lock down sensitive directories, especially SSH keys.

sudo chmod 700 /root
sudo chmod 700 /home/*/.ssh 2>/dev/null
sudo chmod 600 /home/*/.ssh/authorized_keys 2>/dev/null

This ensures:

11. Disable Core Dumps

When a program crashes, it can dump its memory contents to a file. That memory might contain passwords, keys, or other sensitive data. We should disable this.

sudo nano /etc/security/limits.conf

Add at the bottom:

* soft core 0
* hard core 0

Also add to the kernel hardening file:

sudo echo "fs.suid_dumpable = 0" >> /etc/sysctl.d/99-custom.conf
sudo sysctl -p /etc/sysctl.d/99-custom.conf

12. Disable Unnecessary Services

Every running service is a potential attack vector. If you're not using something, turn it off. This reduces your attack surface.

sudo systemctl stop cups bluetooth avahi-daemon
sudo systemctl disable cups bluetooth avahi-daemon

What these are:

13. Cleanup

Let's clean up unused packages and free some disk space:

sudo apt autoremove -y
sudo apt autoclean

autoremove removes packages that were installed as dependencies but are no longer needed. autoclean clears the apt package cache.

14. Install a Web Server (Optional)

If you're hosting a website, you'll need a web server. I prefer nginx for its performance, but Apache is also fine. Let's install nginx:

sudo apt install -y nginx
sudo ufw allow 'Nginx Full'
sudo systemctl enable nginx
sudo systemctl start nginx

The firewall rule allows both HTTP (port 80) and HTTPS (port 443) traffic.

If you prefer Apache instead:

sudo apt install -y apache2
sudo a2enmod ssl rewrite headers
sudo ufw allow 'Apache Full'
sudo systemctl enable apache2
sudo systemctl start apache2

15. Set Up a Tor Onion Site (Optional)

Want to host your site anonymously? A Tor onion site lets visitors access your site without either of you revealing your IP addresses. It's the ultimate in privacy hosting.

Check out my Build an Onion Site tutorial for the full walkthrough.

Pro tip: Our server_setup.sh script includes an option to automatically set up a Tor hidden service with all the proper configuration.
Onion-Location Tip: To let Tor Browser visitors know your onion site exists, add a meta tag to each HTML page on your main site:

<meta http-equiv="onion-location" content="http://your-onion-address.onion/path/to/page.html" />

Each page needs its own meta tag pointing to the corresponding onion page. Tor Browser will show a purple onion icon in the address bar when it detects this.

That's It—Your Server Is Hardened

You now have a VPS that:

This is the foundation. From here, you can host websites, run Docker containers, set up databases, or whatever else you need your server to do.

Want to automate all this? I've written a bash script called server_setup.sh that does every step in this guide automatically. Just download it, run it, and answer the prompts. It's designed to be safe—you can skip steps you don't want, and it checks for common pitfalls before making changes.

Remember: security isn't a one-time thing. Keep an eye on those logwatch emails. Update your server regularly. Monitor fail2ban to see who's trying to get in. The automation handles a lot, but you're still the one watching the house.

The revolution will not be proprietary.

// Comments

Leave a Comment