Setting Up a VPS with sensible defaults
In this guide I will walk you through setting up a VPS with secure and sensible defaults. First manually so you understand what's happening a bit better and then with cloud-init to automate the whole process.
This guide focuses on Ubuntu.
Manually: Understanding the basics
Step 1: Generate your SSH key
First things first - if you don't already have an SSH key, let's create one on your local machine:
ssh-keygen -t ed25519 -C "[email protected]"
Now copy the public key it generated into your VPS provider's SSH keys area. You can get the public key with cat ~/.ssh/id_ed25519.pub
if it was stored in the default path.
Go ahead and use this key to create your new server.
Step 2: Create a non-root user
Log into your new server with ssh root@your-server-ip
We shouldn’t generally be interacting with the server as the root user. If compromised, an attackers gets complete system control, and you can accidentally damage critical files with no safety net. A regular user with sudo is safer since you need to explicitly escalate privileges when you need it. Let's create one:
adduser tutorial
adduser tutorial sudo
The first command creates the user and asks you to set a password. The second adds it to the sudo group. We're using tutorial
for the non-root user as an example but you can name it whatever you want.
Step 3: Setting up SSH access for the new user
Now we need to copy your SSH key to the new user:
mkdir /home/tutorial/.ssh
cp ~/.ssh/authorized_keys /home/tutorial/.ssh/authorized_keys
chown -R tutorial:tutorial /home/tutorial/.ssh
chmod u+rwx,go-rwx /home/tutorial/.ssh
chmod 600 /home/tutorial/.ssh/authorized_keys
authorized_keys
file. That's why we can simply copy it over to our new user..ssh
directory needs to be 700 (owner-only access) and authorized_keys
needs to be 600 (owner read/write only).Step 4: Harden the SSH configuration
We should go ahead and lock down SSH access. Open the SSH config:
sudo vi /etc/ssh/sshd_config
Find and change these lines to:
PermitRootLogin no
PasswordAuthentication no
Then restart SSH to apply the changes:
sudo systemctl restart ssh
ssh tutorial@your-server-ip
. Some people also like to change the default ssh port from 22 to something else but I won't cover that here as it doesn't affect security in any meaningful way.
Step 5: Set up the firewall
Ubuntu comes with UFW (Uncomplicated Firewall). Let's set it up:
sudo ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
sudo ufw status verbose
When you run ufw enable
, it'll warn you about disrupting SSH connections. Since we already allowed OpenSSH, you can safely proceed.
Step 6: Enable automatic security updates
Keep your server patched without having to remember to manually update:
sudo apt update
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
Select "Yes" when asked if you want to automatically download and install updates.
For personal projects and non-critical services, automatic updates are usually worth the peace of mind.
The cloud-init way: automation from the start
Doing all that manually can get old fast. I'll show you how to configure your server automatically on first boot with cloud-init because it is supported by most VPS providers.
Here's a configuration that does everything we just did manually:
#cloud-config
users:
- name: tutorial
groups: sudo
shell: /bin/bash
sudo: ALL=(ALL) ALL
lock_passwd: false
passwd: $6$randomsalt$yourHashedPasswordHere
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... [email protected]
# Disable password authentication for SSH
ssh_pwauth: false
# Disable root SSH login
disable_root: true
# Install required packages
packages:
- ufw
- unattended-upgrades
# Configure firewall and security updates
runcmd:
- ufw allow OpenSSH
- ufw allow http
- ufw allow https
- ufw --force enable
- dpkg-reconfigure -plow unattended-upgrades
Do you see that passwd: $6$randomsalt$yourHashedPasswordHere
part? We need to change that. You can generate it with openssl passwd -6
on your local machine. If you're on Windows then WSL could be a good option to get access to some Linux standard tools such as openssl.
This will prompt you for the password and output the hash. Copy the output and replace $6$randomsalt$yourHashedPasswordHere
with it.
Also, don't forget to change the ssh_authorized_keys
part to include the key you generated in the first step.
Then go ahead and use it during the VPS creation step (it should mention cloud-init somewhere). I am using Hetzner (referral URL: https://hetzner.cloud/?ref=KHnQDk7q1gJg, you'll get 20€, I'll get 10€) but many other providers support cloud-init as well, such as AWS, Google Cloud Platform, Azure, DigitalOcean, Linode, Vultr and OVHcloud.
What's next?
And with that your foundation is ready! With either approach, you now have:
- A non-root user with sudo access
- SSH key authentication only (no passwords)
- Root login disabled
- Basic firewall protecting your server
- Automatic security updates
Author’s Note: Claude assisted with editing and proofreading this post but the concept and final content are my own.