Nginx 教學 Ubuntu 網站架設基礎設定快速入門

me
林彥成
2019-07-13 | 6 min.

Nginx 網站伺服器可以做反向代理(reverse proxy)、負載平衡器(load balancer) 和 HTTP 快取,在 Non Blocking IO 的機制上,可以提供很好的響應速度解決 C10K 的問題。

如何在 Ubuntu 上架設 Nginx 網站伺服器? 如果是 SPA (single-page application),會需要放建置過的網頁檔到伺服器,並透過正確的路由能夠回應給使用者。接下來會按照下面順序介紹前端工程師常用的 Nginx Config。

  1. Linux、Windows 安裝與設定
  2. Nginx 服務管理: Systemctl
  3. Nginx Config 基礎設定: 反向代理 (proxy pass)、負載平衡器 (load balancer)、HTTP 快取
  4. https 設定: 推薦使用 certbot,可以方便的使用免費的 Let’s Encrypt
  5. 效能優化 (Linux、Nginx 設定)

Linux 主機設定

Linux 是一個檔案系統,所以檔案要有系統的被放置

  1. 常用的會有在 home 目錄底下的{使用者名稱}目錄,因為 linux 的權限規劃的比較嚴謹,每個檔案都有相關的存取權限,建議發佈位置放在這個目錄下。
  2. etc (配置檔)
  3. var(log)
  • 連接至主機,一般建議用 putty 免安裝版用 ssh 去連就可以了,如果虛擬機主人沒有動 port 預設都是可以連的,然後搭配不同家廠商的服務,大致都需要提供一些 key 或是配置檔。
  • 升級系統相關套件與服務
1
2
3
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
  • 清理安裝檔
1
2
3
sudo apt-get autoremove
sudo apt-get clean
sudo apt-get autoclean

Nginx Windows 指令

Windows 的指令比較特別,之前曾遇過多的 processes 關不掉的情況,所以建議在修改配置後都是使用 nginx -s reload

1
2
3
4
nginx -s stop    fast shutdown
nginx -s quit graceful shutdown
nginx -s reload starting new worker processes with a new configuration, graceful shutdown of old worker processes
nginx -s reopen re-opening log files

Nginx Systemctl 服務管理

當我們安裝了像是 Nginx、Jenkins、DB 後,會需要管理他們,在 Linux 中,我們一般會使用 sudo systemctl 加上底下幾種指令:

  1. status (狀態)
  2. stop (停止)
  3. start (開始)
  4. enable (開機啟用)
  5. restart (重開)

底下的範例就是看 nginx 目前的狀態,接著列出有在開機預設開啟中的程式或服務,最後看目前有在執行的服務。

1
2
3
systemctl status nginx
systemctl list-unit-files | grep enabled
systemctl | grep running

這些服務的 log 一般都會存在 /var/log 資料夾中,如果我們想看 nginx 的 access log,就可以使用 tail -f /var/log/nginx/access.log,這裡有一點要注意的是如果沒有管理,log 可能會佔蠻多硬碟空間,這時候就可以使用 sudo du -sh /var/log/ 來看到底用了多少,改善方法有以下兩種:

  1. 從設定檔中進行設定/etc/logrotate.d
  2. 執行指令進行清除 sudo find /var/log/ -type f -regex '.*\.[0-9]+\.gz$' -delete

Nginx Log

關掉 Access Logging 只要紀錄就會對 CPU 硬碟產生消耗,或是增加 buffer size] 不要頻繁的製造 CPU 處理硬碟 IO,設定 flush=time 的時間定期處理,當然直接停用最好

  • access log 位置會在 /var/log/nginx/access.log,這邊推薦可以使用 GoAccess 將資訊圖像化,如果不想使用手工,可以搭配 Linux 的 crontab 排程進行自動更新。
  • error log 位置會在 /var/log/nginx/error.log

Nginx config 基礎設定

server_name 就是搭配我們的網域,接下來只要在 DNS 指向主機就大功告成。靜態的網站就較為單純,指向正確就可以了,但若是像 php 屬於動態網頁就還需要搭配 fastcgi 做相關反向代理的設定,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80 default_server;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
try_files $uri /index.html;
}

server {
listen 80 default_server;
server_name example2.com www.example2.com;
root /var/www/example2.com;
index index.html;
try_files $uri /index.html;
}

Nginx proxy pass (反向代理)

反向代理: 網域往往只能連到一台入口主機,但當我們後端有很多網站及服務分配到多台主機時,這時候就需要透過路徑上的代理來轉發還有配置附載平衡,Nginx 就提供了這樣的功能,當然 AWS 上也有提供相關服務。

除此之外還可以做負載平衡,反向代理該設的參數要設對,proxy_http_version 1.1 請注意,有人有踩過雷了,另外附載平衡也很簡單,其中有幾種模式可以提供選擇,也可以進一步設定 health_check,讓 Nginx 去定時確認後端伺服器是否安好。

  • least_conn 選擇最少連線數
  • least_time 回應時間
  • weight 倍數
1
2
3
4
5
6
7
8
9
10
11
12
13
upstream myapp1 {
server srv1.example.com weight=3;
server srv2.example.com;
server srv3.example.com;
least_conn;
}

server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}

https 設定 Certbot 自動更新 Let’s Encrypt 憑證

另外主要的用途可用來掛 https,在 https 安裝上推薦使用憑證機器人

1
2
3
sudo certbot --nginx -d test.domain.com
sudo certbot delete --cert-name test.domain.com
sudo certbot renew --dry-run

跑過以後可以在檔案裡面可以看到 # managed by Certbot 的註解,代表這份配置檔的部分設置就不需要我們維護了,Digital Ocean 提供了很詳盡的教學,非常推薦。

Linux 排程設定

先寫好想要執行的 test.sh 檔,接著就可以透過設定排程來固定更新 SSL 憑證,記得將檔案改好權限 chmod +x test.sh,下面示範會產生資料夾:

1
2
3
4
#!/bin/bash
DIR=`date +%D`
DEST=~/test/$DIR
mkdir $DEST

自訂的排程時間則可以使用 crontab,使用 crontab -e進行編輯,透過分鐘、小時、日、月、星期幾來進行週期設定。

  • 譬如每個星期二的 4:00am 就可以寫成 0 4 * * 2 ~/test.sh
  • 也可以使用縮寫 @daily ~/test.sh

相關縮寫如下:

  • @hourly 0 * * * *
  • @daily 0 0 * * *
  • @weekly 0 0 * * 0
  • @monthly 0 0 1 * *
  • @yearly 0 0 1 1 *

防呆可以先用下面這個網站試寫:
https://crontab.guru/

程式發佈方法

  • 放置檔案到伺服器
    1. FTP,架設的方式很多部落客都有教學
    2. jenkins,從版控抓 master branch 下來自動 build 及執行 shell 記得 BUILD_ID=DONTKILLME
  • 接受請求的程式
    1. 靜態的檔案,這個部分推薦使用 nginx 就好了,方便又快速
    2. 如果是 node.js 的後端,需要使用 PM2 這類的工具進行管理,也推薦使用 cluster mode 無痛升級效能,node.js 在 Linux 上運行的好物

Nginx 效能優化設定

主要的配置檔位置在 Linux 環境中會在 /etc/nginx 底下,除了 epoll 可以從機制上影響效能外,也可以從系統服務的性質從核心的設定以及相關設定優化效能。

  • worker_processes 就是配合主機核心數,若是 4 核心就可以設置 worker_processes 4
  • worker_rlimit_nofile 是可以開啟的檔案數量,像我以前公司伺服器就有需要提供圖磚的快取,設定大量的開啟檔案數量可以說是必須
  • 快取,在 Nginx 也有提供 proxy_cache_path 的快取設定
  • Gzip 壓縮,這個在很多地方都可以啟用,不一定需要在 Nginx 開啟
  • client_max_body_size 限制檔案上傳大小

Connections 相關

  • keepalive_requests: 預設值 100 可以邊壓測邊調整
  • keepalive_timeout: 多久要切掉
  • 反向代理的 keepalive,記得設定 proxy_http_version 1.1; proxy_set_header Connection “”;

加上相關限制

  • limit_conn 譬如某些路由很佔頻寬就可以直接限制,不要影響其他快速的服務
  • limit_rate 限速
  • max_conns 如果 upstream 是比較弱的機台就建議設定一下

如果有需要用到 websocket,設定會不太一樣,參考官網文件需要配置如下。

1
2
3
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

Nginx Epoll

Nginx 在 Linux 的 IO 機制上有支援 epoll,所以在靜態網頁的效能上遠超過使用 select 機制的 apache,而且只需要透過簡單配置即可使用,還有其他支援的機制可以參考官方文件

1
2
3
4
5
events {
use epoll;
worker_connections 1024;
multi_accept on;
}

Linux 效能優化系統核心設定

主要是編輯這個檔案 /etc/sysctl.conf

  • sys.fs.file-max 最大開檔上限 sysctl -w fs.file-max=50000 (可以暫時測試重開機後會消失)
  • net.core.somaxconn: 能被 nginx queue 接受的最大連線數,可以設定成 512,超過還需要設定 listen 的 backlog 參數,因為除了 FreeBSD, DragonFly BSD, macOS 其他預設值是 511
  • net.core.netdev_max_backlog: 網路卡的 backlog,加大會增加效能,但不了解網路卡的極限就容易出現錯誤 Orz
  • nofile 也跟開檔數有關會在 /etc/security/limits.conf

編輯器

select-editor 建議使用 nano,相對簡單,使用時就是使用指令加檔名 nano test.conf,若是要修改權限外的檔案則要 sudo nano test.conf ,常見的如下,vi 和 vim 有區分指令模式跟輸入模式,操作概念較為複雜:

  • vi
  • vim
  • nano

網路連線設定

  • 防火牆,會碰到這個一般是都弄好了,但怎麼都看不到網頁,若停用防火牆後以使用,代表防火牆需要設定
    sudo ufw disable 停用
    sudo ufw allow from 192.168.0.0/16 允許通過
  • 端口、埠 (Port) 的設定,可能程式沒寫好錯誤處理,又剛好選到的 port 跟其他服務一樣,也請看一下目前這個 port 是不是有被使用:
    netstat -tulpn | grep LISTEN

常見問題排除

  • 記憶體不足,如果記憶體不足當機的話,可以幫 EC2 主機加上 swap,因為預設是沒有的。
    tophtop 看一下是不是一直在交換
    watch -n 1 free -m只看記憶體
  • 檔案權限然後上傳有問題,會發現竟然寫不進去,全開的話就 chmod -R 777 ./*,不需要執行的話就 755,執行 (+X),這裡可以看到三個數字,就是搭配在 linux 上使用指令 ls -l 看到三組的 rwx,其中 r=4 (讀),w=2 (寫),x=1 (執行)
UserGroupOther
764
rwxrwr
777
rwxrwxrwx

喜歡這篇文章,請幫忙拍拍手喔 🤣

share