How to Setup a Hetzner Server

A simple walkthrough of purchasing a Hetzner cloud server, then locking it down with SSH hardening, a firewall, automatic updates, and Fail2ban.

Photo of Kenny Tran
KT

By Kenny Tran

  • devops
  • hetzner
  • linux
  • security
  • self-hosting
  • vps
  • hermes

I recently picked up a Hetzner Cloud server to host my Hermes agent and was surprised by how straightforward the process was. This post covers both: getting the server, then making it reasonably secure.

They offer two products worth knowing:

  • Hetzner Cloud — VPS instances, managed with a web UI or API. Good for most workloads.
  • Hetzner Robot (Dedicated) — bare metal servers. Much more power but requires a reboot into rescue mode to reinstall.

For most projects, Hetzner Cloud is a good starting point.

Provisioning the Server

  1. Create an account at hetzner.com and navigate to the Cloud Console.
  2. Create a new project, then click Add Server.
  3. Pick a location.
  4. Select a type. The CX23 is a good starting point; scale up if needed.
  5. Choose an image — Ubuntu 26.04 LTS is a safe pick with long-term support.
  6. Under SSH keys, paste your public key. This is mandatory, you should never rely on password auth.
  7. Optionally enable backups (adds 20% to the monthly cost but is worth it).

Once created, you’ll have an IP address and root SSH access within seconds.

First Login

Connect as root using your SSH key:

Terminal window
ssh root@<your-server-ip>

Before anything else, update the system:

Terminal window
apt update && apt upgrade -y

Create a Non-Root User

Running everything as root is asking for trouble. Create a user with sudo access:

Terminal window
usermod -aG sudo kenny

Copy your SSH key to the new user:

Terminal window
rsync --archive --chown=kenny:kenny ~/.ssh /home/kenny

Test the new user in a separate terminal before continuing:

Terminal window
ssh kenny@<your-server-ip>

Harden SSH

Edit /etc/ssh/sshd_config:

Terminal window
sudo nano /etc/ssh/sshd_config

Set or confirm these values:

Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
X11Forwarding no
AllowUsers kenny

Changing the port from 22 to something like 2222 cuts noise from automated scanners significantly. It is not a security measure on its own, but it reduces log spam.

Restart SSH — do not close your existing session yet:

Terminal window
sudo systemctl restart sshd

Open a new terminal and verify you can connect on the new port:

Terminal window
ssh -p 2222 kenny@<your-server-ip>

Once confirmed, close the old session.

Configure the Firewall with UFW

Ubuntu ships with UFW (Uncomplicated Firewall). Enable it and set sensible defaults:

Terminal window
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow your new SSH port
sudo ufw allow 2222/tcp
sudo ufw enable
sudo ufw status verbose

Hetzner also provides a Cloud Firewall at the network level in the console. Using both is a good idea — the cloud firewall drops packets before they reach the OS.

Enable Automatic Security Updates

Install unattended-upgrades to automatically apply security patches:

Terminal window
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

To confirm the configuration:

Terminal window
cat /etc/apt/apt.conf.d/20auto-upgrades

It should contain:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Install Fail2ban

Fail2ban watches log files and bans IPs that show malicious behaviour (repeated failed SSH logins, etc.):

Terminal window
sudo apt install fail2ban -y

Create a local override so your config survives package updates:

Terminal window
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Find the [sshd] section and update it:

[sshd]
port = 2222

Restart and check the service:

Terminal window
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Summary

Here is the full checklist:

  • ✅ Provisioned server with SSH key, no root password
  • ✅ Created non-root user with sudo access
  • ✅ Disabled root login and password authentication in sshd
  • ✅ Moved SSH to a non-standard port
  • ✅ Configured UFW with deny-by-default
  • ✅ Enabled automatic security updates
  • ✅ Installed and configured Fail2ban

This gets you to a reasonable baseline.