2023-08-02

#AWS EC2#deploy#ubuntu#cloud server#nginx#pm2#project#next.js#node.js

如何使用Nginx設置二個不同網站

今天要來教大家的是如何在Ubuntu上面設置二個專案,一個是前端框架使用的是Next.js,在React環境下,另一個是後端框架使用的是Node.js。

前端的專案教學會再另外寫一篇文章,今天這篇文章會專注在如何部署Next.js跟Node.js,並二個專案都可以有自己專屬的網址,以及加上SSL保護網址設定。

這些內容都是我自己實際部署和設定的結果,如果有其它的問題,可以問ChatGPT,或google搜尋相關教學設定。

那我們來開始吧!


SSH連線

打開電腦的Terminal,找到.pem檔案(當初建立的EC2時,會下載的一份ssh連線檔),後面的ec2-url是ssh要連線的網址,請查AWS EC2的Server顯示連線網址。

$ ssh -i connect.pem ubuntu@ec2-url

連線成功後,會進入到ubuntu@ip使用者的console,新建立好的Ubuntu系統是沒有任何工具,所以要先安裝一些部署工具。

安裝Nginx

$ sudo apt update
$ sudo apt install nginx

Nginx常用的指令如下

檢查狀態

$ sudo systemctl status nginx

開啟

$ sudo systemctl start nginx

停止

$ sudo systemctl stop nginx

修改配置後,重新啟動

$ sudo systemctl restart nginx

修改配置後,重新裝載

$ sudo systemctl reload nginx

禁用Nginx

$ sudo systemctl disable nginx

啟用Nginx

$ sudo systemctl enable nginx

當Nginx安裝和啟動後,就可以直接打開瀏覽器,並輸入IP址,測試網站是不是成功。
這時候應該會看到Nginx的成功畫面,如果沒有成功,請檢查看看/var/www/html底下是否有nginx的index.html檔案,或是檢查看看nginx是否有正常啟動。
Nginx的port預設為80。 Nginx

設定防火牆(ufw)

查看可以設定的內容

$ sudo ufw app list

輸出結果如下:

Output
Available applications:
  Nginx Full (port: 80, 443)
  Nginx HTTP (port: 80)
  Nginx HTTPS (port: 443)
  OpenSSH (port: 22)

啟用防火牆

$ sudo ufw enable

在這裡加入Nginx Full, OpenSSH,因為Nginx Full包含80跟443的port,OpenSSH是包含22的port,所以這裡只要用Nginx Full就可以允許使用http或是https外連進來。

請記得,一定要啟用OpenSSH或是sudo ufw allow ssh,不然無法從外部使用SSH連進AWS EC2哦!

$ sudo ufw allow 'Nginx Full'
$ sudo ufw allow 'OpenSSH'
$ sudo ufw status

輸出結果如下:

Output
Status: active

To                         Action      From
--                         ------      ----
Nginx Full                 ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
Nginx Full (v6)            ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)

確認上面的Status是否為active的狀態,表示防牆已經正常啟用。

接下來安裝curl,並使用curl來下載安裝nvm,nvm是用來切換並安裝不同版本的node,有一些專案會因為node的版本不同,需要進行系統切換,這裡使用nvm的原因,是因為AWS EC2的Ubuntu沒辦法直接更新到最新的node版本,所以要用nvm來安裝。(因為我畢竟不是AWS EC2的專家)

安裝curl

$ sudo apt update
$ sudo apt upgrade
$ sudo apt-get install curl
$ curl --version

成功安裝curl後,下面是如何使用curl來執行命令。
Usage Once installed you can use it as follows to see the headers:

$ curl -I https://www.google.co.in/
$ curl -I https://www.cyberciti.biz/

Sample outputs:

HTTP/2 200
date: Mon, 29 Jul 2019 13:13:08 GMT
content-type: text/html; charset=UTF-8
set-cookie: __cfduid=d5292058141c28e3cda2d9501688cff531564405988; expires=Tue, 28-Jul-20 13:13:08 GMT; path=/; domain=.cyberciti.biz; HttpOnly; Secure
vary: Accept-Encoding
strict-transport-security: max-age=15552000
x-whome: l-cbz02
cf-cache-status: HIT
age: 102433
x-content-type-options: nosniff
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 4fdf59334ab9dcb5-MAA

Or download a file from a server using curl itself:

$ curl -o output.file http://server1.cyberciti.biz/bar.foo.txt

安裝nvm

$ sudo apt update
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash  

說明指令
查看版本清單nvm ls
查看目前版本nvm --version
安裝nodenvm install node
安裝最新版本nvm install -lts
安裝穩定版本nvm install stable
指定安裝node版本nvm install 8.16.2
變更node版本nvm use v14.10.0
移除node版本nvm uninstall 11.5

安裝node

$ nvm install node

安裝gh

這邊我是使用gh來下載遠端的git repository,如果習慣用git的人,也可以直接跳過這個步驟,請直接安裝git。

sudo apt update
sudo apt upgrade
sudo apt install gh

使用方法

安裝完畢後,要進行帳號驗證登入,才能使用gh下載遠端的repository

gh auth login

git login

從網頁輸入驗證碼

打開瀏覽器,並將下面的網址貼上

https://github.com/login/device

在auth login的時候,應該會看到一串數字,First copy your one-time code: D61D-2887,將數字拷貝,然後貼到欄位上。 device activation 按下continue按鈕,會跳出詢問是否要Authorize github,按下之後,會轉頁並詢問帳號密碼。 authorize github 輸入帳號密碼後,看到此頁就表示驗證完整,可以開始使用gh了! connected

恭喜!可以使用gh命令了

gh --version
gh repo clone {github網址} {新的資夾名稱}

下載Github repository

這邊的範例是下載我自己的後端node.js專案

$ gh repo clone bxbdev/next-chat-server-side server

安裝 git

$ sudo apt-get install git-all

安裝yarn

$ npm i yarn -g

安裝pm2

這邊我是使用pm2的方式,來管理執行不同的專案,下面是啟動程式或是專案的方法 啟動js

$ pm2 start app.js

啟動python

$ pm2 start python-app.py

啟動使用不同的port

$ pm2 start binary-file -- --port 1520

說明指令
全域安裝pm2npm i -g pm2
yarn global add pm2
顯示管理程序狀態pm2 [list|ls|status]
清空 logpm2 flush
輸出logspm2 logs
啟動專案pm2 start name
停止專案pm2 stop name
停止所有專案pm2 stop all
刪除專案pm2 delete name
刪除所有專案pm2 kill
監聽系統和專案執行狀態pm2 monit
監聽資料變更時,自動重啟pm2 start --watch folder

如果terminal出現下面的訊息時,可改用npx pm2就可以正常使用指令

pm2: command not found

或是退出AWS EC2的連線,再重新使用ssh連線,就可以正常使用pm2命令了。 一般安裝完畢後,需要關閉Terminal,再重新開啟,才可以使用。

建立新專案到Nginx底下

$ sudo mkdir -p /var/www/html/app_name/

從git下載repository後,會直接在最外層的目錄,所以要用拷貝的方法,將檔案拷貝到/var/www/html底下,因為沒有修改html底下的目錄權限,這邊可自行查詢如何修改Ubuntu的目錄權限。

搬移資料夾並覆蓋內容的指令

$ sudo cp -rT server /var/www/html/server
$ cd /var/www/html

進到html的目錄底下後,執行pm2,因為我的server底下只有一個index.js,所以只要在外層的目錄直接執行,就會自動啟動了。

$ pm2 start server
$ pm2 ls

讓PM2在系統重啟時,自動啟動

$ pm2 startup

把目前的執行狀態存起來,下次重啟後,會自動啟動一樣的專案,如果內容還有可能會變更的話,就需要將logs清除掉,不然修改的專案內容會因為pm2重新啟動,不會看到新的修改內容。

$ pm2 save

如果不希望啟動的名稱和資料夾名稱一樣的話,可以使用下面指令流程

$ cd /var/www/html/server
$ pm2 start index.js --name server.seekdecor.online

網站設定

新增設定檔

$ sudo touch /etc/nginx/sites-available/site_name

編輯設定檔

$ sudo nano /etc/nginx/sites-available/site_name

Nginx網站設定檔的命名方式,可以是名稱,也可以是網址方式來命名

/etc/nginx/sites-available/app
/etc/nginx/sites-available/www.domain.com
/etc/nginx/sites-available/sub1.domain.com
/etc/nginx/sites-available/sub2.domain.com

以下是我的後端server的範例設定,proxy_pass是反向代理位置,啟動後的project port。 http://localhost:5000這邊的port,要看專案使用的port是指定哪一個,比如next.js預設是3000,那這裡的port就要換成http://localhost:3000

server {
	listen 80;
	listen [::]:80;

	root /var/www/html/server;
	index index.html index.htm index.nginx-debian.html;

	server_name server.seekdecor.online;

	location / {
		proxy_pass http://localhost:5000;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
	}
}

將文件同步連結到/etc/nginx/sites-enabled/,可方便日後修改同步

$ sudo ln -s /etc/nginx/sites-available/server /etc/nginx/sites-enabled/

這個動作完成後,需要指定server.seekdecor.online的ip位址,需要檢查一次nginx的狀態後,確定新增的內容沒有任何問題,然後再重新啟動nginx

$ sudo nginx -t

出現下面的訊息,表示nginx正常沒有問題,如果有問題,就表示文件設置有問題。

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

沒有問題,就可以重新啟動nginx了,這裡也可以使用reload

$ sudo systemctl restart nginx

瀏覽器打開後,輸入網址連線http://server.seekdecor.online,看到頁面輸出的內容就表示所有設定都成功了,第一個專案就設定完成了,重複建立新的nginx網站設定檔。

設定SSL

Let's Encrypt Client

$ sudo apt install -y certbot

# stop nginx service, this is a must
$ sudo systemctl stop nginx

# generate an ssl certificate
$ sudo certbot certonly -d sub1.domain.com -d sub2.domain.com

可以一次新增二個不同的subdomain網站,這裡的sub1.domain.com跟sub2.domain.com請直接換成其它網址。

文件設置SSL

再次編輯文件

$ sudo nano /etc/nginx/sites-available/server

新增SSL設定

server {
    listen 443 ssl;

    # ssl configuration;
    ssl_certificate /etc/letsencrypt/live/server.seekdecor.online/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/server.seekdecor.online/privkey.pem;
}

SSL完整設定

注意這裡的ssl configuration,如果subdomain使用的是同一個檔案,另一個新增的檔案,也要設置一模一樣的檔案。 第一個server的內容,是一般http的連線,如果不希望使用者用一般的網址進到網站的話,可以加上return 301 https://example.domain.com$request_uri;,會自動轉址到https。 第二個server的內容,root的位置是指定專案的目錄,比如目錄的位置是在/app/my_blog的話,那就要將root的修改為root /app/my_blog

server {
 listen 80;
 listen [::]:80;
 server_name server.seekdecor.online;

 return 301 https://server.seekdecor.online$request_uri;
}

server {
 listen 443 ssl;
 server_name server.seekdecor.online;

 root /var/www/html/server;
 index index.html index.htm index.nginx-debian.html;

 location / {
         proxy_pass http://localhost:5000;

         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "upgrade";
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Forwarded-Proto $scheme;
 }

 # ssl configuration;
 ssl_certificate /etc/letsencrypt/live/server.seekdecor.online/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/server.seekdecor.online/privkey.pem;
}

重新測試並重新啟動nginx服務器

$ sudo nginx -t
$ sudo systemctl restart nginx

打開瀏覽器測試網址,如果Chrome的網址旁邊有出現鎖頭,就表示設定成功。


結語心得

這是經過不斷嘗試好幾次AWS EC2整個掛掉後,不得已終止Instance,然後又重新建立新的Instance,最後實測的結果,最完整的紀錄。

還得感謝水球軟體學院的大佬們幫忙提點,才能夠這麼順利的架好二個不同網址的網站,自己一個人光設定Nginx就失敗好多次,最後終於理解,並且知道怎麼設定網站。