For a long time, I relied exclusively on Vercel for my Next.js projects. The developer experience is unmatched, but as my traffic grew, so did the ‘bandwidth anxiety.’ If you’ve ever looked at a surprise bill from a serverless platform, you know exactly what I mean. That’s why I started looking for a more predictable, cost-effective alternative. In this guide, I’ll show you how to deploy Next.js on Hetzner, which offers a fantastic balance of raw performance and aggressive pricing.

Before we dive in, it’s worth noting that while Vercel is great for hobbyists, moving to a VPS (Virtual Private Server) gives you full control over your environment. If you’re curious about how Hetzner stacks up against other providers, check out my Hetzner Cloud review for developers.

Prerequisites

Before we start the deployment process, make sure you have the following ready:

Step 1: Provisioning your Hetzner Server

I recommend starting with the CX21 or CX31 instance for Next.js. While the smallest plan works, Next.js builds can be memory-intensive and might crash on 2GB RAM instances without a swap file.

  1. Log into the Hetzner Cloud Console.
  2. Click Create Server.
  3. Select Ubuntu 22.04 LTS as your image.
  4. Choose the location closest to your users (e.g., Falkenstein or Helsinki).
  5. Add your SSH key (avoid using passwords for security).
  6. Click Create & Buy Now.

Step 2: Preparing the Server Environment

Once you’ve SSH’d into your server (ssh root@your_server_ip), we need to install the necessary runtime. I prefer using NVM (Node Version Manager) to handle Node.js versions.

# Update system packages
sudo apt update && sudo apt upgrade -y

# Install NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
. ~/.nvm/nvm.sh

# Install the latest LTS version of Node
nvm install --lts

# Install PM2 to keep your app running in the background
npm install -g pm2
Terminal screenshot showing successful installation of Node.js and PM2 on Ubuntu
Terminal screenshot showing successful installation of Node.js and PM2 on Ubuntu

Step 3: Deploying the Next.js Application

Now, let’s pull your code and get it running. I’ll use a simple Git-based deployment here, though for larger teams, you might consider a CI/CD pipeline. If you’re managing multiple apps, you might find deploying a monorepo more complex, but the principle of server-side build remains the same.

# Clone your repository
git clone https://github.com/yourusername/your-nextjs-app.git
cd your-nextjs-app

# Install dependencies
npm install

# Create your .env file
nano .env.local
# (Add your environment variables here, then Ctrl+O, Enter, Ctrl+X)

# Build the application
npm run build

Now we use PM2 to start the application. PM2 ensures that if the app crashes or the server reboots, your site comes back online automatically.

pm2 start npm --name "next-app" -- start
pm2 save
pm2 startup

Step 4: Setting up Nginx as a Reverse Proxy

By default, Next.js runs on port 3000. We don’t want users typing yourdomain.com:3000. We’ll use Nginx to route traffic from port 80 (HTTP) and 443 (HTTPS) to port 3000.

# Install Nginx
sudo apt install nginx -y

# Create a config file for your site
sudo nano /etc/nginx/sites-available/next-app

Paste the following configuration (replace yourdomain.com with your actual domain):

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

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Enable the config and restart Nginx:

sudo ln -s /etc/nginx/sites-available/next-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Nginx configuration file for Next.js reverse proxy in VS Code
Nginx configuration file for Next.js reverse proxy in VS Code

Step 5: Enabling SSL with Let’s Encrypt

Security is non-negotiable. Use Certbot to get a free SSL certificate from Let’s Encrypt.

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts, and Certbot will automatically update your Nginx config to redirect all HTTP traffic to HTTPS.

Pro Tips for Production

Troubleshooting Common Issues

The build fails with “JavaScript heap out of memory”

This is common on small VPS instances. Increase the Node memory limit during build:

NODE_OPTIONS="--max-old-space-size=2048" npm run build

Nginx shows “502 Bad Gateway”

This usually means your Next.js app isn’t running on port 3000. Check your PM2 status with pm2 list and ensure the app is “online”.

What’s Next?

Now that you’ve mastered how to deploy Next.js on Hetzner, you might be wondering about other hosting options. If you’re comparing PaaS options, my guide on Railway.app vs Vercel explores the middle ground between a raw VPS and a fully managed platform.

Ready to scale? Consider setting up a separate database server on Hetzner to keep your application and data decoupled.