-
-
Save oelbaga/5019647715e68815c602ff05cff2416e to your computer and use it in GitHub Desktop.
#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 "[email protected]" | |
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 [email protected]:username/repo_name.git | |
or B (by specifying a branch): git clone -b <branch-name-optional> [email protected]: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 "[email protected]" | |
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 "[email protected]" | |
- 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/[email protected] | |
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 |
Thank you very much, very useful and good explained tutorial!
Hi @oelbaga can u help how we can integrate
NextJS app on Digital Ocean space on Ubuntu server and access all css/assets/js from Digital Ocean space cdn.
Very Helpful, thanks
thank you
i am getting 502 bad gateway
Thank you, this is very helpful
i am getting 502 bad gateway
check error with "pm2 logs" commands
Thank you for this file and the Youtube tutorial. It helped me make my own NextJS app on an Ubuntu server. 8)
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
Thank you!
Images i used from public folder are not showing on production. Any Fix @oelbaga
Thank you!
Thank you very much. Unforunately, currently I can't display the sitemap.xml from the public folder.
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
Awesome, very useful and spelled out nicely
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.
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?
This is a life save. Thanks so much!
Thank you!!!
thank you, useful!