Back to posts

How to Deploy a Next.js App on a DigitalOcean VPS (Step-by-Step)

Hamid Sabri / November 2, 2025

Deploy Next.js to a DigitalOcean VPS

If you’ve ever wanted to deploy your Next.js app on your own VPS instead of paying for managed platforms, this guide is for you.
We’ll cover everything from creating your server on DigitalOcean to automating your deployments with GitHub Actions.


Step 1 — Create Your Droplet

  1. Go to DigitalOcean → Droplets → Create.
  2. Choose:
    • Ubuntu 22.04 (LTS)
    • Basic / Regular / $6 per month plan
    • Region: closest to your audience
    • Authentication: select SSH Key

Don’t Have an SSH Key Yet?

On Windows

  1. Open Git Bash or PowerShell
  2. Run:
    ssh-keygen
  3. Hit Enter to accept defaults (no passphrase needed unless you want one).
  4. Your SSH key will be stored here:
    C:\Users\<YourUserName>\.ssh\id_rsa.pub
    
  5. Open it and copy the full key.

On macOS / Linux

  1. Run:
    ssh-keygen
  2. Press Enter to confirm default location.
  3. Then copy it:
    cat ~/.ssh/id_rsa.pub

🔹 Back on DigitalOcean

Paste your SSH key in the “Add SSH Key” box, name it (e.g. My-MacBook), and click Create Droplet.


Step 2 — Connect to Your VPS

From your terminal:

ssh root@your-vps-ip

Update and upgrade:

apt update && apt upgrade -y

Create a new user:

adduser user_name
usermod -aG sudo user_name

Allow SSH for the New User

sudo su - user_name
mkdir .ssh && cd .ssh
touch authorized_keys
nano authorized_keys

Paste your public key from your local machine, save (Ctrl + X, Y, Enter), then secure permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Exit and reconnect:

exit
exit
ssh user_name@your-vps-ip

✅ You can now log in directly with your SSH key — no password.


Step 3 — Install Node.js and PM2 (via NVM)

Install NVM:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
source ~/.bashrc

Install Node.js (LTS) and PM2:

nvm install --lts
npm install -g pm2

Check:

node -v
npm -v
pm2 -v

Step 4 — Install and Configure Nginx

Install Nginx:

sudo apt install nginx -y

Create config:

sudo nano /etc/nginx/sites-available/your_app_name

Paste:

server {
    server_name your_domain.com www.your_domain.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 and test:

sudo ln -s /etc/nginx/sites-available/your_app_name /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 5 — Clone Your Project

From your VPS home directory:

cd ~
git clone git@github.com:your_username/your_repo_name.git
cd your_repo_name
npm install
npm run build

Test:

npm start

Visit http://your-vps-ip:3000 to confirm it’s running.


Step 5.1 — Add a Deploy Key for Your Server

Your VPS needs permission to pull updates from your private GitHub repository.
We’ll generate a new SSH key on the VPS and add it to GitHub as a Deploy Key.

On your VPS:

ssh-keygen 
cat ~/.ssh/id_rsa.pub

Then on GitHub:

  1. Go to Repository → Settings → Deploy keys
  2. Click Add deploy key
  3. Title it something like server
  4. Paste in the public key you just generated
  5. ✅ Check “Allow read access” only (leave “write access” unchecked)
  6. Click Add key

Now your VPS can securely pull updates from your repo.

You can verify the connection:

ssh -T git@github.com

If you see:

Hi your_username! You've successfully authenticated, but GitHub does not provide shell access.

→ You’re good to go.

Then test pulling from your repo:

cd ~/your_repo_name
git pull origin production

Step 6 — Run App with PM2

pm2 start npm --name "your_app_name" -- start
pm2 save
pm2 startup

Your app now restarts automatically on reboot.


Step 7 — Add SSL with Certbot

Install and run:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
sudo certbot renew --dry-run

Step 8 — Point Your Domain

Add DNS records (Hostinger, Namecheap, etc.):

  • A@ — your VPS IP — 3600
  • Awww — your VPS IP — 3600
nslookup your_domain.com

Step 9 — Automate Deployment (GitHub Actions)

Create .github/workflows/deploy.yml

name: Deploy to VPS

on:
  push:
    branches:
      - production

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: SSH and deploy
        uses: appleboy/ssh-action@v0.1.10
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script_stop: true
          shell: bash
          script: |
            export NVM_DIR="/home/user_name/.nvm"
            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
            [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
            export PATH=$PATH:/home/user_name/.nvm/versions/node/v24.11.0/bin

            cd /home/user_name/your_repo_name
            git pull origin production
            npm install
            npm run build
            pm2 restart your_app_name || pm2 start npm --name "your_app_name" -- start
            pm2 save

Deploy with:

git checkout production
git merge main --no-edit
git push origin production

Step 10 — (Optional) Deploy PostgreSQL Database

Create .env.production:

cd ~/your_repo_name
nano .env.production

Paste:

DATABASE_URL="postgresql://db_user:password@localhost:5432/db_name"

Install PostgreSQL:

sudo apt-get install postgresql postgresql-contrib -y
sudo -i -u postgres
createuser --pwprompt db_user
createdb -O db_user db_name
exit

Run Prisma migrations:

npx prisma generate
npx prisma migrate deploy

Rebuild and restart:

npm run build
pm2 restart your_app_name
pm2 save

✅ Done — your Next.js app now runs on a full-stack VPS setup with database, HTTPS, and automated deployment!