Nginx 作為現代 Web 架構的基石,以其卓越的效能表現、靈活的組態能力與豐富的功能特性,成為全球最受歡迎的 Web 伺服器與反向代理解決方案之一。相較於傳統的 Apache HTTP Server,Nginx 採用事件驅動的非同步架構,能夠以更少的系統資源處理更多的並發連線,特別適合高流量的 Web 應用場景。本文將深入探討 Nginx 的核心組態原理、效能調校技巧、安全性強化措施,以及與現代化開發工具的整合應用,協助讀者全面掌握 Nginx 在生產環境中的部署與管理。
Nginx 基礎架構與安裝部署
Nginx 的架構設計體現了其對高效能的追求。採用主從程序模型,由一個主程序管理多個工作程序,每個工作程序能夠處理數千個並發連線。這種設計充分利用了現代多核心處理器的運算能力,同時透過非阻塞的事件驅動機制,避免了傳統多執行緒模型的上下文切換開銷。
在 Debian 與 Ubuntu 系統上部署 Nginx 是一個相對直觀的過程。系統的套件管理工具提供了預先編譯好的 Nginx 套件,能夠快速完成安裝並自動處理依賴關係。然而,在生產環境中,我們需要對預設組態進行調整,以滿足特定的效能與安全需求。
# 更新套件索引確保取得最新版本資訊
sudo apt update
# 安裝 Nginx 主套件
sudo apt install -y nginx
# 啟動 Nginx 服務
sudo systemctl start nginx
# 設定開機自動啟動
sudo systemctl enable nginx
# 檢查 Nginx 服務狀態
sudo systemctl status nginx
# 驗證 Nginx 版本與編譯參數
nginx -v
nginx -V
# 測試組態檔語法正確性
sudo nginx -t
# 重新載入組態而不中斷服務
sudo nginx -s reload
Nginx 的主要組態檔位於 /etc/nginx/nginx.conf,這個檔案定義了全域性的伺服器行為。組態採用模組化的設計,透過 include 指令載入其他組態檔案,使得管理大型部署變得更加便利。典型的組態檔結構包含全域區塊、events 區塊與 http 區塊,每個區塊負責不同層面的設定。
# Nginx 主組態檔 /etc/nginx/nginx.conf
# 定義 Nginx 工作程序的執行使用者
# www-data 是 Debian/Ubuntu 系統的標準 Web 服務使用者
user www-data;
# 工作程序數量設定
# auto 會自動偵測 CPU 核心數並設定對應數量的工作程序
# 最佳化建議:通常設定為 CPU 核心數或稍少
worker_processes auto;
# 主程序 PID 檔案位置
pid /run/nginx.pid;
# 錯誤日誌檔案位置與記錄等級
# 等級選項: debug, info, notice, warn, error, crit
error_log /var/log/nginx/error.log warn;
# 載入動態模組
include /etc/nginx/modules-enabled/*.conf;
# Events 區塊定義連線處理機制
events {
# 每個工作程序可處理的最大並發連線數
# 理論最大並發數 = worker_processes * worker_connections
worker_connections 2048;
# 使用高效的事件模型(Linux 使用 epoll)
use epoll;
# 工作程序一次接受所有新連線
multi_accept on;
}
# HTTP 區塊定義 Web 伺服器行為
http {
##
# 基本設定
##
# 載入 MIME 類型定義
include /etc/nginx/mime.types;
# 預設 MIME 類型
default_type application/octet-stream;
# 存取日誌格式定義
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time';
# 存取日誌檔案位置
access_log /var/log/nginx/access.log main;
##
# 效能最佳化設定
##
# 啟用 sendfile 系統呼叫,提升靜態檔案傳輸效能
sendfile on;
# 與 sendfile 配合使用,減少網路封包數量
tcp_nopush on;
# 停用 Nagle 演算法,降低延遲
tcp_nodelay on;
# 持久連線超時時間
keepalive_timeout 65;
# 持久連線上的最大請求數
keepalive_requests 100;
# 請求標頭讀取超時
client_header_timeout 30;
# 請求主體讀取超時
client_body_timeout 30;
# 回應傳送超時
send_timeout 30;
# 客戶端請求主體最大尺寸
client_max_body_size 20m;
# 客戶端請求主體緩衝區大小
client_body_buffer_size 128k;
# 大型請求標頭緩衝區設定
large_client_header_buffers 4 16k;
##
# Gzip 壓縮設定
##
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss
application/rss+xml font/truetype font/opentype
application/vnd.ms-fontobject image/svg+xml;
gzip_disable "msie6";
##
# 快取設定
##
# 開啟檔案快取
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
##
# 安全性設定
##
# 隱藏 Nginx 版本號
server_tokens off;
# 防止點擊劫持攻擊
add_header X-Frame-Options "SAMEORIGIN" always;
# 啟用 XSS 保護
add_header X-XSS-Protection "1; mode=block" always;
# 防止 MIME 類型嗅探
add_header X-Content-Type-Options "nosniff" always;
# 內容安全政策
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
##
# 虛擬主機組態
##
# 載入站點組態檔案
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
這個組態檔展示了 Nginx 的核心設定結構。工作程序數量的自動偵測確保了系統資源的充分利用,而事件模型的選擇則直接影響並發處理能力。HTTP 區塊中的各項參數需要根據實際的硬體規格與流量模式進行調整,沒有一成不變的最佳值。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 140
package "Nginx 架構" {
rectangle "主程序 (Master Process)" as master {
component "組態管理" as config
component "工作程序管理" as worker_mgmt
component "訊號處理" as signal
}
package "工作程序池 (Worker Processes)" {
rectangle "工作程序 1" as w1 {
component "事件迴圈" as ev1
component "請求處理" as req1
}
rectangle "工作程序 2" as w2 {
component "事件迴圈" as ev2
component "請求處理" as req2
}
rectangle "工作程序 N" as wn {
component "事件迴圈" as evn
component "請求處理" as reqn
}
}
cloud "客戶端請求" as clients
database "後端服務" as backend
}
clients --> w1
clients --> w2
clients --> wn
master --> w1
master --> w2
master --> wn
w1 --> backend
w2 --> backend
wn --> backend
@enduml效能調校與資源最佳化
Nginx 的效能調校是一個系統性的工程,需要考慮網路層、應用層與作業系統層的多個面向。合理的參數設定能夠顯著提升系統的吞吐量與回應速度,同時降低資源消耗。效能調校的核心在於理解各個參數的作用機制,並根據實際的工作負載進行適配。
連線管理是效能調校的重要環節。持久連線機制允許客戶端在同一個 TCP 連線上發送多個 HTTP 請求,避免了頻繁的連線建立與關閉開銷。然而,過長的持久連線超時可能導致資源佔用,過短則無法充分發揮持久連線的優勢。在實務中,需要根據客戶端的請求模式找到平衡點。
# 高效能 Web 伺服器組態範例
# 適用於高流量生產環境
http {
##
# 連線處理最佳化
##
# 持久連線超時設定
# 在高流量環境下,適度縮短超時可以釋放資源
keepalive_timeout 30;
# 單一持久連線上的最大請求數
# 設定較高的值可以充分利用持久連線
keepalive_requests 200;
# 停用 IE6 的持久連線(已過時的瀏覽器)
keepalive_disable msie6;
# 緩慢關閉連線以確保資料完整傳輸
lingering_close on;
lingering_time 30s;
lingering_timeout 5s;
##
# 請求處理最佳化
##
# 客戶端請求標頭讀取超時
client_header_timeout 30;
# 客戶端請求主體讀取超時
client_body_timeout 30;
# 忽略無效的請求標頭
ignore_invalid_headers on;
# 請求主體最大尺寸(根據應用需求調整)
client_max_body_size 50m;
# 請求主體緩衝區大小
client_body_buffer_size 256k;
# 大型請求標頭緩衝區(4 個 8KB 的緩衝區)
large_client_header_buffers 4 8k;
# 限制 Range 請求的範圍數量
max_ranges 30;
##
# 回應傳送最佳化
##
# 回應傳送超時
send_timeout 30;
# 回應緩衝區設定
# 關閉緩衝以減少記憶體使用(適合大檔案)
proxy_buffering off;
# 或者設定適當的緩衝區大小
# proxy_buffer_size 4k;
# proxy_buffers 8 4k;
##
# FastCGI 最佳化(用於 PHP 等動態內容)
##
# FastCGI 連線超時
fastcgi_connect_timeout 60;
# FastCGI 傳送超時
fastcgi_send_timeout 180;
# FastCGI 讀取超時
fastcgi_read_timeout 180;
# FastCGI 緩衝區設定
fastcgi_buffer_size 64k;
fastcgi_buffers 8 64k;
fastcgi_busy_buffers_size 128k;
# FastCGI 暫存檔案設定
fastcgi_temp_file_write_size 256k;
# FastCGI 快取設定(大幅提升動態內容效能)
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=fastcgi_cache:100m
inactive=60m
max_size=1g;
##
# Proxy 快取最佳化
##
# Proxy 快取路徑設定
proxy_cache_path /var/cache/nginx/proxy
levels=1:2
keys_zone=proxy_cache:100m
inactive=60m
max_size=2g;
# Proxy 快取鍵定義
proxy_cache_key "$scheme$request_method$host$request_uri";
# Proxy 快取有效期設定
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
##
# 限流與安全防護
##
# 定義請求頻率限制區域
# 限制每個 IP 每秒最多 10 個請求
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# 定義連線數限制區域
# 限制每個 IP 最多 50 個並發連線
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
##
# 上游伺服器連線池(用於反向代理)
##
upstream backend_servers {
# 使用最少連線演算法進行負載平衡
least_conn;
# 啟用持久連線到上游伺服器
keepalive 32;
keepalive_requests 100;
keepalive_timeout 60s;
# 定義後端伺服器
server backend1.example.com:8080 weight=3 max_fails=3 fail_timeout=30s;
server backend2.example.com:8080 weight=2 max_fails=3 fail_timeout=30s;
server backend3.example.com:8080 weight=1 max_fails=3 fail_timeout=30s backup;
}
##
# 虛擬主機範例
##
server {
listen 80;
server_name example.com www.example.com;
# 強制重導向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# 網站根目錄
root /var/www/html;
index index.html index.htm;
# 套用請求頻率限制
limit_req zone=req_limit burst=20 nodelay;
# 套用連線數限制
limit_conn conn_limit 50;
# 靜態檔案處理
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# API 反向代理
location /api/ {
proxy_pass http://backend_servers;
proxy_http_version 1.1;
# 啟用到上游的持久連線
proxy_set_header Connection "";
# 轉發客戶端資訊
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;
# 啟用 Proxy 快取
proxy_cache proxy_cache;
proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# 新增快取狀態標頭
add_header X-Cache-Status $upstream_cache_status;
}
}
}
這個進階組態展示了多層次的效能最佳化策略。FastCGI 快取能夠顯著降低動態內容的生成開銷,對於 PHP 應用程式尤其有效。Proxy 快取則適用於反向代理場景,減少對後端服務的請求壓力。限流機制保護系統免受濫用,是生產環境必備的防護措施。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 130
start
:客戶端發送 HTTP 請求;
:Nginx 接收請求;
if (請求頻率限制檢查) then (通過)
if (連線數限制檢查) then (通過)
if (請求靜態資源?) then (是)
:檢查檔案快取;
if (快取有效?) then (是)
:直接傳送快取內容;
else (否)
:讀取檔案系統;
:建立快取;
:傳送內容;
endif
else (否)
if (需要 FastCGI 處理?) then (是)
:檢查 FastCGI 快取;
if (快取有效?) then (是)
:傳送快取內容;
else (否)
:轉發到 FastCGI;
:接收處理結果;
:建立快取;
:傳送內容;
endif
else (反向代理)
:檢查 Proxy 快取;
if (快取有效?) then (是)
:傳送快取內容;
else (否)
:選擇後端伺服器;
:轉發請求;
:接收回應;
:建立快取;
:傳送內容;
endif
endif
endif
else (超過限制)
:返回 503 錯誤;
endif
else (超過限制)
:返回 429 錯誤;
endif
:關閉連線或維持持久連線;
stop
@endumlDocker 容器化部署整合
容器化技術徹底改變了應用程式的部署方式。將 Nginx 封裝為 Docker 容器,不僅簡化了部署流程,更提供了一致的執行環境,消除了「在我的電腦上可以運作」的經典問題。Docker 的輕量級特性使得 Nginx 容器能夠快速啟動,配合編排工具可以實現彈性的水平擴展。
Docker Compose 提供了宣告式的多容器應用定義方式。透過 YAML 檔案描述服務間的依賴關係、網路配置與資料卷掛載,使得複雜的部署變得簡單可重現。對於開發環境與測試環境,Docker Compose 是極佳的選擇,而在生產環境則可以無縫遷移到 Kubernetes 等容器編排平台。
# docker-compose.yml
# Nginx 容器化部署範例
version: '3.8'
services:
nginx:
# 使用官方 Nginx 映像檔
image: nginx:1.25-alpine
# 容器名稱
container_name: nginx-server
# 重啟策略
restart: unless-stopped
# 連接埠對映
ports:
- "80:80"
- "443:443"
# 資料卷掛載
volumes:
# 主組態檔
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
# 虛擬主機組態目錄
- ./nginx/conf.d:/etc/nginx/conf.d:ro
# 網站內容目錄
- ./www:/var/www/html:ro
# SSL 憑證目錄
- ./nginx/ssl:/etc/nginx/ssl:ro
# 日誌目錄(持久化)
- nginx-logs:/var/log/nginx
# 快取目錄(持久化)
- nginx-cache:/var/cache/nginx
# 環境變數
environment:
- TZ=Asia/Taipei
- NGINX_HOST=example.com
- NGINX_PORT=80
# 網路設定
networks:
- web-network
# 依賴服務
depends_on:
- php-fpm
- redis
# 健康檢查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
php-fpm:
# PHP-FPM 容器(用於處理動態內容)
image: php:8.2-fpm-alpine
container_name: php-fpm
restart: unless-stopped
volumes:
- ./www:/var/www/html:ro
- ./php/php.ini:/usr/local/etc/php/php.ini:ro
networks:
- web-network
environment:
- TZ=Asia/Taipei
redis:
# Redis 容器(用於快取)
image: redis:7-alpine
container_name: redis-cache
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- redis-data:/data
networks:
- web-network
environment:
- TZ=Asia/Taipei
# 資料卷定義
volumes:
nginx-logs:
driver: local
nginx-cache:
driver: local
redis-data:
driver: local
# 網路定義
networks:
web-network:
driver: bridge
對應的 Nginx 組態檔需要針對容器環境進行調整。容器內的檔案路徑與主機不同,日誌輸出可以導向標準輸出以便於容器日誌管理系統收集。同時,需要確保 Nginx 能夠正確解析到其他容器的服務名稱。
# nginx/nginx.conf
# Docker 容器環境 Nginx 組態
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format json_combined escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
access_log /var/log/nginx/access.log json_combined;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# 載入虛擬主機組態
include /etc/nginx/conf.d/*.conf;
}
# nginx/conf.d/default.conf
# 預設虛擬主機組態
# PHP-FPM 上游定義
upstream php_backend {
server php-fpm:9000;
keepalive 8;
}
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
# 健康檢查端點
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 靜態檔案處理
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
# PHP 檔案處理
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass php_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 180s;
fastcgi_read_timeout 180s;
}
# 預設位置處理
location / {
try_files $uri $uri/ =404;
}
}
使用 Docker Compose 啟動服務非常簡單,只需要一個命令就能夠完成整個堆疊的部署。容器間的網路連線由 Docker 自動處理,服務發現透過容器名稱即可實現。
# 啟動所有服務
docker-compose up -d
# 查看服務狀態
docker-compose ps
# 查看服務日誌
docker-compose logs -f nginx
# 重新載入 Nginx 組態
docker-compose exec nginx nginx -s reload
# 停止所有服務
docker-compose down
# 停止並移除資料卷
docker-compose down -v
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 130
package "Docker 主機" {
package "Web 網路 (Bridge)" {
rectangle "Nginx 容器" as nginx {
component "Nginx 主程序" as nginx_master
component "工作程序" as nginx_workers
folder "組態檔案 (唯讀掛載)" as nginx_conf
folder "網站內容 (唯讀掛載)" as nginx_www
folder "SSL 憑證 (唯讀掛載)" as nginx_ssl
}
rectangle "PHP-FPM 容器" as php {
component "PHP-FPM 程序" as php_process
folder "應用程式碼 (唯讀掛載)" as php_code
}
rectangle "Redis 容器" as redis {
component "Redis 服務" as redis_service
database "資料持久化" as redis_data
}
}
cloud "外部請求" as client
database "持久化資料卷" as volumes
}
client -down-> nginx : "HTTP/HTTPS\n連接埠 80/443"
nginx -down-> php : "FastCGI\n連接埠 9000"
nginx -down-> redis : "快取查詢\n連接埠 6379"
php -down-> redis : "Session 存儲"
nginx_conf -up-> volumes
nginx_www -up-> volumes
redis_data -up-> volumes
@endumlSSL/TLS 安全性強化
在現代 Web 環境中,HTTPS 已經從可選項變為必要的基礎設施。SSL/TLS 協定不僅保護資料傳輸的機密性,更提供了伺服器身份驗證機制,防止中間人攻擊。搜尋引擎也將 HTTPS 作為排名因素之一,促使網站管理者採用加密連線。
Nginx 的 SSL/TLS 組態需要平衡安全性與相容性。最新的 TLS 1.3 協定提供了更強的安全性與更好的效能,但仍需要支援舊版協定以確保廣泛的客戶端相容性。加密套件的選擇也是關鍵,應該優先使用提供前向保密特性的套件,即使私鑰洩露也無法解密過去的通訊內容。
# SSL/TLS 安全組態範例
# /etc/nginx/conf.d/ssl-example.conf
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
##
# SSL 憑證設定
##
# SSL 憑證檔案(完整憑證鏈)
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
# SSL 私鑰檔案
ssl_certificate_key /etc/nginx/ssl/example.com/privkey.pem;
# 信任的 CA 憑證(用於 OCSP Stapling)
ssl_trusted_certificate /etc/nginx/ssl/example.com/chain.pem;
##
# SSL 協定與加密套件
##
# 支援的 TLS 協定版本
# 移除已不安全的 TLS 1.0 和 1.1
ssl_protocols TLSv1.2 TLSv1.3;
# 優先使用伺服器端的加密套件順序
ssl_prefer_server_ciphers on;
# TLS 1.2 加密套件設定
# 優先使用提供前向保密的 ECDHE 套件
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
# TLS 1.3 加密套件(通常使用預設值即可)
# ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
##
# DH 參數與 ECDH 曲線
##
# Diffie-Hellman 參數檔案(用於 DHE 套件)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# ECDH 曲線設定
ssl_ecdh_curve secp384r1;
##
# SSL Session 快取
##
# 共享 SSL Session 快取
# 10MB 約可儲存 40000 個 Session
ssl_session_cache shared:SSL:50m;
# SSL Session 超時時間
ssl_session_timeout 1d;
# 啟用 SSL Session Tickets
ssl_session_tickets on;
# Session Ticket 金鑰檔案(定期輪替)
ssl_session_ticket_key /etc/nginx/ssl/ticket.key;
##
# OCSP Stapling
##
# 啟用 OCSP Stapling 減少客戶端憑證驗證延遲
ssl_stapling on;
# 驗證 OCSP 回應
ssl_stapling_verify on;
# DNS 解析器(用於 OCSP 查詢)
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
##
# 安全性標頭
##
# HTTP 嚴格傳輸安全(HSTS)
# 強制客戶端在指定時間內只使用 HTTPS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# 防止點擊劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# XSS 防護
add_header X-XSS-Protection "1; mode=block" always;
# MIME 類型嗅探防護
add_header X-Content-Type-Options "nosniff" always;
# 引用來源政策
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# 內容安全政策
add_header Content-Security-Policy "default-src 'self' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https: data:; connect-src 'self' https:; frame-ancestors 'self';" always;
# 權限政策
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
##
# 網站內容
##
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP 重導向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# Let's Encrypt ACME 挑戰
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# 其他所有請求重導向到 HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
使用 Let’s Encrypt 取得免費的 SSL 憑證是最佳實踐。Certbot 工具能夠自動化憑證的申請與更新流程,配合 Nginx 外掛可以自動完成組態調整。憑證的自動更新確保了持續的安全保護,避免因憑證過期導致服務中斷。
# 安裝 Certbot 與 Nginx 外掛
sudo apt install -y certbot python3-certbot-nginx
# 申請 SSL 憑證(自動組態 Nginx)
sudo certbot --nginx -d example.com -d www.example.com
# 測試自動更新
sudo certbot renew --dry-run
# 設定自動更新 Cron 任務
echo "0 0,12 * * * root certbot renew --quiet" | sudo tee -a /etc/crontab
# 生成 DH 參數檔案(提升安全性,但生成過程較耗時)
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
HSTS(HTTP Strict Transport Security)標頭指示瀏覽器在指定時間內只能透過 HTTPS 存取網站,即使使用者手動輸入 HTTP URL 也會自動轉換。includeSubDomains 指令將這個政策擴展到所有子網域,preload 則是準備將網站加入瀏覽器的 HSTS 預載入清單。
單頁應用與 API 閘道配置
單頁應用架構已成為現代 Web 開發的主流模式。React、Vue.js、Angular 等前端框架構建的應用程式,在客戶端透過 JavaScript 處理路由,而不是傳統的伺服器端路由。這要求 Nginx 的組態必須正確處理前端路由,避免將前端路由路徑誤判為不存在的檔案。
API 閘道模式將後端微服務隱藏在統一的入口之後。Nginx 作為反向代理,負責請求路由、負載平衡、快取與安全控管。這種架構分離了前端與後端的關注點,使得兩者可以獨立開發與部署,同時也簡化了跨域資源共享的處理。
# 單頁應用與 API 閘道組態範例
# /etc/nginx/conf.d/spa-api-gateway.conf
# 後端 API 服務定義
upstream api_backend {
least_conn;
server api1.internal.example.com:8080 max_fails=3 fail_timeout=30s;
server api2.internal.example.com:8080 max_fails=3 fail_timeout=30s;
server api3.internal.example.com:8080 max_fails=3 fail_timeout=30s backup;
keepalive 32;
}
# WebSocket 服務定義
upstream websocket_backend {
server ws1.internal.example.com:8081;
server ws2.internal.example.com:8081;
}
server {
listen 443 ssl http2;
server_name app.example.com;
# SSL 設定(參考前面的 SSL 組態)
ssl_certificate /etc/nginx/ssl/app.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/app.example.com/privkey.pem;
# 單頁應用根目錄
root /var/www/spa;
index index.html;
##
# SPA 前端路由處理
##
location / {
# 嘗試尋找檔案,若不存在則返回 index.html
# 讓前端 JavaScript 路由器處理
try_files $uri $uri/ /index.html;
# 快取控制(針對 index.html 不快取)
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# 靜態資源長期快取
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
}
##
# API 反向代理
##
location /api/ {
# 套用限流保護
limit_req zone=req_limit burst=20 nodelay;
# 移除 /api 前綴並轉發到後端
rewrite ^/api/(.*) /$1 break;
proxy_pass http://api_backend;
proxy_http_version 1.1;
# 維持到後端的持久連線
proxy_set_header Connection "";
# 轉發客戶端資訊
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;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# 超時設定
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# CORS 標頭設定(如果需要)
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH, OPTIONS" always;
add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-Requested-With" always;
add_header Access-Control-Allow-Credentials "true" always;
# 處理 OPTIONS 預檢請求
if ($request_method = 'OPTIONS') {
return 204;
}
# 錯誤頁面
proxy_intercept_errors on;
error_page 502 503 504 = @api_error;
}
##
# WebSocket 支援
##
location /ws/ {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
# WebSocket 升級標頭
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;
# WebSocket 超時設定(較長)
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
}
##
# 錯誤處理
##
location @api_error {
default_type application/json;
return 502 '{"error": "Service temporarily unavailable", "code": 502}';
}
# 404 錯誤頁面
error_page 404 /404.html;
location = /404.html {
internal;
}
# 50x 錯誤頁面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
internal;
}
}
這個組態展示了完整的 SPA 與 API 閘道整合方案。try_files 指令確保所有前端路由都能正確處理,而 API 請求則透過反向代理轉發到後端服務。CORS 標頭的設定允許跨域請求,OPTIONS 預檢請求的特殊處理確保了 CORS 機制的正常運作。
WebSocket 支援需要特別的組態。Upgrade 和 Connection 標頭的正確設定是 WebSocket 連線建立的關鍵。相較於一般 HTTP 請求,WebSocket 連線的生命週期可能很長,因此需要設定較長的超時時間。
進階主題與最佳實踐
在生產環境中部署 Nginx 還需要考慮監控、日誌分析、自動化部署等多個面向。完善的監控系統能夠及時發現效能瓶頸與異常狀況,日誌分析提供了流量洞察與安全審計的基礎,而自動化部署則確保了變更的快速與可靠執行。
GoAccess 是一款開源的即時日誌分析工具,能夠解析 Nginx 的存取日誌並生成豐富的統計報告。它支援終端機介面與 HTML 報告兩種輸出方式,可以快速了解網站的流量模式、訪客來源、熱門頁面等資訊。對於需要即時監控的場景,GoAccess 的 WebSocket 模式能夠實現儀表板的自動更新。
# 安裝 GoAccess
sudo apt install -y goaccess
# 即時分析 Nginx 存取日誌(終端機模式)
goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
--real-time-html
# 生成靜態 HTML 報告
goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
--output=/var/www/html/report.html
# 啟動即時 HTML 儀表板
goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
--real-time-html \
--output=/var/www/html/report.html \
--daemonize \
--port=7890 \
--ws-url=wss://example.com:7890
# 分析壓縮的日誌檔案
zcat /var/log/nginx/access.log.*.gz | goaccess \
--log-format=COMBINED \
--output=/var/www/html/report.html
持續整合與持續部署是現代軟體開發的核心實踐。Jenkins 與 GitLab CI/CD 都提供了強大的自動化能力,能夠在程式碼變更時自動觸發建置、測試與部署流程。整合 Nginx 組態的自動化部署需要確保語法驗證、漸進式推送與快速回復機制。
# .gitlab-ci.yml
# GitLab CI/CD 自動化部署 Nginx 組態
stages:
- validate
- test
- deploy
variables:
NGINX_CONFIG_PATH: "./nginx"
DEPLOY_HOST: "production.example.com"
# 組態語法驗證
validate:nginx:
stage: validate
image: nginx:alpine
script:
- nginx -t -c ${NGINX_CONFIG_PATH}/nginx.conf
only:
changes:
- nginx/**/*
# 安全性掃描
test:security:
stage: test
image: ubuntu:latest
script:
- apt-get update && apt-get install -y ssl-cert
- |
# 檢查 SSL 組態
if grep -r "ssl_protocols.*TLSv1\." ${NGINX_CONFIG_PATH}; then
echo "發現不安全的 TLS 協定版本"
exit 1
fi
only:
changes:
- nginx/**/*
# 部署到生產環境
deploy:production:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan ${DEPLOY_HOST} >> ~/.ssh/known_hosts
script:
- |
# 同步組態檔案
rsync -avz --delete \
${NGINX_CONFIG_PATH}/ \
deploy@${DEPLOY_HOST}:/tmp/nginx-config/
# 在遠端主機上執行部署
ssh deploy@${DEPLOY_HOST} << 'EOF'
# 備份當前組態
sudo cp -r /etc/nginx /etc/nginx.backup.$(date +%Y%m%d%H%M%S)
# 複製新組態
sudo cp -r /tmp/nginx-config/* /etc/nginx/
# 驗證組態
sudo nginx -t
# 重新載入 Nginx
sudo systemctl reload nginx
# 清理臨時檔案
rm -rf /tmp/nginx-config
EOF
only:
- main
when: manual
environment:
name: production
url: https://example.com
Nginx 的強大不僅體現在其卓越的效能,更在於其靈活的組態能力與豐富的生態系統。從基礎的 Web 伺服器功能到複雜的微服務閘道,從簡單的靜態內容服務到動態內容快取,Nginx 都能夠勝任。透過合理的組態調校,Nginx 能夠在有限的硬體資源下支撐大規模的流量,同時保持低延遲的回應速度。
玄貓認為,掌握 Nginx 的關鍵在於理解其工作原理而非死記組態參數。每個參數都有其存在的理由與適用場景,盲目複製他人的組態往往無法達到最佳效果。生產環境的組態應該是經過反覆測試與調整的結果,需要根據實際的硬體規格、流量模式與業務需求進行客製化。
安全性是永遠不能妥協的領域。即使犧牲一些效能,也應該確保 SSL/TLS 組態的安全性,定期更新 Nginx 版本以修補已知漏洞,實施適當的存取控制與限流機制。同時,完善的監控與日誌系統能夠在問題發生時快速定位,甚至在問題擴大前就發現潛在的隱患。
隨著容器化與雲端原生技術的普及,Nginx 的使用模式也在不斷演進。Kubernetes Ingress Controller、Service Mesh 等新興技術正在重新定義反向代理的角色。然而,Nginx 的核心價值始終不變,那就是提供高效能、高可靠性的 HTTP 流量處理能力。對於任何需要建構現代化 Web 服務的團隊而言,深入掌握 Nginx 都是一項值得投資的技能。