Deploy Nextjs Application on AWS EC2(ubuntu) Via PM2 and Reverse proxy with Nginx

Supanut Laddayam
5 min readOct 12, 2023

--

ใช้ pm2 รัน Nextjs Application บน AWS EC2 และทำ Reverse proxy ด้วย Nginx

*จริงๆแล้ว server ที่เราเลือกใช้ไม่ว่าจะเจ้าไหนก็จะไม่ต่างกันมาก เพราะหลักๆ คือเราใช้ Linux ubuntu เป็น OS image หลัก แต่ในบทความนี้จะใช้ AWS EC2 ครับ

Components

  • Nextjs project
  • AWS EC2
  • PM2
  • Domain name
  • Cloudflare
  • Nginx

เตรียมตัว

  1. เตรียม source code ของโปรเจคให้เรียบร้อย และ push ขึ้น Github
  2. Launch AWS EC2 instance
  3. config security group ของ EC2 instance (เพื่อให้สามารถเข้าถึง port ได้)
  • port22 สำหรับ SSH เข้าไปยัง EC2 instance
  • 3000 สำหรับ port ของ Application
  • 80 สำหรับ HTTP
  • 443 สำหรับ HTTPS

ลุยยย…

  1. SSH เข้าไปที่ EC2 instance และ set up
//access to EC2 instance
$ ssh {username}@{IPv4} and password OR use keypair

//set up
$ sudo apt-get update

2. Install nvm

เนื่องจาก application ที่เราจะรัน base on Nodejs แต่จะไม่ลง node ตรงๆ เพราะจะยากต่ออนาคต ถ้าต้องการเปลี่ยน version ของ Nodejs. โดยจะใช้เป็นตัว nvm แทน

$ sudo apt install curl 

$ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash

$ source ~/.bashrc

$ nvm install node


//check nvm and node

$ nvm list
ของผมจะใช้เป็น node version 20.8.0

3. Clone project จาก Github (บทความนี้จะใช้ fortue-app) และลองรัน app

//clone project
$ git clone https://github.com/{username}/{reponame}.git


//change directory to project
$ cd {project_path}

//install package
$ npm install

//run Nextjs applicatopn
$ npm run dev

เข้าดู application ผ่าน browser ด้วย {IPv4 ของ instance}: 3000

run the Nextjs application

โอเคร application ทำงานได้ดี ✨

❗️❓… แต่ ถ้าเราปิด terminal หรือ exit ออกจาก server ก็จะทำให้ application down ลงไปด้วย เพราะเราไม่ได้รัน application ใน background

ctrl + c to stop Nextjs application

💡แก้ด้วย …ซึ่งถ้าเราต้องการทำให้ application ของเราสามารถรันใน backgrond ทำได้ด้วย “PM2”

PM2

what is pm2?

ลง pm2 ผ่าน npm

$ npm install pm2 -g

ขั้นตอนการ run application ด้วย PM2

  1. Build ตัว project
// change directory to target project
$ cd {project_path}

$ npm run build

2. Run application via pm2


$ pm2 start npm --name {project_name} -- start


//case if you want to specific port
$ pm2 start npm --name {project_name} -- start -- -p {port_number}
result of pm2 start

ดูผลลัพธ์ที่ => {IPv4}:3000

More pm2 cli

//start application
$ pm2 start {name or id}

//stop application
$ pm2 stop {name or id}

//check status
$ pm2 ls

//delete application
$ pm2 delete {name or id}

//check log
$ pm2 monit

ซึ่งจะเห็นว่า application ทำงานได้ปกติ โดย pm2 จะเป็นตัวรันให้ใน background✨

❗️❓… แต่จะเห็นว่า url ของ application ของเรายังใช้ ipv4 ของ instance , port ของ application และยังไม่ secure ด้วย ซึ่งยากในการใช้งานจริง ต่างจากเว็บทั่วไปที่ต่างจาก url ที่เราใช้กันบ่อยๆ ซึ่งจะเป็นชื่อที่เราอ่านออก และมี รูปกุญแจล็อค

💡 ชื่อของ url นั่นคือ Domain name และ กุญแจล็อคนั่นคือการบอกว่า secure connection (SSL)

โดย Domain name ที่เช่ามา ผมจะ register ไปที่ cloud flare และจะใช้ Certificate ที่ Cloudflare generate ให้ เพื่อทำ secure connection ให้กับ application

* ในบทความนี้ไม่ได้พูดถึงการเช่า domain name นะครับ 🙏

Cloudflare

โดย application นี้ผมจะให้มี sub domain name ว่า fortune-day.0xnutx.space

Domain name > DNS

เพิ่ม subdomain ให้กับ domain หลัก ในชื่อ fortune app ชนิด A, ค่าเป็น IPv4 ของ EC2 instance และใช้ proxy mode

ปรับโหมด SSL ของ CloudFlare

Domain name > SSL/TSL > Overview

select encryption mode -> Full or Full (strict)

สร้าง Certificate จาก CloudFlare

Domain name > SSL/TSL > Origin server > Create certificate

cloudflare จะให้ secret มา 2 ส่วนคือ certificate และ private key เก็บไว้ในที่ที่ปลอดภัย

Generate Certificate and private key for implement SSL

Nginx

ใช้ Nginx ในการทำ reverse proxy ของตัว port, set domain และทำ SSL ด้วย certitifacte จาก cloudflare

//install
$ sudo apt install nginx-core


//check nginx status
$ sudo systemctl status nginx
Nginx รันปกติ

โดย Nginx จะอยู่ที่ /etc/nginx

ก็ cd /etc/nginx และเข้าไปที่ folder con.f และทำการสร้างไฟล์ในการ config ชื่อ default.conf

เริ่ม Config ตัว domain name ที่จะให้กับ application ของเรา และทุกครั้งที่เข้า domain นั้น จะให้ forward ไปที่ 443 หรือ HTTPS (SSL) และที่ 443 ทำ reverse proxy ไปที่ port ของ fortune application และมีการดึง certificate และ private key จากที่เรา generate ที่ cloudFlare.

cd /etc/nginx/cond.f

sudo vi default.conf
  1. สร้างไฟล์ config ของ nginx => “default.conf”
  • DNS_name จะเป็นที่ subdomain ที่เราตั้งไว้ก่อนหน้า คือ “fortune-day.0xnutx.space”
  • port จะเป็น 3000 ซึ่งจะตรงกับที่ application ที่ pm2 กำลังรันอยู่
//default.conf

server {
listen 80;
server_name {{DNS_name}};

return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name {{DNS_name}};

ssl_certificate /etc/nginx/certs/certificate.crt;
ssl_certificate_key /etc/nginx/certs/private.key;

location / {
proxy_pass http://{{private_ip}}:{port};
proxy_set_header Host $host;
}
}

2. สร้าง directory certs เพื่อเก็บ certificate และ private key (ค่าได้จาก certificate และ private key จาก Cloudflare ที่ได้สร้าง และบันทึกไว้ก่อนหน้านี้)

certificate.crt, private.key

เมื่อ config ตัวไฟล์ default.conf เสร็จแล้วให้ reload ตัว nginx

$ sudo systemctl reload nginx

more nginx cli

//check nginx status
$ sudo systemctl status nginx

//start nginx
$ sudo systemctl start nginx

//stop nginx
$ sudo systemctl stop nginx

//reload nginx / restart
$ sudo systemctl reload nginx

มาดูผลลัพธ์

สำเร็จ fortune app ของเรารันและเข้าถึงได้ตามปกติ เช่นเดียวกับเข้าด้วย ipv4 และ port ของ instance ✨

สรุป

เราได้ deploy Nextjs application ลงบน ubuntu instance server (บทความนี้ใช้ AWS EC2) เริ่มด้วยเรา clone ตัว source code ที่อยู่บน github ลงมาใน server, ติดตั้ง dependencies ที่ต้องการ (node และ npm) จากนั้นทำการ build application และให้ pm2 เป็นคนรัน application ให้เรา. ต่อด้วยการ config reverse proxy เพื่อให้สามารถเข้าถึง application ของเราได้ด้วย Domain

*จริงๆแล้วใน server หนึ่วตัว เราสามารถรัน application และเซ็ท reverse proxy ได้หลายตัวนะ แต่ก็ขึ้นอยู่กับทรัพยากรที่ server เรามีด้วย

*อย่าลืมลบ instance กันด้วย

EC2 > instance > instance state > terminate

Reference

--

--

No responses yet