Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save oelbaga/5019647715e68815c602ff05cff2416e to your computer and use it in GitHub Desktop.
Save oelbaga/5019647715e68815c602ff05cff2416e to your computer and use it in GitHub Desktop.
Setup NextJS app on Digital Ocean Ubuntu server Full Terminal Commands Step by Step
#Setup NextJS on Ubuntu server (Digital Ocean, EC2,...) Terminal Commands
#based on my YouTube video
#Recommended: An ubuntu server with at least 2 GB memory to handle npm run build
#login to server
ssh root@ip_address
#Upgrade Server - may take a few minutes
sudo apt update
sudo apt upgrade
#Install NGINX and Certbot
sudo apt install nginx certbot python3-certbot-nginx
#Allow Firewall Access
sudo ufw allow "Nginx Full"
ufw allow OpenSSH
ufw enable
#Install NPM - may take a couple of minutes
apt install npm
#install nodejs
#Option 1: install nodejs with nvm
curl -o- | bash
exec $SHELL
nvm install --lts
nvm install 20 #or version of choice
nvm use 20
nvm alias default 20
#Option 2:
curl -fsSL | sudo -E bash -
sudo apt-get install -y nodejs
#Install pm2
npm install -g pm2
#Check pm2 is working
pm2 status
cd /root/.ssh
ssh-keygen -t rsa -b 4096 -C ""
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/
#add public key to github repo settings > deploy key [or add to your profile settings > SSH so you can pull from all repos]
#go to www root
cd /var/www
#Create NextJS App or clone here
Option 1: npx create-next-app@latest name_of_app
Option2: clone with a specific branch. [You need SSH permissions from above for this].
A: git clone
or B (by specifying a branch): git clone -b <branch-name-optional> <local-name-desired-optional>
#note the name of the directory created for later to launch pm2 app
#Go inside new app directory
cd name_of_app
#Install npm modules for app
npm i
#Build it
npm run build
#Create NGINX config file and edit it
cd /etc/nginx/sites-available
touch name_of_app
nano name_of_app
#Syslink the file in sites-enabled
sudo ln -s /etc/nginx/sites-available/name_of_app /etc/nginx/sites-enabled/name_of_app
#make Sure NGINX file is good
nginx -t
#remove the default config files
cd /etc/nginx/sites-available
rm default
cd /etc/nginx/sites-enabled
rm default
#restart NGINX to reload config files
systemctl restart nginx
#Go to site directory and launch it with pm2
cd /var/www/name_of_app
#launch app with pm2
#Option 1:
pm2 start npm --name name_of_app -- start
#Option 2: if you need to launch on a different port. It seems this port should match what's used in the server block.
pm2 start npm --name nest -- start -- --port=3001
#save pm2 list
pm2 save
#pm2 restart on reboot
pm2 startup
#Create SSL with letsencryot
sudo certbot --nginx -d -d
#redirect site to www version
Go back in server block where the domain is managed by certbot and add www. To the redirect.
————— helpful commands ————
pm2 start npm --name name_of_app -- start (make sure you're inside the site's directory first)
systemctl restart nginx (restart NGINX)
sudo certbot --nginx -d (Add SSL)
#nginx config file for Nextjs App
#place in /etc/nginx/sites-available/name_of_config_file
server {
listen 80;
server_name; #if no domain you can use server ip until then
gzip on;
gzip_proxied any;
gzip_types application/javascript application/x-javascript text/css text/javascript;
gzip_comp_level 5;
gzip_buffers 16 8k;
gzip_min_length 256;
location /_next/static/ {
alias /var/www/name_of_app/.next/static/;
expires 365d;
access_log off;
location / {
proxy_pass; #change ports for second app i.e. 3001,3002
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;
1. Allow pulling from GitHub onto Digital ocean (if not done already).
- Create a new id_rsa key on your droplet
cd /root/.ssh
ssh-keygen -t rsa -b 4096 -C ""
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/
- add public key to git hub repo settings > deploy key [or add to your profile settings > SSH so you can pull from all repos]
- Now clone the entire repo for the first time under /var/www
2. Setup auto-deployment from GitHub commits to ubuntu server with Github actions
- local terminal ssh
cd .ssh
ssh-keygen -t rsa -b 4096 -C ""
- Copy that key to add to the server
cat ~/.ssh/
- Add public key to .ssh on ubuntu server
cd /root/.ssh
nano authorized_keys
- Copy that private key to add to GitHub
cat ~/.ssh/id_rsa
- Add private key Github repo
Settings > Secrets > Actions > New repository secret. Label: SSH_PRIVATE_KEY
Configure GitHub Actions with a deploy yml file:
- In your repository, create a new directory .github/workflows with a file called deploy.yml.
[SEE yml FILE] #
# Update to match your values: branch_name, app_name, SSH key name on GitHub from previous step if changed, server ip, username, port, and server Node pathname (using 'which pm2' on server to get path)
name: Deploy Next.js App
- branch_name # Change to your specific branch
# - deployprod # Additional branch for deployment
runs-on: ubuntu-latest
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
node-version: "20"
- name: Check Node.js version
run: node -v
- name: Set up SSH
uses: webfactory/ssh-agent@v0.5.1
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy to DigitalOcean
TARGET_DIR: /var/www/folder_name
APP_NAME: app_name #should match the name of the server block
PORT: 3000
#if multiple deploys are needed from different branches
#TARGET_DIR: ${{ github.ref == 'refs/heads/deploytest' && '/var/www/folder_name' || github.ref == 'refs/heads/deployprod' && '/var/www/another-location' }}
#APP_NAME: ${{ github.ref == 'refs/heads/deploytest' && 'folder_name' || github.ref == 'refs/heads/deployprod' && 'folder_name_2' }}
#PORT: ${{ github.ref == 'refs/heads/deploytest' && '3000' || github.ref == 'refs/heads/deployprod' && '3001' }}
run: |
ssh -o StrictHostKeyChecking=no $USERNAME@$HOST << EOF
export PATH=/root/.nvm/versions/node/v20.12.0/bin:$PATH #'which pm2' command on terminal will give the right path
git pull origin ${GITHUB_REF#refs/heads/}
npm install
npm run build
if pm2 list | grep -q $APP_NAME; then
echo "Restarting application: $APP_NAME"
pm2 restart $APP_NAME
echo "Starting application: $APP_NAME"
pm2 start npm --name $APP_NAME -- start -- --port=$PORT
pm2 save
Copy link

ripon52 commented Aug 17, 2023

i am getting 502 bad gateway

Copy link

Thank you, this is very helpful

Copy link

i am getting 502 bad gateway

check error with "pm2 logs" commands

Copy link

otsolap commented Oct 16, 2023

Thank you for this file and the Youtube tutorial. It helped me make my own NextJS app on an Ubuntu server. 8)

Copy link

ltshv commented Nov 18, 2023

sorry, but with that configuration i cant clone or build app with 'unable to resolve host' error, my '/etc/resolv.conf' file is always updates with '' nameserver

Copy link

Thank you!

Copy link

Images i used from public folder are not showing on production. Any Fix @oelbaga

Copy link

Thank you!

Copy link

Thank you very much. Unforunately, currently I can't display the sitemap.xml from the public folder.

Copy link

oelbaga commented Apr 6, 2024

i am getting 502 bad gateway

I updated to try to clarify steps. It means something is not pointing correctly, Pm2 app not started or something wrong with the server block file. Review those. Remember to also cd into the app_directory to start the app using pm2

Copy link

Awesome, very useful and spelled out nicely

Copy link

Hi @oelbaga,
I just to want to shared my experience, maybe some other dev will have the same issues. I follow your video and guide, and for the most part I had no issues, but I was not able to access the mydomain form my local machine, I used my browser and I notice that it was getting a time out.
And from the ubuntu VM I curl to https://www.mydomain and same thing.

I fixed my issue by adding on my local host file
And on Azure, I added a new inbound rule to allow TCP port 443.

I'm kind of new using ubuntu and setting up domains on azure, so for me it was kind of tricky to fix.

Copy link

Hello, thank you for your good teaching

I have a problem, I install correctly, but when I want to update, I have a problem, I have to delete all the items from the beginning and run npm i and npm run build again.
What should I do to update?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment