Skip to main content

Deploy Next.js on DigitalOcean Droplet — complete guide

TL;DR

Step-by-step guide to deploying a Next.js application on a DigitalOcean Droplet with PM2, nginx, and SSL.

Key facts

Topology
Next.js on DigitalOcean

TL;DR

This guide walks through deploying a Next.js application to a DigitalOcean Droplet with Node.js, PM2, nginx, and SSL — a production-ready setup without vendor lock-in.

Prerequisites

  • A DigitalOcean account and a Droplet running Ubuntu 24.04 (minimum 2 GB RAM for Next.js builds)
  • A domain name with DNS pointing to the Droplet's IP
  • Your Next.js project in a Git repository

Step 1 — Droplet setup

SSH into your Droplet and prepare the system:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git build-essential

Install Node.js 22 LTS:

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs

Step 2 — Deploy the application

sudo mkdir -p /var/www/nextapp
sudo chown $USER:$USER /var/www/nextapp
cd /var/www/nextapp
git clone git@github.com:yourorg/nextapp.git .
npm ci

Create your .env.production with the correct NEXT_PUBLIC_* variables, then build:

npm run build

Step 3 — Process management with PM2

sudo npm install -g pm2
pm2 start npm --name "nextapp" -- start
pm2 startup systemd
pm2 save

For standalone output mode (recommended for production), update next.config.js:

module.exports = { output: 'standalone' };

Then run the standalone server:

pm2 start .next/standalone/server.js --name "nextapp" -i max

Step 4 — nginx reverse proxy

sudo apt install -y nginx
server {
    listen 80;
    server_name example.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;
    }

    location /_next/static {
        alias /var/www/nextapp/.next/static;
        expires 365d;
        access_log off;
    }
}
sudo ln -s /etc/nginx/sites-available/nextapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 5 — SSL with Let's Encrypt

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com

Certbot's auto-renewal timer is enabled by default. Verify with:

sudo systemctl status certbot.timer

With Reflex

Connect your Droplet to Reflex for continuous monitoring and safe deployments. Reflex handles zero-downtime PM2 reloads, tracks Next.js build performance, monitors nginx error rates, and can auto-fix common issues like stale builds or memory spikes — all from a single dashboard. See How it works.