常用的 Nginx Config 與相關指令教學 四大步驟入門網站架設

me
林彥成
2019-07-13 | 7 min.
文章目錄
  1. 1. 四大步驟入門 Nginx 架站基礎設定
    1. 1.1. Linux、Windows 主機安裝與指令
    2. 1.2. 伺服器管理與程式發佈
      1. 1.2.1. 伺服器管理範例
      2. 1.2.2. Nginx Log
      3. 1.2.3. 程式發佈
    3. 1.3. Nginx config 基礎設定
      1. 1.3.1. Nginx proxy pass (反向代理)
        1. 1.3.1.1. 導流到根目錄
        2. 1.3.1.2. 導流到特定目錄
      2. 1.3.2. https 設定
    4. 1.4. Nginx 效能優化設定
      1. 1.4.1. Nginx Epoll
      2. 1.4.2. Linux 系統核心設定
  2. 2. 伺服器架設常見問題排除
    1. 2.1. 記憶體不足
    2. 2.2. Permission denied while connecting to upstream
    3. 2.3. 檔案權限設定
    4. 2.4. 網路連線設定
  3. 3. Nginx 監控報表
    1. 3.1. Elastic Metricbeat
    2. 3.2. Elastic Filebeat
    3. 3.3. GoAccess

四大步驟入門 Nginx 架站基礎設定

Nginx 搭配 Linux 系統 (Ubuntu) 架設網站可以說是常見的解決方案,可實現反向代理(reverse proxy)、負載平衡(load balancer) 和快取,透過 Non Blocking IO 機制解決 C10K 的問題,接下來會用四個主要步驟介紹前端工程師常用的 Nginx Config 與相關指令。

  1. Linux、Windows 主機安裝與指令
  2. 伺服器管理與程式發佈
  3. Nginx Config 基礎設定: 反向代理 (proxy pass)、https 設定
  4. Nginx 效能優化設定 (HTTP 快取、Linux 系統核心設定)

如何在 Ubuntu 上架設 Nginx 網站伺服器? 如果是 SPA (single-page application),會需要放建置過的網頁檔到伺服器,並透過正確的路由能夠回應給使用者。

Linux、Windows 主機安裝與指令

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

在 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

伺服器管理與程式發佈

在 Linux 主機上運用 Systemctl 做 Nginx 服務管理,當我們安裝了像是 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

程式發佈

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

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;
}
}
導流到根目錄
1
2
3
4
5
location /app/ {
proxy_pass http://192.168.1.100;
}

test.com/app/xxxxx => http://192.168.1.100/xxxxx
導流到特定目錄
1
2
3
4
5
location /app/ {
proxy_pass http://192.168.1.100/maped_dir/;
}

test.com/app/xxxxx => http://192.168.1.100/maped_dir/xxxxx

https 設定

https 可以使用免費的 Let’s Encrypt,在 https 安裝上推薦使用憑證機器人 自動更新 Let’s Encrypt 憑證

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/

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

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

  • vi
  • vim
  • nano

伺服器架設常見問題排除

在架設完不管是地端或是雲端的伺服器後,通常會遇到三個問題

  1. 記憶體不足
  2. 檔案權限
  3. 網路連線設定問題

記憶體不足

記憶體不足,如果記憶體不足當機的話,可以幫 EC2 主機加上 swap,因為預設是沒有的。
tophtop 看一下是不是一直在交換
watch -n 1 free -m只看記憶體

Permission denied while connecting to upstream

如果 Linux 的環境中設置了 proxy_pass 卻沒有作用的時候,這時候可以透過 tail -f /var/log/nginx/*.log 指令來查看相關錯誤,如果發現 Permission denied while connecting to upstream,可能就是 SELinux 權限的問題,這時候如果只是需要先測試的話,可以

  1. 設定連接權限: setsebool httpd_can_network_connect on -P
  2. 查看是否設定成功:getsebool -a | grep httpd

檔案權限設定

檔案權限然後上傳有問題,會發現竟然寫不進去,全開的話就 chmod -R 777 ./*,不需要執行的話就 755,執行 (+X),這裡可以看到三個數字,就是搭配在 linux 上使用指令 ls -l 看到三組的 rwx,其中 r=4 (讀),w=2 (寫),x=1 (執行)

UserGroupOther
764
rwxrwr
777
rwxrwxrwx

網路連線設定

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

Nginx 監控報表

目前我有使用過最簡單的方式有兩個:

  1. 透過 Elastic 提供的 Filebeat 和 Metricbeat 可以從狀態、日誌即時的去監控 Nginx
  2. 使用開源的 GoAccess 加上系統排程定時更新資料

Elastic Metricbeat

之前剛好使用過 Elastic 相關 Solution,發現透過簡單的配置就能夠知道目前伺服器的狀況,詳細的教學歡迎參考這篇文章: Elastic Metricbeat 搭配 Kibana 來監控 Nginx 伺服器狀態,就像下圖就是系統預設提供的樣板,可以簡單即時去監控 Nginx 的流量、記憶體、處理器當下使用量。

Metricbeat + Kibana
SystemMetric

Elastic Filebeat

那如果需要分析 Log 並產生報表呢? 當然也可以透過 Elastic 相關 Solution,透過 Filebeat 傳送 Nginx Access Log 到 Elasticsearch 中,最後透過 Kibana 即時監看相關分析。

Filebeat + Kibana
FilebeatDashBoard

GoAccess

如果不想要透過 Elastic,也有一套開源的工具 GoAccess 能夠分析 Log 並且產生報表的靜態網頁,不過由於是靜態網頁,所以使用上就需要透過設定作業系統排程來定時跑腳本更新頁面。

GoAccess Dashboard
GoAccessDashboard


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

share