How to Deploy a Next.js App on a DigitalOcean VPS (Step-by-Step)
Hamid Sabri / November 2, 2025

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
- Go to DigitalOcean → Droplets → Create.
- 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
- Open Git Bash or PowerShell
- Run:
ssh-keygen - Hit Enter to accept defaults (no passphrase needed unless you want one).
- Your SSH key will be stored here:
C:\Users\<YourUserName>\.ssh\id_rsa.pub - Open it and copy the full key.
On macOS / Linux
- Run:
ssh-keygen - Press Enter to confirm default location.
- 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:
- Go to Repository → Settings → Deploy keys
- Click Add deploy key
- Title it something like
server - Paste in the public key you just generated
- ✅ Check “Allow read access” only (leave “write access” unchecked)
- 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 - A —
www— 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!