Disclosure: we may earn a commission or referral reward from CloudCone, Contabo, DigitalOcean (account credit, not cash), Hostwinds, InterServer, RackNerd, VPSDime and Vultr if you sign up through our links. It does not change the price you pay. Every other provider pays us nothing. Prices in this guide are as of the date shown and may have changed; see the comparison pages for the latest checked prices.
Guides · BLOG
How to host a Next.js app on a $5 VPS in 2026
Some prices quoted in this guide are out of date. It is being rebuilt on our price index; for current prices use the comparison pages, which show when each price was checked.
You don't need Vercel to host Next.js. A $4.60 Hetzner CX22 runs a production Next.js app comfortably — supporting SSR, ISR, image optimization, API routes, everything. This guide walks through the setup end-to-end.
Prices as of 2026-09-22.
Why do this
- Vercel Hobby is free for personal projects. If it fits, use it.
- Vercel Pro is $20/user/month plus usage-based Function/Bandwidth costs. A busy site can end up at $50-200/mo quickly.
- A Hetzner CX22 at $4.60/mo runs a Next.js app up to reasonably heavy traffic (10-50 req/s sustained) with room for more.
- Vercel is priced for the developer experience. You're paying for git-push deploys, previews, and edge network. If those matter, pay for Vercel. If they don't, a VPS is 90% cheaper.
What you're not getting
- Automatic edge network. You'll use Cloudflare in front for CDN (free tier).
- Preview deploys per pull request. Set up a
staging.yourdomain.comand rsync it manually. - Zero-configuration serverless functions with edge routing. You're on a Node.js process.
- Automatic image optimization at CDN. Next's built-in Image component works on Node.js self-hosted; it's optimised at request time, not at build time to a CDN.
The stack
- Hetzner CX22: 2 vCPU, 4 GB RAM, Ubuntu 24.04 LTS.
- Node.js 20 LTS via NodeSource.
- PM2 or systemd for process management.
- Nginx as a reverse proxy for TLS termination and static file serving.
- Certbot for Let's Encrypt SSL.
- Cloudflare in front for CDN and DDoS protection (free).
Step 1: Provision Hetzner CX22
Create the server. Ubuntu 24.04 LTS. Basic hardening: adduser deploy, SSH keys, disable password auth, UFW. See our shared hosting to VPS weekend guide for the exact commands.
Step 2: Install Node.js and PM2
```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
sudo apt install -y nodejs
Install PM2 globally
sudo npm install -g pm2
Have PM2 start on reboot
pm2 startup
Follow the sudo command it prints
```
Step 3: Deploy your Next.js app
Option A — git clone directly:
```bash
cd /var/www
sudo git clone https://github.com/YOURORG/YOURAPP.git yourapp
sudo chown -R deploy:deploy yourapp
cd yourapp
npm ci --production=false
npm run build
```
Option B — build locally, rsync the .next and public and package.json:
```bash
On your local machine:
npm run build
rsync -avz .next public package.json package-lock.json next.config.js deploy@vps-ip:/var/www/yourapp/
```
Option B avoids build overhead on a small VPS but requires you to commit to a workflow.
Step 4: Start with PM2
```bash
cd /var/www/yourapp
pm2 start npm --name "yourapp" -- start
pm2 save
```
pm2 status shows the running app. pm2 logs yourapp streams logs.
Alternatively, systemd:
```
[Unit]
Description=Next.js app
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/var/www/yourapp
ExecStart=/usr/bin/npm start
Restart=always
Environment=NODE_ENV=production
Environment=PORT=3000
[Install]
WantedBy=multi-user.target
```
Step 5: Nginx reverse proxy
```nginx
server {
server_name yourdomain.com www.yourdomain.com;
location /_next/static/ {
alias /var/www/yourapp/.next/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location /public/ {
alias /var/www/yourapp/public/;
expires 1y;
}
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_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;
}
}
```
sudo certbot --nginx -d yourdomain.com for SSL.
Step 6: Cloudflare in front
- Point your DNS at Cloudflare.
- Add an A record to your Hetzner IP.
- Enable Cloudflare's proxy (orange cloud).
- Set SSL mode to "Full (strict)".
- Add a page rule to cache HTML for 1 hour on public marketing pages.
You now have a CDN in front for free. Cloudflare's free tier is plenty for most Next.js apps.
Environment variables
Store secrets in /etc/systemd/system/yourapp.service.d/env.conf:
```
[Service]
Environment="DATABASE_URL=postgres://..."
Environment="API_KEY=..."
```
Or use PM2's ecosystem file. Do not commit secrets to git.
Deployment script
~/deploy.sh on your local machine:
```bash
#!/bin/bash
set -e
npm run build
rsync -avz --delete .next/ public/ package.json package-lock.json next.config.js deploy@vps-ip:/var/www/yourapp/
ssh deploy@vps-ip "cd /var/www/yourapp && npm ci --production && pm2 restart yourapp"
```
chmod +x ~/deploy.sh. Deploy with ~/deploy.sh.
Zero-downtime deploys
Use PM2's built-in restart to keep the process running during the rebuild. Alternative: use a second port and swap Nginx upstream (blue/green).
Cost view
- Hetzner CX22: $4.60/mo
- Cloudflare free tier: $0
- Backblaze B2 for backups: ~$0.50/mo
- Domain: variable, ~$1/mo amortised
- Total: ~$6/mo
Vercel Pro for the same site: $20-100+/mo depending on function invocations and bandwidth.
When to give up and pay for Vercel
- You need preview deploys per pull request and don't want to build them yourself.
- You need genuinely global edge network and Cloudflare's free tier isn't enough.
- You need Vercel-specific features like Edge Functions with sub-50ms latency worldwide.
- Your team's DX is worth more than the price gap.
Related guides
- Best hosting for a Node.js API — the pure API version.
- Best hosting for a small SaaS MVP — MVP-scale hosting.
- Cheapest VPS under $10 in 2026 — Hetzner CX22 in context.
Prices as of 2026-09-22.