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- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
exec $SHELL
nvm install --lts
nvm install 20 #or version of choice
nvm use 20
nvm alias default 20
#Option 2:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
#Install pm2
npm install -g pm2
#Check pm2 is working
pm2 status
#[SETUP SSH KEY ON SERVER TO ALLOW CLONE AN EXISTING REPO ONTO YOUR DROPLET]
cd /root/.ssh
ssh-keygen -t rsa -b 4096 -C "username@email.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub
#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 git@github.com:username/repo_name.git
or B (by specifying a branch): git clone -b <branch-name-optional> git@github.com:username/repo_name.git <local-name-desired-optional>
#note the name of the directory created for later to launch pm2 app
ls
#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
[SEE OTHER GIST FOR CONFIG FILE (Server Block) CONTENTS]
#https://gist.github.com/oelbaga/5019647715e68815c602ff05cff2416e#file-02-nginx-config-file-for-nextjs-site
#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 domainname.com -d www.domainname.com
#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 domainname.com (Add SSL)
#nginx config file for Nextjs App
#place in /etc/nginx/sites-available/name_of_config_file
server {
listen 80;
server_name domainname.com www.domainname.com; #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 http://127.0.0.1:3000; #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 "your_email@example.com"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub
- 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 "oelbaga@newworldgroup.com"
- Copy that key to add to the server
cat ~/.ssh/id_rsa.pub
- 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] #https://gist.github.com/oelbaga/5019647715e68815c602ff05cff2416e#file-04-github-actions-for-auto-deployment-deploy-yml
# 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
on:
push:
branches:
- branch_name # Change to your specific branch
# - deployprod # Additional branch for deployment
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Check Node.js version
run: node -v
- name: Set up SSH
uses: webfactory/ssh-agent@v0.5.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Deploy to DigitalOcean
env:
HOST: XX.XX.XX.XX
USERNAME: root
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
cd $TARGET_DIR
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
else
echo "Starting application: $APP_NAME"
pm2 start npm --name $APP_NAME -- start -- --port=$PORT
fi
pm2 save
EOF
@jakshybala
Copy link

thank you

@ripon52
Copy link

ripon52 commented Aug 17, 2023

i am getting 502 bad gateway

@ZwangaMukwevho
Copy link

Thank you, this is very helpful

@ilyasdev3
Copy link

i am getting 502 bad gateway

check error with "pm2 logs" commands

@otsolap
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)

@ltshv
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 '127.0.0.53' nameserver

@SarkisMKRtchian
Copy link

Thank you!

@joerush18
Copy link

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

@datasistah
Copy link

Thank you!

@hilmanski
Copy link

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

@oelbaga
Copy link
Author

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

@Ocelloid
Copy link

Awesome, very useful and spelled out nicely

@fernandovch
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
127.0.0.1 www.mydomain.com
127.0.0.1 mydomain.com
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.

@msaebi031
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?

@nyanzi-ashraf
Copy link

This is a life save. Thanks so much!

@maxschneidercodes
Copy link

Thank you!!!

@rajeshkumaryadavdotcom
Copy link

I tried this today, excellent video and command, all worked fine in one go and my website rajeshkumaryadav.com I have moved from Azure Static Web to my VPS :)

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