DeployWise
HomeGuidesDeploy Next.js to Hetzner
HetznerNext.jsGuide

Deploy Next.js to Hetzner VPS with PM2 & Nginx

A complete, hands-on guide to deploying a production-ready Next.js application on Hetzner Cloud. Covers server provisioning, Node.js setup, PM2 process management, Nginx reverse proxy, free SSL, and automated deployments via GitHub webhooks.

12 min read
Updated 2026

Why Hetzner for Next.js?

Hetzner is the best-value VPS provider for hosting Next.js apps in 2026. Their CX22 plan gives you 2 vCPU, 4 GB RAM, and 20 TB bandwidth for just €4.15/mo ($4.51) — that's 200x more bandwidth than Vercel's free tier at a fraction of the cost of Vercel Pro.

Best price-to-performance ratio of any cloud provider
EU and US datacenter locations (Falkenstein, Nuremberg, Helsinki, Ashburn, Hillsboro)
20 TB bandwidth included on every plan — no overage charges
ARM-based Ampere servers (CAX line) for even lower prices
NVMe SSD storage on all plans
Hourly billing — pay only for what you use

Hetzner server tiers for Next.js

Here are the three Hetzner plans we recommend for Next.js deployments. The CX22 handles most projects. Pick CX32 if you run multiple apps, or CAX11 (ARM) if you want the absolute cheapest option.

PlanArchPriceCPURAMSSDBandwidth
CX22x86€4.152 vCPU4 GB40 GB20 TB
CX32x86€7.004 vCPU8 GB80 GB20 TB
CAX11ARM€3.792 vCPU4 GB40 GB20 TB

Tip: The CAX11 ARM server is €3.79/mo and runs Next.js perfectly. Node.js has excellent ARM support. Just make sure your npm dependencies don't require x86-only native binaries.

Prerequisites

A GitHub account with your Next.js repository
A Hetzner Cloud account (free to create)
A domain name pointed to your server IP (for SSL)
Basic terminal / SSH knowledge

1Create a Hetzner Cloud server

Log in to Hetzner Cloud Console and click Create Server. Configure the following:

LocationAshburn (US East) or Falkenstein (EU) — pick closest to your users
ImageUbuntu 22.04 LTS
TypeCX22 (2 vCPU, 4 GB RAM, 40 GB SSD)
SSH KeyAdd your public SSH key (or create one with ssh-keygen -t ed25519)
Namenextjs-production (or any label you prefer)

Click Create & Buy Now. Your server will be ready in about 10 seconds. Copy the IP address — you'll need it next.

2Initial server setup

SSH into your new Hetzner server and run the initial hardening steps:

# Connect to your server
ssh root@YOUR_SERVER_IP

# Update packages
apt update && apt upgrade -y

# Set up UFW firewall
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

# (Optional) Create a non-root user
adduser deploy
usermod -aG sudo deploy
cp -r ~/.ssh /home/deploy/
chown -R deploy:deploy /home/deploy/.ssh

Your server is now secured with a firewall that only allows SSH, HTTP, and HTTPS traffic. All other ports are blocked by default.

3Install Node.js, PM2, and Nginx

Install the runtime and tools your Next.js app needs:

# Install Node.js 20 LTS via NodeSource
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
apt install -y nodejs

# Verify installation
node -v   # v20.x.x
npm -v    # 10.x.x

# Install PM2 globally
npm install -g pm2

# Install Nginx
apt install -y nginx
systemctl enable nginx
systemctl start nginx

Visit http://YOUR_SERVER_IP in your browser — you should see the default Nginx welcome page. That confirms Nginx is running and ports 80/443 are open.

4Deploy your Next.js app

Clone your repository and start the app with PM2:

# Create app directory
mkdir -p /var/www && cd /var/www

# Clone your repo
git clone https://github.com/YOUR_USER/YOUR_REPO.git myapp
cd myapp

# Install dependencies
npm ci

# Build the Next.js app
npm run build

# Start with PM2
pm2 start npm --name "myapp" -- start
pm2 save
pm2 startup

The pm2 startup command generates a systemd service so PM2 (and your app) restarts automatically if the server reboots. Run the command it outputs to complete the setup.

Using a PM2 ecosystem file gives you more control. Create ecosystem.config.js in your project root:

module.exports = {
  apps: [
    {
      name: "myapp",
      script: "node_modules/.bin/next",
      args: "start",
      cwd: "/var/www/myapp",
      instances: "max",
      exec_mode: "cluster",
      env: {
        NODE_ENV: "production",
        PORT: 3000,
      },
    },
  ],
};

Then start with pm2 start ecosystem.config.js. Cluster mode spawns one process per CPU core, maximizing throughput on the CX22's 2 vCPUs.

5Configure Nginx reverse proxy

Create an Nginx server block that forwards HTTP traffic to your Next.js app running on port 3000:

# /etc/nginx/sites-available/myapp

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    # Cache static assets
    location /_next/static/ {
        proxy_pass http://127.0.0.1:3000;
        expires 365d;
        access_log off;
        add_header Cache-Control "public, immutable";
    }
}

Enable the site and reload Nginx:

# Enable the site
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/

# Remove the default site
rm /etc/nginx/sites-enabled/default

# Test and reload
nginx -t
systemctl reload nginx

Your Next.js app is now accessible at http://yourdomain.com. The Nginx config also caches Next.js static assets with a one-year expiry for optimal performance.

6SSL with Let's Encrypt

Install Certbot and obtain a free SSL certificate:

# Install Certbot
apt install -y certbot python3-certbot-nginx

# Obtain and auto-configure SSL
certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Verify auto-renewal
certbot renew --dry-run

Certbot automatically modifies your Nginx config to redirect HTTP to HTTPS and adds the SSL certificate paths. Certificates auto-renew every 90 days via a systemd timer — zero maintenance required.

7Set up GitHub webhook for auto-deploy

Create a simple deploy script on your server so every git push to main triggers a fresh build:

#!/bin/bash
# /var/www/deploy.sh

cd /var/www/myapp
git pull origin main
npm ci
npm run build
pm2 restart myapp

You can trigger this script with a lightweight webhook listener like webhook (adnanh/webhook) or a simple Express endpoint. For detailed instructions, see our GitHub webhooks auto-deploy guide.

Or: skip all 7 steps with DeployWise

DeployWise automates everything above. Connect your GitHub repo and your Hetzner server — DeployWise installs Node.js, configures PM2, sets up Nginx, provisions SSL, and deploys your app. Push to GitHub, and it auto-deploys.

1.Sign in with GitHub
2.Add your Hetzner server (IP + SSH key)
3.Select your repo, branch, and start command
4.Click Deploy — live in under 2 minutes

No SSH commands. No config files. No forgetting to restart PM2 after a deploy. Every step in this guide is automated by DeployWise.

Hetzner vs other VPS providers

A quick comparison of the entry-level plan suitable for Next.js from each provider:

ProviderPriceCPURAMBandwidthVerdict
Hetzner CX22$4.512 vCPU4 GB20 TBBest value
DigitalOcean$61 vCPU2 GB2 TBBest docs
Vultr$61 vCPU2 GB2 TBMost locations
Linode$51 vCPU1 GB1 TBReliable
Vercel Pro$20ServerlessN/A1 TBEasiest, priciest

For most indie developers and small teams, Hetzner's CX22 delivers 4x the RAM, 10x the bandwidth, and half the price of DigitalOcean's entry plan. The only downside is no Asia-Pacific datacenters — if your users are primarily in Asia, consider Vultr or DigitalOcean instead.

Ready to deploy to Hetzner?

Sign in with GitHub, add your Hetzner server, and have your Next.js app live in under 2 minutes — for free.

Open DeployWise Dashboard

Related guides