How to Set Up Hetzner Cloud VPS — From Signup to Production (2026)
Hetzner's dashboard will confuse you for about 15 minutes. The terminology is slightly off, the navigation feels like it was designed by engineers who think in German, and the account verification process may require your passport. And then you will look at your server specs — 2 vCPU, 4GB RAM, 40GB NVMe for $4.59/mo — and forgive everything. This is a Porsche Cayenne for the price of a Honda Civic. The ride quality is outstanding once you figure out where the ignition is. One US datacenter (Ashburn, VA), so this is an East Coast play. But for the money? Nothing else comes close. Here is the full setup, quirks included.
What You'll Build
A production server with SSH key auth, Hetzner Cloud Firewall (network-level, fires before your OS even sees traffic), UFW as backup, Nginx, Let's Encrypt SSL, and automated snapshots. The CX22 at $4.59/mo delivers specs that embarrass $20 plans elsewhere. That is not marketing — our benchmarks confirmed it.
Table of Contents
- Create Your Hetzner Account (EU Verification Note)
- Choose Your Server Type (CX vs CPX vs CCX)
- Create Your First Server (Console Walkthrough)
- SSH Keys in Hetzner
- First Login & System Update
- Non-Root User Setup
- Hetzner Cloud Firewall (Dashboard-Level)
- UFW Firewall (OS-Level, Double Protection)
- Install & Configure Nginx
- Domain & DNS Setup
- SSL with Certbot
- hcloud CLI Setup (Optional but Powerful)
- Hetzner Features (Volumes, Networks, Snapshots)
- Common Hetzner Issues (EU Verification, CAPTCHA, Abuse Reports)
- FAQ
Step 1 — Create Your Hetzner Account (EU Verification Note)
Head to console.hetzner.cloud and sign up. Fair warning: Hetzner is German, and they take fraud prevention with the seriousness you would expect from a company headquartered in Gunzenhausen, Bavaria. Most US users sail through signup. Some get hit with ID verification — passport photo, uploaded through their portal, processed in 1–24 hours. It is annoying exactly once, and then never again.
Payment: credit card activates fastest. PayPal works. SEPA is EU-only. No free trial credits like Vultr's $100 or DO's $200 — but at $4.59/mo for the CX22, the "trial" is basically just... using the service. The financial risk of testing Hetzner for a month is less than a fancy coffee.
After signup you land in the Cloud Console, which looks clean but works differently than you expect. First: create a Project. Everything in Hetzner is scoped to a project — servers, networks, firewalls, SSH keys. Name it "production" or "web-servers" or whatever makes sense. This is the one piece of organization you cannot skip.
One thing that catches people: US pricing is slightly higher than EU. The CX22 costs $4.59/mo in Ashburn vs $3.29/mo in Falkenstein or Nuremberg. Still cheaper than literally every US-native competitor at comparable specs.
Step 2 — Choose Your Server Type (CX vs CPX vs CCX)
Three server families. The naming convention is confusing at first (CX? CPX? CCX? Pick a letter, Hetzner), but here is the decoder ring:
- CX Series (Shared vCPU, Intel/AMD) — Entry-level shared vCPUs. CX11 (1 vCPU/2GB) at $3.29/mo, CX22 (2 vCPU/4GB/40GB NVMe) at $4.59/mo, CX32 (4 vCPU/8GB) at $8.19/mo. Best for most web applications.
- CPX Series (Shared AMD vCPU, higher performance) — AMD EPYC with better sustained CPU performance than CX. CPX11 at $3.85/mo, CPX21 (3 vCPU/4GB) at $5.83/mo. Good for CPU-bound workloads.
- CCX Series (Dedicated AMD vCPU) — Dedicated physical CPU cores, no shared resources. CCX13 (2 dedicated vCPU/8GB) starts at $17.36/mo. For production databases and CPU-intensive applications that cannot tolerate noisy neighbors.
- CAX Series (ARM64) — Ampere Altra ARM processors. Cheaper than x86 and very power efficient. Not available in US datacenter yet (EU only as of 2026).
My pick: the CX22 at $4.59/mo. 2 vCPU and 4GB RAM runs a full LEMP stack with headroom to spare. I have run WordPress sites serving 50,000 monthly visitors on this tier without touching swap. It is the plan I recommend to everyone who asks.
Ashburn, Virginia is your only US option. One datacenter. That is it. If your users are in Seattle, you are looking at 70-80ms latency — use Vultr or DO for West Coast. But Ashburn sits on top of one of the world's biggest internet exchange points, so East Coast latency is superb. Under 10ms to New York, DC, Philadelphia. For the money, there is no better East Coast server.
Step 3 — Create Your First Server (Console Walkthrough)
Click Add Server in your project. The wizard is functional but slightly cluttered compared to DO's elegant flow. Here is what to pick and why:
- Location: Select Ashburn, VA (us-east) for US audiences.
- Image: Choose Ubuntu 24.04.
- Type: Select the CX22 (2 vCPU, 4GB RAM, 40GB NVMe).
- Networking: Public IPv4 and IPv6 are included. If you want to add a private network (for server-to-server communication), create one first under Networks and add it here.
- SSH Keys: Add your SSH public key here (see next step).
- Firewalls: You can attach a Hetzner Cloud Firewall here (we'll create one in Step 7).
- Name: Give your server a name like
web01.
Click Create & Buy Now. The server appears in 30–60 seconds. This is actually the fastest provisioning I have measured across all providers — faster than Vultr by a hair, though both are effectively instant.
Step 4 — SSH Keys in Hetzner
Same drill as every provider: generate keys locally, hand Hetzner the public half. Never create keys on the server.
# Generate Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "your-email@example.com"
# Accept default path (~/.ssh/id_ed25519)
# Add a passphrase for extra security
# Show your public key — copy this entire output
cat ~/.ssh/id_ed25519.pub
In the Cloud Console: Security → SSH Keys → Add SSH Key. Paste your public key. Hetzner lets you scope keys to the project level so every server in that project inherits them. A nice touch buried in a menu you might not find on your own.
# If you missed adding the key during server creation, add it manually:
# (Replace with your server's IP)
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@203.0.113.30
# Then log in using the temporary root password from the Hetzner console
# and paste the above command output
Step 5 — First Login & System Update
# Connect to your server (replace with your actual IP from the Hetzner console)
ssh root@203.0.113.30
# Accept the host fingerprint on first connection
# Update all packages immediately
apt update && apt upgrade -y
# Install essential tools
apt install -y curl wget git unzip htop ufw nano software-properties-common fail2ban
# Set timezone
timedatectl set-timezone America/New_York
# Set hostname
hostnamectl set-hostname web01.yourdomain.com
# Verify system info
uname -a
lsb_release -a
Step 6 — Non-Root User Setup
Do not operate as root. Just don't. Create a regular user, give it sudo, and pretend root does not exist.
# Create a new user
adduser deploy
# Add to sudo group
usermod -aG sudo deploy
# Copy SSH keys
mkdir -p /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
# Test in a NEW terminal window before making any SSH changes
ssh deploy@203.0.113.30
sudo whoami # Should output: root
# Once confirmed, disable root SSH login
sudo nano /etc/ssh/sshd_config
# Set: PermitRootLogin no
# Set: PasswordAuthentication no
sudo systemctl restart sshd
Step 7 — Hetzner Cloud Firewall (Dashboard-Level)
This is Hetzner's best feature and nobody talks about it enough. The Cloud Firewall operates at the network layer — traffic is killed before it ever reaches your server's NIC. Your server could be OOM-killed, CPU-pegged at 100%, completely unresponsive, and the firewall rules still hold. That is genuinely excellent engineering.
Create one in Security → Firewalls → Create Firewall. Here is a sane default ruleset:
| Direction | Protocol | Port | Source/Dest |
|---|---|---|---|
| Inbound | TCP | 22 | Any IPv4 / Any IPv6 |
| Inbound | TCP | 80 | Any IPv4 / Any IPv6 |
| Inbound | TCP | 443 | Any IPv4 / Any IPv6 |
| Inbound | ICMP | — | Any (for ping) |
| Outbound | TCP + UDP | All | Any |
Click Apply to Servers, pick your server, and you are done. No reboot. Applies in seconds. The UI for this is actually clear — one of the few places where Hetzner's interface gets out of its own way.
Best part: these firewalls are free and apply to multiple servers at once. Create one called "web-servers," apply it to everything that faces the internet. Centralized rule management at $0/mo. Compare that to AWS Security Groups or GCP firewall rules and you start to appreciate Hetzner's philosophy.
Step 8 — UFW Firewall (OS-Level, Double Protection)
Belt and suspenders. The cloud firewall handles the heavy lifting, but UFW inside the server catches anything that slips through — like when you accidentally open a port in the Hetzner console at 1 AM and do not realize it until morning.
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (add this FIRST before enabling the firewall)
sudo ufw allow 22/tcp
# Allow web traffic
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Rate-limit SSH to prevent brute force
sudo ufw limit 22/tcp
# Enable the firewall
sudo ufw enable
# Verify
sudo ufw status verbose
Step 9 — Install & Configure Nginx
# Install Nginx
sudo apt install nginx -y
# Enable and start
sudo systemctl enable nginx
sudo systemctl start nginx
# Verify it's running
sudo systemctl status nginx
# Visit http://YOUR_SERVER_IP — should show Nginx welcome page
# Create the web root
sudo mkdir -p /var/www/yourdomain.com/html
sudo chown -R deploy:www-data /var/www/yourdomain.com
sudo chmod -R 755 /var/www/yourdomain.com
# Add a test page
echo '<h1>Hetzner Cloud VPS is working!</h1>' | sudo tee /var/www/yourdomain.com/html/index.html
# Create the server block
sudo nano /etc/nginx/sites-available/yourdomain.com
Paste this config. It includes security headers that Hetzner's own documentation recommends — one of the few providers whose docs actually mention hardening:
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/yourdomain.com/html;
index index.html index.php;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
# Test and reload
sudo nginx -t
sudo systemctl reload nginx
Step 10 — Domain & DNS Setup
Point your domain at the Hetzner IP. Standard A records at your registrar:
| Type | Name | Value | TTL |
|---|---|---|---|
| A | @ | 203.0.113.30 (your Hetzner IP) | 300 |
| A | www | 203.0.113.30 (your Hetzner IP) | 300 |
# Verify DNS propagation
dig yourdomain.com +short
# Or from within the server:
curl -s https://dnschecker.org/api/dns-lookup/?domain=yourdomain.com&type=A | python3 -m json.tool
Hetzner has its own DNS management under the DNS section. Free, fast, and good enough for most use cases. I still prefer Cloudflare for DNS (old habits), but keeping everything in one console has its appeal.
Step 11 — SSL with Certbot
# Install Certbot
sudo apt install certbot python3-certbot-nginx -y
# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Test automatic renewal
sudo certbot renew --dry-run
# Check certificate status
sudo certbot certificates
Step 12 — hcloud CLI Setup (Optional but Powerful)
This is where Hetzner reveals its inner genius. The hcloud CLI is fast, beautifully documented, and can manage your entire infrastructure from a terminal. Combined with Hetzner's official Terraform provider (not community-maintained like Vultr's), the automation story is best-in-class for a provider at this price point. It feels like a $50/mo provider's tooling at a $5/mo price.
# Install hcloud CLI on Linux
curl -sSL https://github.com/hetznercloud/cli/releases/latest/download/hcloud-linux-amd64.tar.gz | tar -xzv
sudo mv hcloud /usr/local/bin/
hcloud version
# Or on macOS with Homebrew:
brew install hcloud
# Authenticate (get API token from Hetzner Console -> Project -> Security -> API Tokens)
hcloud context create my-project
# Enter your API token when prompted
# List your servers
hcloud server list
# Create a new server
hcloud server create \
--name web02 \
--type cx22 \
--image ubuntu-24.04 \
--location ash \
--ssh-key "my-key"
# Take a snapshot
hcloud server create-image web01 --description "pre-upgrade-$(date +%Y%m%d)" --type snapshot
# List snapshots
hcloud image list --type snapshot
# Manage Hetzner Firewalls via CLI
hcloud firewall create --name web-firewall
hcloud firewall add-rule web-firewall --direction in --protocol tcp --port 22 --source-ips 0.0.0.0/0
hcloud firewall add-rule web-firewall --direction in --protocol tcp --port 80 --source-ips 0.0.0.0/0
hcloud firewall add-rule web-firewall --direction in --protocol tcp --port 443 --source-ips 0.0.0.0/0
# Apply firewall to server
hcloud firewall apply-to-resource web-firewall --type server --server web01
Step 13 — Hetzner-Specific Features (Volumes, Networks, Snapshots)
Volumes (Persistent Block Storage)
Volumes survive server deletion. Detach from one server, attach to another. At $0.052/GB/month (minimum 10GB = $0.52/mo), you can store your database on a separate volume and migrate it between servers without rsync gymnastics. This alone has saved me hours during upgrades.
# Create a 20GB volume in the Hetzner console or via CLI:
hcloud volume create --name data-vol --size 20 --server web01
# The volume appears as a block device (e.g., /dev/sdb)
# Format and mount it:
sudo mkfs.ext4 /dev/sdb
sudo mkdir -p /mnt/data
sudo mount /dev/sdb /mnt/data
# Make it persistent across reboots
echo '/dev/sdb /mnt/data ext4 defaults 0 0' | sudo tee -a /etc/fstab
Private Networks
Free private networking over 10.x.x.x. Your web server and database server talk privately, never touching the public internet. Essential for any setup where MariaDB lives on a separate box.
# Create a private network via hcloud
hcloud network create --name internal-net --ip-range 10.0.0.0/16
# Add your servers to the network
hcloud server attach-to-network web01 --network internal-net --ip 10.0.0.2
hcloud server attach-to-network db01 --network internal-net --ip 10.0.0.3
# Servers can now communicate via 10.0.0.x addresses
Automated Snapshots
# Enable automatic backups in the Hetzner console
# (Backups tab in server settings — costs 20% of server price/mo)
# Or use a cron job with hcloud for manual snapshot schedule:
# Create /usr/local/bin/hetzner-snapshot.sh:
#!/bin/bash
HCLOUD_TOKEN="your-api-token"
SERVER_NAME="web01"
DATE=$(date +%Y%m%d-%H%M)
hcloud server create-image $SERVER_NAME --description "auto-$DATE" --type snapshot
# Keep only last 5 snapshots (cleanup logic here)
# Add to crontab (run daily at 3 AM):
# 0 3 * * * /usr/local/bin/hetzner-snapshot.sh
Step 14 — Common Hetzner Issues (EU Verification, CAPTCHA, Abuse Reports)
Issue: Account requires identity verification
Upload a clear photo of your government ID through the support portal. US driver's licenses and passports both work. One-time process, usually cleared in 1–24 hours. Annoying? Yes. But Hetzner's abuse prevention is why their IP ranges are clean and their servers do not get blacklisted — a trade-off I have come to appreciate.
Issue: CAPTCHA loops on signup
Hetzner's CAPTCHAs are... enthusiastic. If you get stuck in a loop, disable your VPN (biggest trigger), switch browsers, clear cookies, or try incognito mode. The signup page and a VPN connection do not get along.
Issue: Abuse reports blocking server access
# If your server is blocked due to an abuse report, Hetzner will email you
# In the meantime, access via the Hetzner Console (web-based terminal):
# Cloud Console -> Server -> Open Console
# Common causes: open mail relay, cryptocurrency mining, port scanning
# Fix the underlying issue, then respond to the abuse report via support
# Check for suspicious outbound connections:
sudo ss -tulnp
sudo netstat -tulnp | grep ESTABLISHED
# Check for unusual processes:
ps aux --sort=-%cpu | head -20
Issue: Server runs slowly — noisy neighbor
# Check CPU steal time (high steal = noisy neighbor on shared vCPU)
top
# Look for 'st' (steal) column — anything above 5-10% is concerning
# Run a quick CPU benchmark to test current performance:
sysbench cpu --cpu-max-prime=20000 run
# If consistently poor, try rebuilding the server (may land on a different physical host)
# Or upgrade to CCX series (dedicated vCPUs, no steal)
Frequently Asked Questions
Why does Hetzner require identity verification?
Hetzner is a European company (Germany) with strict fraud prevention. New accounts from certain countries or with certain payment patterns may trigger manual verification requiring a copy of ID. This is one-time and usually processed in 1–24 hours. US users generally don't face this but it occasionally happens. Using a VPN during signup increases the chance of triggering verification.
What is the difference between Hetzner CX, CPX, and CCX servers?
CX uses shared vCPUs on AMD EPYC — good baseline performance for web workloads. CPX also uses AMD EPYC with slightly higher clock speeds and better sustained CPU performance. CCX uses dedicated (not shared) AMD EPYC CPU cores — guaranteed performance, no noisy neighbors, higher price. For most workloads, CX or CPX is sufficient. Use CCX for production databases or CPU-intensive applications.
Hetzner Cloud Firewall vs OS firewall — do I need both?
Hetzner Cloud Firewall is network-level — it filters before traffic reaches your server OS. OS firewall (UFW) is software-level inside the VM. Using both provides defense-in-depth: even if UFW is misconfigured, Hetzner's firewall blocks traffic. We recommend both, with Hetzner's firewall as the primary control. The cloud firewall is free and applies instantly without server restarts.
Does Hetzner have DDoS protection?
Yes. Hetzner has upstream DDoS mitigation at their network level. It is not as prominently advertised as Vultr's but is present and effective for typical attacks. Hetzner will temporarily null-route attacked IPs during extreme volume attacks (100+ Gbps). For high-risk services (game servers, crypto exchanges), combine Hetzner with Cloudflare for best protection.
Can I use Hetzner for US-based websites?
Yes. Their Ashburn VA datacenter provides excellent East Coast latency (typically <10ms to major Eastern US cities). West Coast users will see higher latency (~70–80ms) — choose Vultr LA or DO SFO3 for West Coast. For purely US-East workloads, Hetzner's price-to-performance is unmatched. Pair with Cloudflare CDN for global coverage.
Is Hetzner GDPR compliant for US websites?
Hetzner is a German company and fully GDPR compliant. Their Ashburn VA datacenter stores data on US soil, which simplifies compliance for US-focused sites. If you serve EU users, Hetzner's German/Finnish datacenters keep data within the EU. For US-only sites using the Ashburn DC, GDPR is not a concern — your data never leaves the US.
What payment methods does Hetzner accept?
Hetzner accepts credit cards (Visa, Mastercard), PayPal, and bank transfer (SEPA for EU). No cryptocurrency. The minimum deposit is variable. Hetzner requires identity verification for new accounts — you may need to upload a government ID. This is standard for German hosting companies and typically takes 1–24 hours to process.
A Porsche at Honda Money
$4.59/mo. 2 vCPU. 4GB RAM. 40GB NVMe. The interface is German. The value is unbeatable.