Nginx配置文件介紹和基本使用
Nginx 是一款高性能的 HTTP 服務器、反向代理服務器及電子郵件代理服務器,由俄羅斯工程師 Igor Sysoev 開發,并于2004年首次公開發布。以輕量級、高并發能力、穩定性和低資源消耗著稱。
主要功能
- HTTP服務器:可以作為靜態網頁服務器,處理大量的并發請求。
- 反向代理服務器:能夠將客戶端請求轉發給后端服務器,并將響應返回給客戶端,支持負載均衡。
- 郵件代理服務器:提供IMAP、POP3和SMTP協議的支持。
- 高并發處理:單臺服務器可支持數萬并發連接。
- 低內存占用:典型場景下內存占用僅數兆至數十兆。
- 模塊化設計:支持豐富的擴展模塊(如
rewrite
、ssl
、http_gzip_module
等)。 - 反向代理與負載均衡:可高效轉發請求至后端服務器集群。
- 靜態資源處理:擅長處理靜態文件(如圖片、CSS、JS),性能優于傳統 Apache 服務器。
- 熱部署:無需停止服務即可更新配置和二進制文件。
- 其他特性:包括但不限于SSL/TLS加密、URL重寫、gzip壓縮、緩存等。
1、安裝
1.1、聯網Linux
# Ubuntu/Debian
# 更新軟件源
sudo apt update
# 安裝 Nginx
sudo apt install nginx# CentOS/RHEL
# 安裝 epel 源(若未安裝)
sudo yum install epel-release
# 安裝 Nginx
sudo yum install nginx# 啟動服務
sudo systemctl start nginx
# 查看狀態(確保 active(running))
sudo systemctl status nginx
# 開機自啟
sudo systemctl enable nginx# 測試配置文件語法
nginx -t
# 查看完整配置(包括默認值)
nginx -T# 調試日志
error_log /var/log/nginx/error.log debug;
# 使用 strace 調試
strace -p $(cat /var/run/nginx.pid)
1.2、Windows
-
下載地址:
http://nginx.org/en/download.html
(選擇Windows
版本)。 -
解壓后,進入目錄,雙擊
nginx.exe
啟動。 -
命令行啟動 / 停止:
# 啟動 start nginx # 重啟 nginx -s reload # 重新打開日志文件 nginx -s reopen # 停止(快速停止) nginx -s stop # 優雅停止(處理完當前請求后停止) nginx -s quit
1.3、macOS
# 使用 Homebrew 安裝
brew install nginx
# 啟動服務
brew services start nginx
# 或手動啟動
nginx -c /usr/local/etc/nginx/nginx.conf
路徑:/usr/local/etc/nginx/nginx.conf
2、配置
使用核心就是其配置文件。
Nginx 的配置文件采用模塊化結構,通過指令(directive)和上下文(context)組織。
Nginx 的配置文件是一個文本文件,通常命名為nginx.conf
,它定義了 Nginx 如何處理請求、響應以及其他相關設置。
Nginx 的主要配置文件位于/etc/nginx/nginx.conf
或/usr/local/nginx/conf/nginx.conf
。你也可以在這個目錄下創建額外的配置文件,通過 include
指令引入主配置文件中。
配置文件結構
Nginx 配置文件的基本結構是由多個塊(block)組成,每個塊可以包含其他塊或指令。
頂級塊包括 main
(全局設置)、http
、server
和 location
等。
全局塊 (main context)
├── events 塊
└── http 塊├── server 塊 (虛擬主機)│ ├── location 塊│ └── location 塊└── server 塊├── location 塊└── location 塊
主要塊介紹如下
2.1、Main (全局)
位于配置文件的最外層,定義影響整個Nginx服務器的行為,如工作進程數(worker_processes
)、錯誤日志位置(error_log
)等。
常用指令
user
: 指定Nginx工作進程運行的用戶和組。worker_processes
: 設置工作進程的數量,推薦設置為CPU核心數。error_log
: 定義錯誤日志的位置和記錄級別。pid
: 指定存儲主進程ID的文件位置。
示例
user www-data; # 運行Nginx的用戶和組,一般情況下默認都是nginx用戶
worker_processes auto; # 工作進程數,auto 自動檢測 CPU 核心數(通常設為CPU核心數)
pid /run/nginx.pid; # PID文件位置
error_log /var/log/nginx/error.log warn; # 錯誤日志路徑和級別# 工作進程最大打開文件數限制(提升并發能力)
worker_rlimit_nofile 100000; # 每個worker能打開的文件描述符數量
錯誤日志說明
這一塊的 error_log
日志主要用于記錄Nginx運行過程中遇到的各種問題、警告和調試信息。包括但不限于啟動失敗、配置文件錯誤、資源限制(如打開文件數過多)、處理請求時發生的錯誤等。可以設置不同的日志級別來控制哪些級別的消息會被記錄下來。可選的日志級別從低到高依次為:debug、info、notice、warn、error、crit、alert、emerg。例如:
error_log /var/log/nginx/error.log warn;
對于排查Nginx的運行故障非常有用,可以幫助管理員了解服務器的狀態和可能的問題所在。
還有一類是訪問日志,和這里的日志是不一樣的,見下面小節。
2.2、Events
配置影響 Nginx 服務器與客戶端網絡連接的設置。
示例
events {worker_connections 1024; # 每個worker進程的最大連接數multi_accept on; # 一次接受所有(多個)新連接# 事件驅動模型(Linux 推薦 epoll,FreeBSD 推薦 kqueue)use epoll; # Linux高性能事件模型accept_mutex on; # 啟用互斥鎖進行連接分發
}
2.3、Http
包含與HTTP相關的配置,可嵌套多個server
塊,每個server
塊代表一個虛擬主機。
常用指令
include
: 包含其他配置文件,便于管理大量配置。default_type
: 默認MIME類型。log_format
: 自定義訪問日志格式。access_log
: 訪問日志的位置及使用的日志格式。sendfile
: 啟用或禁用sendfile()
函數以提高文件傳輸效率。keepalive_timeout
: 設置長連接超時時間。
示例
http {# 基本設置include /etc/nginx/mime.types; # MIME類型映射文件default_type application/octet-stream; # 默認MIME類型# 日志格式定義log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main; # 訪問日志# 性能優化sendfile on; # 啟用高效文件傳輸模式tcp_nopush on; # 僅在sendfile開啟時有效tcp_nodelay on; # 禁用Nagle算法# 長連接配置keepalive_timeout 65; # 保持連接超時時間types_hash_max_size 2048; # MIME類型哈希表大小# Gzip壓縮gzip on;gzip_disable "msie6"; # 禁用IE6及以下版本的Gzip壓縮gzip_vary on; # 是否在響應頭部添加 Vary: Accept-Encoding 字段gzip_proxied any; # 對所有代理請求啟用Gzip壓縮gzip_comp_level 6; # 設置壓縮級別為6gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; # 指定哪些MIME類型的內容需要被壓縮,默認僅壓縮text/html類型# 虛擬主機配置(可包含多個 server 塊),包含其他配置文件include /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;
}
訪問日志說明
訪問日志記錄了每個客戶端請求的詳細信息,適用于分析網站流量、用戶行為、性能監控等方面。
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
詳細使用,遇到了再說,比如buffer、gzip等參數的使用。
內容:通常包含但不限于以下信息:
- 客戶端IP地址
- 請求時間
- 請求方法(GET、POST等)
- 請求的URL路徑
- HTTP響應狀態碼
- 發送到客戶端的數據量
- 引薦頁面
- 用戶代理(瀏覽器類型等)
格式:可以通過log_format
指令自定義訪問日志的格式。默認情況下,Nginx使用“combined”格式,示例如下:
log_format combined '$remote_addr - $remote_user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log combined;
除了記錄基本的HTTP請求信息外,還可以根據需要添加其他變量,如請求處理時間、是否緩存命中等,以滿足特定的監控需求。
這里的日志是訪問url請求的日志,和上面的錯誤日志是不一樣的,更多見上面小節。
日志格式示例
log_format combined '$remote_addr - $remote_user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent"';
這是Nginx默認使用的格式,適用于大多數情況。
字段解釋:
$remote_addr
: 客戶端IP地址。$remote_user
: 用于HTTP基本認證的用戶名(如果沒有則為-
)。$time_local
: 服務器本地時間。$request
: 請求的第一行,包括方法、URL和協議版本。$status
: HTTP響應狀態碼。$body_bytes_sent
: 發送給客戶端的字節數,不包括響應頭的大小。$http_referer
: 來源頁面(即用戶是從哪個頁面鏈接到當前頁面的),注意這個字段是可選的,且可能為空。$http_user_agent
: 用戶代理(User-Agent)字符串,包含了客戶端瀏覽器和其他信息。
帶有請求時間和上游服務器響應時間的格式
如果你想了解每個請求的處理時間和后端服務器的響應時間,可以使用以下格式:
log_format timed_combined '$remote_addr - $remote_user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent" ''$request_time $upstream_response_time';
新增字段解釋:
$request_time
: 請求處理總時間(從接收請求到發送響應完畢所花費的時間),單位是秒,精度達到毫秒級。$upstream_response_time
: 上游服務器(如Tomcat)響應時間,單位是秒。
JSON格式
對于需要結構化數據的情況,可以使用JSON格式的日志,便于后續使用ELK(Elasticsearch, Logstash, Kibana)或EFK(Elasticsearch, Fluentd, Kibana)等工具進行集中化日志分析:
log_format json '{"time": "$time_iso8601", ''"remote_addr": "$remote_addr", ''"remote_user": "$remote_user", ''"request": "$request", ''"status": $status, ''"body_bytes_sent": $body_bytes_sent, ''"request_time": $request_time, ''"upstream_response_time": "$upstream_response_time", ''"http_referer": "$http_referer", ''"http_user_agent": "$http_user_agent"}';
access_log /var/log/nginx/access.log json;
這種格式將日志條目以JSON格式輸出,便于解析和自動化處理。
更多細節的高級格式
如果你需要更多的信息來進行深入分析,比如客戶端的真實IP(通過X-Forwarded-For頭)、請求ID(用于追蹤特定請求)等,可以使用如下格式:
log_format advanced '$remote_addr - $remote_user [$time_local] ''"$request" $status $body_bytes_sent ''"$http_referer" "$http_user_agent" ''"$http_x_forwarded_for" "$request_id" ''$request_time $upstream_response_time';
新增字段解釋:
$http_x_forwarded_for
: 客戶端的真實IP地址,通常在反向代理或負載均衡場景下使用。$request_id
: 可以通過設置$uid_got
或類似的變量來生成一個唯一的請求ID,用于追蹤特定請求。
選擇適合你需求的日志格式,并確保日志文件不會過大影響性能,同時定期歸檔和清理舊日志。如果你正在使用集中化的日志管理工具,那么采用結構化的JSON格式可能會更加方便。
2.4、Server
用于定義虛擬主機(網站),可以有多個server
塊來服務不同的域名或端口。
常用指令
listen
: 監聽的IP地址和端口號。server_name
: 該服務器塊處理的域名或IP地址。root
: 網站根目錄的位置。index
: 默認索引文件名。
示例
server {listen 80; # 監聽端口server_name example.com www.example.com; # 服務器名稱,域名root /var/www/example.com; # 網站根目錄index index.html index.htm; # 默認索引文件# 錯誤頁面error_page 404 /404.html;location = /404.html {internal; # 僅內部訪問}error_page 500 502 503 504 /50x.html;# 日志access_log /var/log/nginx/example.access.log;error_log /var/log/nginx/example.error.log;# Location塊location / {try_files $uri $uri/ =404;}location ~ \.php$ {include snippets/fastcgi-php.conf;fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;}# 靜態資源緩存策略location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {expires 30d;access_log off;add_header Cache-Control "public";}# 禁止訪問隱藏文件location ~ /\. {deny all;}
}
2.5、Location(重要)
定義如何處理針對特定URL路徑的請求,是server
塊內的子塊。
常用指令
- location: 根據請求的URI匹配規則來處理請求。
- 使用前綴匹配(
location /prefix
)、精確匹配(location = /exact/path
)、正則表達式匹配(location ~ pattern
)等方式。
- 使用前綴匹配(
alias
: 定義別名路徑,替換路徑前綴更靈活。try_files
: 嘗試按順序查找指定的文件或目錄,直到找到為止,找不到則返回404。
root vs alias
-
root:會拼接 location 的前綴匹配,就是 前綴匹配 + root 后面的路徑,就是說將請求的 URI 直接拼接到
root
指定的路徑之后。會保留
location
匹配的前綴路徑,并將其作為文件路徑的一部分。使用場景
-
適用于簡單的路徑映射,如將整個站點的靜態資源指向同一目錄(如
root /var/www/html;
)。 -
可在
http
、server
、location
塊中使用。
-
-
alias:使用 alias 后面的路徑替換location 的前綴匹配,并不會拼接前綴匹配;會移除 location 匹配的前綴路徑(如
/static/
),直接用 alias 路徑替換,注意路徑末尾必須帶 /。使用場景
- 必須與 location 配合使用,且只能在
location
塊中生效。 - 路徑末尾必須包含
/
,否則可能導致路徑解析錯誤(如請求/static/image.jpg
時,若 alias 為/data
,Nginx 會嘗試訪問/datastatic/image.jpg
,顯然不存在)。 - 若
location
匹配模式不含末尾/
(如location /static
),alias 路徑也可不加/
,但實際開發中建議統一使用帶/
的匹配模式和 alias 路徑。
- 必須與 location 配合使用,且只能在
區別
- 使用
root
時,服務器文件系統中必須存在與location
前綴一致的子目錄(如/data/static/
)。 - 使用
alias
時,可直接映射到任意目錄(如/data/static_files/
),無需保留前綴路徑。
優先級:
- 當
location
同時存在root
和alias
時,alias
會覆蓋root
,因為alias
專門用于路徑替換。
正則 location 中的使用
-
在正則匹配的
location
(如location ~ \.jpg$
)中,只能使用alias
,不能使用root
。location ~ \.(jpg|png|gif)$ {alias /data/images/; # 正確用法 }
整體示例
# 訪問 http://yourdomain.com/images/logo.png# root,直接拼接,實際是:/var/www/static/images/logo.png
location /images/ {root /var/www/static/; #======================= ①
}# alias,移除前綴,實際是:/var/www/static/images/logo.png
location /images/ {alias /var/www/static/images/; #======================= ②
}# 注意,上述的 ① 和 ② 處的值不一樣
語法格式
location [修飾符] 匹配模式 {# 配置指令
}
修飾符類型(優先級從高到低):
=
:精確匹配,如果找到完全匹配,Nginx將停止搜索并使用此匹配。停止搜索后面的location,即使后面有更“精確”的正則表達式。^~
:前綴匹配(否定前綴),不檢查后面location的正則,比普通前綴匹配更高的優先級,常用于加速某些特定路徑的匹配過程。~
:區分大小寫的正則匹配。~*
:不區分大小寫的正則匹配。- 無修飾符:前綴匹配,只要請求的URI以指定的字符串開頭,就被認為是匹配的,Nginx會從最長到最短嘗試匹配所有定義的前綴。
- 正則表達式:正則表達式匹配是在前綴匹配之后進行的,并且一旦匹配成功,Nginx也會停止搜索(停止搜索后面的普通location),若轉義特殊字符,請確保在正則表達式中正確使用反斜杠。
匹配優先級
- 精確匹配 (
=
) - 最高優先級 - 前綴匹配 (
^~
) - 特殊前綴(短路機制) - 正則匹配 (
~
或~*
) - 按配置文件順序 - 普通前綴匹配 (無修飾符) - 最低優先級
匹配順序
- 首先,Nginx嘗試找到最具體的前綴匹配。如果有多個前綴匹配,選擇最長的那個。
- 如果找到了帶有
^~
前綴的前綴匹配,并且它是最佳匹配,則直接使用它而不再檢查正則表達式匹配。 - 然后,Nginx檢查正則表達式匹配。按照它們在配置文件中出現的順序進行測試,一旦匹配即停止。
- 如果沒有正則表達式匹配被選中,先前找到的最佳前綴匹配將被使用。
server {location = /login { # 精確匹配/login[ configuration A ]}location /static/ { # 前綴匹配/static/,會先記住它,不會立即使用這個匹配,繼續去檢查是否有正則表達式匹配更合適[ configuration B ]}location ^~ /images/ { # 否定前綴匹配/images/,阻止后續正則匹配[ configuration C ]}location ~* \.(gif|jpg|png)$ { # 不區分大小寫的正則表達式匹配圖片文件[ configuration D ]}
}
在這個例子中:
- 請求
/login
會匹配“configuration A”。 /static/style.css
會匹配“configuration B”。/images/logo.png
會匹配“configuration C”,即使它也符合正則表達式location
的條件,但由于^~
的存在,不會進一步檢查正則表達式。- 對于
/documents/document.pdf
,由于沒有匹配的前綴或精確匹配,若存在其他匹配邏輯,將根據其情況決定;但如果請求是針對圖像文件(如.jpg
),則會匹配“configuration D”。
示例
# 精確匹配
location = / { # 精確匹配首頁# 特殊處理
}
location = /exact-match {# 僅匹配完全相同的路徑 /exact-matchreturn 200 "Exact match!";
}# 前綴匹配
location /images/ { # 匹配/images/開頭的URIroot /data;expires 30d; # 緩存30天
}
location ^~ /static/ {# 匹配以 /static/ 開頭的路徑,不繼續正則匹配root /var/www;
}# 正則匹配
location ~ \.(php|php5)$ {# 匹配 .php 或 .php5 結尾的路徑fastcgi_pass unix:/run/php/php8.1-fpm.sock;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;include fastcgi_params;
}location ~* \.(jpg|jpeg|png|gif)$ {# 不區分大小寫的正則匹配expires 30d;
}location ~ \.(gif|jpg|png)$ { # 匹配圖片文件root /data/images;access_log off; # 不記錄訪問日志
}location ~* \.php$ { # 匹配PHP文件(不區分大小寫)fastcgi_pass 127.0.0.1:9000;include fastcgi_params;
}# 通用匹配
location / {# 所有未匹配的請求都會落入此處try_files $uri $uri/ /index.php?$query_string; # 嘗試文件 → 目錄 → PHP 處理
}
示例2
# 假設有以下配置:
server {location = /exact-match { ... } # 1. 精確匹配location ^~ /prefix-special { ... } # 2. 特殊前綴location ~ /regex-.* { ... } # 3. 正則匹配1location ~ /prefix-.* { ... } # 4. 正則匹配2location /prefix-normal { ... } # 5. 普通前綴
}
當請求 /prefix-special/test
時:
- 先檢查精確匹配
/exact-match
→ 不匹配。 - 檢查
^~ /prefix-special
→ 匹配成功! - 立即停止,不再檢查后面的正則和普通前綴。
匹配流程圖
用戶請求 URI ——>
|
|——→ 是否存在 = 精確匹配? → 是 → 使用并結束|否↓是否存在前綴匹配?(包括 ^~ 和普通前綴)↓選擇最長匹配的前綴↓是否是 ^~ 類型? → 是 → 使用并結束|否↓繼續檢查正則表達式匹配(按配置順序查找)↓找到第一個匹配的正則? → 是 → 使用并結束|否↓使用之前記錄的最長前綴匹配↓都沒找到? → 返回 404
說明(重要)
我們可以簡單的理解為兩大類匹配。
第一類就是
=
號匹配:
=
號匹配優先級最高,nginx 只要找到就停止向下或者繼續匹配 location,就直接使用當前等號的location,類似于循環中的break關鍵字作用,該次路徑代理結束;第二類就是
前綴匹配
:nginx 會找所有的滿足的前綴匹配 location,此時不管
~
和^~
符號,只管滿足前綴匹配,且不會立即使用這個匹配,而是先記住它;等找到所有且記住所有之后,然后再看是否滿足^~
符號前綴的location,如果滿足就使用當前這個,匹配結束,也類似break關鍵字;再者,如果沒有^~
符號前綴的location,就找~
符號前綴的location,如果只有一個,則使用并結束當前匹配,類似break;如果有多個~
符號前綴的location,則使用最長的location,使用并結束當前匹配,也類似break;如果沒有
^~
符號前綴的location 也沒有~
符號前綴的location,則使用最簡單的前綴的location;如果只有一個就使用它,如果有多個就就使用滿足且最長的那一個。大致流程是這樣,更詳細的原理,可以查看官網。
2.6、Upstream
定義后端服務器組用于負載均衡:
upstream backend {server backend1.example.com weight=5;server backend2.example.com:8080;server unix:/tmp/backend3.sock;server backup1.example.com:8080 backup;# 負載均衡方法# least_conn; # 最少連接# ip_hash; # IP哈希# hash $request_uri consistent; # 一致性哈希
}# 完整配置
http {# 定義上游服務器集群upstream backend_servers {# 輪詢策略(默認)server backend1.example.com weight=5; # 權重越高,分配請求越多server backend2.example.com weight=3;server backend3.example.com weight=2;# 其他負載均衡算法# ip_hash; # 基于客戶端 IP 哈希,確保同一客戶端始終訪問同一服務器# least_conn; # 最少連接數優先# fair; # 響應時間優先(需安裝 ngx_http_upstream_fair 模塊)# 健康檢查check interval=3000 rise=2 fall=5 timeout=1000 type=http;check_http_send "HEAD /health_check HTTP/1.0\r\n\r\n";check_http_expect_alive http_2xx http_3xx;}server {listen 80;server_name loadbalancer.example.com;location / {proxy_pass http://backend_servers;}}
}
2.7、Mail
配置郵件代理服務器:
mail {auth_http localhost:9000/auth;proxy_pass_error_message on;server {listen 110;protocol pop3;proxy on;}server {listen 25;protocol smtp;smtp_auth login plain;proxy on;}
}
3、常用指令詳解
3.1、基本指令
3.1.1、listen
監聽地址和端口:
listen 80;
listen 443 ssl;
listen [::]:80 ipv6only=on;
3.1.2、server_name
服務器名稱,支持通配符和正則:
server_name example.com *.example.com ~^www\d+\.example\.com$;
3.1.3、root
定義文檔根目錄:
root /var/www/html;
3.1.4、index
定義默認索引文件:
index index.html index.htm index.php;
3.2、訪問控制
3.2.1、allow/deny
IP訪問控制:
location /admin/ {allow 192.168.1.0/24;deny all;
}# 基于 IP 的訪問控制
location /admin {allow 192.168.1.0/24; # 允許內網訪問allow 203.0.113.45; # 允許特定 IPdeny all; # 其他 IP 拒絕
}
3.2.2、auth_basic
基本認證:
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;# 基于 HTTP 基本認證的訪問控制
location /secret {auth_basic "Restricted Area";auth_basic_user_file /etc/nginx/.htpasswd; # 使用 htpasswd 生成密碼文件
}
3.2.3、防盜鏈配置
location ~* \.(jpg|jpeg|png|gif|mp3|pdf)$ {valid_referers none blocked example.com *.example.com;if ($invalid_referer) {return 403; # 非法引用返回 403# 或重定向到本地圖片# rewrite ^/ http://example.com/forbidden.png;}
}
3.3、代理相關
3.3.1、proxy_pass
反向代理:
location / {proxy_pass http://backend;
}
3.3.2、proxy_set_header
設置代理頭:
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;server {listen 80;server_name proxy.example.com;location / {proxy_pass http://backend_server; # 后端服務器地址proxy_set_header Host $host; # 傳遞原始請求的 Host 頭proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實 IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme; # 傳遞請求協議(http/https)# 超時設置proxy_connect_timeout 5s;proxy_send_timeout 60s;proxy_read_timeout 60s;# 緩沖區設置proxy_buffer_size 16k;proxy_buffers 4 32k;proxy_busy_buffers_size 64k;}
}
3.3.3、cors 跨域問題
server {listen 80;server_name proxy.example.com;location / {add_header Access-Control-Allow-Origin 'http://localhost:8000' always; add_header Access-Control-Allow-Headers '*'; add_header Access-Control-Allow-Methods '*'; add_header Access-Control-Allow-Credentials 'true'; if ($request_method = 'OPTIONS') { return 204; } proxy_pass http://backend_server; # 后端服務器地址}
}
3.3.4、SSL/TLS配置
# ssl_certificate /path/to/cert.pem;
# ssl_certificate_key /path/to/key.pem;
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# ssl_session_cache shared:SSL:10m;
# ssl_session_timeout 10m;server {listen 443 ssl http2; # 啟用 HTTP/2server_name secure.example.com;# SSL 證書配置ssl_certificate /etc/nginx/ssl/cert.pem;ssl_certificate_key /etc/nginx/ssl/key.pem;# SSL 優化配置ssl_protocols TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers on;ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;ssl_session_cache shared:SSL:10m;ssl_session_timeout 1d;ssl_session_tickets off;# HSTS 頭部(增強 HTTPS 安全性)add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;# 網站根目錄root /var/www/secure;
}# HTTP 自動跳轉 HTTPS
server {listen 80;server_name secure.example.com;return 301 https://$host$request_uri;
}
使用本地測試證書
要在本地環境中使用Nginx配置SSL進行測試,你需要創建一個自簽名的SSL證書,并在Nginx中配置它。
mkdir -p /opt/data/nginx_https/conf/ssl
# 使用 openssl 創建
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt
運行上述命令將生成一個有效期為365天的自簽名證書(localhost.crt
)和對應的私鑰(localhost.key
)。
執行此命令時,系統會提示你輸入一些信息,如國家、省份等。對于本地測試,這些信息可以隨意填寫。
然后參照上述配置文件配置即可:
server {listen 443 ssl;server_name yourdomain.com;ssl_certificate /etc/nginx/ssl/localhost.crt;ssl_certificate_key /etc/nginx/ssl/localhost.key;location / {# 配置其他參數}
}
注意
:監聽端口處,一定加上 ssl
,開啟https功能。
3.3.5、websocket配置
server {listen 443 ssl;server_name yourdomain.com;ssl_certificate /path/to/your/certificate.crt;ssl_certificate_key /path/to/your/private.key;location /wss/ {proxy_pass http://backend_server; # 后端WebSocket服務器地址proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header Host $host;# 下面是可選的超時設置proxy_read_timeout 86400s;proxy_send_timeout 86400s;}
}
listen 443 ssl;
:監聽443端口,并開啟SSL。ssl_certificate
和ssl_certificate_key
:指定你的SSL證書和私鑰路徑。proxy_pass
:指向處理WebSocket連接的實際后端服務器地址。proxy_set_header Upgrade $http_upgrade;
和proxy_set_header Connection "upgrade";
:這些行告訴Nginx將HTTP連接升級到WebSocket協議。- 超時設置可以防止連接因為長時間沒有活動而被關閉。
3.4、重寫和重定向
3.4.1、rewrite
URL重寫:
# 格式
rewrite regex replacement [flag];
# flag:last|break|redirect|permanentrewrite ^/old/(.*)$ /new/$1 permanent;
3.4.2、return
返回狀態碼或重定向,相比 rewrite
指令,return
更加直觀和高效:
# 格式
return code [text];
return code URL;
return URL;# return 301 https://$host$request_uri;
# return 403;# 移除尾部斜杠
rewrite ^/(.*)/$ /$1 permanent;# 移動端跳轉
if ($http_user_agent ~* "mobile|android|iphone") {rewrite ^ http://m.example.com$request_uri permanent;
}# 網站維護模式
if (-f $document_root/maintenance.html) {return 503;
}
error_page 503 @maintenance;
location @maintenance {rewrite ^(.*)$ /maintenance.html break;
}
3.5、FastCGI 配置(PHP 處理)
示例
server {listen 80;server_name php.example.com;root /var/www/php;index index.php index.html;# 處理 PHP 請求location ~ \.(php|php5)$ {fastcgi_pass unix:/run/php/php8.1-fpm.sock; # PHP-FPM Unix 套接字# 或使用 TCP 連接:fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;include fastcgi_params;# 安全優化:禁用 path_infofastcgi_split_path_info ^(.+\.php)(/.+)$;fastcgi_param PATH_INFO $fastcgi_path_info;fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;}# 禁止訪問 .htaccess 文件location ~ /\.ht {deny all;}
}
4、實踐建議
4.1、模塊化配置
將不同功能的配置拆分到單獨文件中,通過 include
指令引入。
4.2、安全配置
server_tokens off; # 隱藏Nginx版本號
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
4.3、性能優化
aio on; # 異步I/O
directio 4m; # 大文件直接I/O
open_file_cache max=1000; # 文件描述符緩存# 開啟 gzip 壓縮
gzip on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml application/javascript application/xml;
gzip_vary on;# 文件緩存配置
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;# 靜態資源緩存
location ~* \.(jpg|jpeg|png|gif|css|js|ico|woff|woff2|ttf|eot|svg|otf)$ {expires 30d;add_header Cache-Control"public";access_log off;
}# 商品頁面緩存
# 對于商品頁面,可以緩存一部分動態內容,如價格和評論數量,以提高響應速度并減少對后端的壓力,
# 通過proxy_cache_valid 200 10m配置,緩存200狀態碼的響應10分鐘,避免頻繁訪問后端獲取相同數據。
location /product/{proxy_cache cache_zone;proxy_cache_key $uri;proxy_cache_valid 200 10m;proxy_cache_valid 404 1m;proxy_cache_use_stale error timeout updating;
}# API響應緩存,對于電商網站的API接口,可能會有一些數據變化不頻繁,可以進行緩存
# 通過上述緩存策略,Nginx幫助電商網站提高了性能,減少了后端負擔,提升了用戶的訪問速度和體驗
location /api/{proxy_cache cache_zone;proxy_cache_valid 200 5m;proxy_cache_use_stale error timeout updating;
}
4.4、錯誤處理
error_page 404 /custom_404.html;
location = /custom_404.html {internal;root /usr/share/nginx/html;
}
錯誤頁面說明
當客戶端請求資源時,如果服務器遇到問題或無法滿足請求,它會返回一個HTTP狀態碼來表示具體的情況。常見的HTTP狀態碼包括:
- 404 Not Found: 請求的資源未找到。
- 500 Internal Server Error: 服務器內部錯誤。
- 502 Bad Gateway: 作為網關或代理服務器從上游服務器收到無效響應。
- 503 Service Unavailable: 由于臨時維護或過載,服務器暫時無法處理請求。
- 504 Gateway Timeout: 作為網關或代理服務器未及時從上游服務器收到響應。
設置自定義錯誤頁面
在Nginx中,你可以使用error_page
指令來指定對于特定HTTP狀態碼應該顯示的錯誤頁面。
基本語法
error_page code [code...] =new_code uri;
code
: 要處理的HTTP狀態碼,可以是一個或多個。=new_code
: 可選參數,允許你更改返回給客戶端的狀態碼(不常用)。uri
: 當發生指定的錯誤時要使用的錯誤頁面的位置。
示例配置
-
簡單示例:為最常見的幾個錯誤代碼設置自定義錯誤頁面。
server {listen 80;server_name example.com;error_page 404 /404.html;error_page 500 502 503 504 /50x.html;location / {root /var/www/example.com/html;index index.html;}# 定義錯誤頁面的位置location = /404.html {root /var/www/example.com/errors;}location = /50x.html {root /var/www/example.com/errors;} }
在這個例子中:
- 對于
404 Not Found
錯誤,將返回/var/www/example.com/errors/404.html
文件。 - 對于
500
,502
,503
,504
錯誤,將返回/var/www/example.com/errors/50x.html
文件。
- 對于
-
重定向到外部URL:如果你想讓用戶在遇到錯誤時被重定向到另一個站點上的錯誤頁面。
server {listen 80;server_name example.com;error_page 404 = http://example.com/error-page-not-found;error_page 500 502 503 504 = http://example.com/error-page-server-error; }
-
動態生成錯誤頁面:如果你希望通過后端應用動態生成錯誤頁面,可以將請求轉發給FastCGI或其他后端服務。
server {listen 80;server_name example.com;error_page 404 /dynamic_404;location = /dynamic_404 {fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;include fastcgi_params;} }
-
返回不同狀態碼:有時候你可能想改變返回給客戶端的狀態碼。例如,將所有404錯誤改為返回200狀態碼(雖然通常不推薦)。
server {listen 80;server_name example.com;error_page 404 =200 /custom_404.html;location = /custom_404.html {root /var/www/example.com/errors;} }
4.5、日志分割
當Nginx的訪問日志文件變得過大時,這不僅會占用大量的磁盤空間,還可能影響到服務器性能和日志分析效率。處理過大的訪問日志文件通常采用**日志輪轉(log rotation)**的方法。日志輪轉可以定期重命名舊的日志文件,并通知Nginx重新打開新的日志文件以繼續記錄新產生的日志信息。
logrotate
是一個非常流行的用于管理日志文件的工具,它可以自動完成日志文件的輪轉、壓縮、刪除舊日志等操作。
通常,logrotate
的 Nginx 配置文件位于 /etc/logrotate.d/nginx
或者你可以創建一個新的配置文件。下面是一個基本的配置示例,使用 cron 任務和 logrotate 工具定期分割日志:
# 創建 logrotate 配置文件 /etc/logrotate.d/nginx
/var/log/nginx/*.log {dailymissingokrotate 52compressdelaycompressnotifemptycreate 0640 www-data admsharedscriptspostrotateif [ -f /var/run/nginx.pid ]; thenkill -USR1 `cat /var/run/nginx.pid`fiendscript
}/var/log/nginx/*.log {daily # 每天輪轉一次missingok # 如果日志丟失,不報錯rotate 14 # 保留最近14個日志文件compress # 輪轉后壓縮日志文件delaycompress # 延遲壓縮,直到下一次輪轉notifempty # 如果日志為空,則不輪轉create 0640 www-data adm # 創建新日志文件的所有者和權限sharedscripts # 共享腳本執行(下面的postrotate腳本)postrotate[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`endscript
}
- daily: 設置日志每天輪轉。
- missingok: 如果日志文件不存在,不要給出錯誤信息。
- rotate 14: 只保留最近14個歸檔的日志文件,超過這個數量的老日志文件將被刪除。
- compress: 在輪轉后壓縮舊的日志文件。
- delaycompress: 推遲壓縮,直到下次輪轉。這樣,最新的歸檔文件不會被壓縮,直到下一次輪轉發生。
- notifempty: 如果日志文件為空,則不進行輪轉。
- create: 定義新日志文件的權限和所有者。
- postrotate/endscript: 在輪轉完成后執行的命令。這里的命令是向Nginx發送一個
USR1
信號,讓Nginx重新打開日志文件,以便開始寫入新的日志文件。
如何測試 logrotate
配置
你可以使用以下命令手動運行 logrotate
并查看其輸出,確保配置正確無誤:
logrotate -d /etc/logrotate.d/nginx
-d
參數表示調試模式,它會顯示 logrotate
將要做的事情但并不會真正執行任何操作。如果想要實際執行輪轉,可以去掉 -d
參數直接運行。
4.6、多項目之單個server
示例如下:
server {listen 80;server_name yourdomain.com;location /project1/ {alias /path/to/your/nginx/html/project1/;try_files $uri $uri/ /index.html;}location /project2/ {alias /path/to/your/nginx/html/project2/;try_files $uri $uri/ /index.html;}location /project3/ {alias /path/to/your/nginx/html/project3/;try_files $uri $uri/ /index.html;}
}
解釋
:
- alias:指定實際的文件系統路徑,注意這里使用的是
alias
而不是root
,因為對于location /projectX/
這樣的配置,alias
更加適合。它會將 URL 路徑中的/projectX/
部分替換為你指定的實際路徑。 - try_files:嘗試找到請求的文件或目錄。如果找不到,則回退到
index.html
。這對于單頁應用(SPA)特別有用,因為它允許路由處理未找到的文件。
4.7、多項目之多個server
每個 server 塊可以對應一個特定的域名或子域名,并指向不同的項目目錄。這種方式使得管理和擴展更加靈活,特別是當你有多個獨立的項目需要以不同的域名訪問時。
示例如下:
# Project 1 configuration
server {listen 80;server_name project1.yourdomain.com;root /path/to/your/nginx/html/project1;index index.html;location / {try_files $uri $uri/ /index.html;}
}# Project 2 configuration
server {listen 80;server_name project2.yourdomain.com;root /path/to/your/nginx/html/project2;index index.html;location / {try_files $uri $uri/ /index.html;}
}# Project 3 configuration
server {listen 80;server_name project3.yourdomain.com;root /path/to/your/nginx/html/project3;index index.html;location / {try_files $uri $uri/ /index.html;}
}
解釋
:
-
server_name:指定每個項目的域名。確保你已經正確配置了DNS解析,將這些子域名指向你的服務器IP地址。
-
其它:可以建立多個配置文件,然后使用
include
指令包含所有即可。
4.8、請求頭緩存
Cache-Control
是 HTTP 響應頭中的一個重要字段,用于定義請求和響應遵循的緩存機制。
它提供了多種指令來控制緩存的行為,包括但不限于瀏覽器緩存、代理服務器緩存等。
請求頭可以包含多個指令,不同指令之間使用逗號分隔。
緩存行為控制
- public:表示響應可以被任何緩存存儲,包括中間代理服務器在內的公共緩存。
- private:指示響應是針對單個用戶的,不應由共享緩存(如代理服務器)存儲。但允許客戶端(如瀏覽器)進行緩存。
- no-store:告知所有緩存不要存儲關于客戶端請求或服務器響應的任何內容。這對于包含敏感信息的響應特別有用。
- no-cache:表示在使用緩存副本之前必須先向源服務器驗證資源的有效性。注意,這并不意味著“不緩存”,而是要求每次都需要重新驗證。
過期時間控制
- max-age=:指定從現在開始到該資源被認為過期為止的最大秒數。例如,
max-age=3600
表示資源將在一小時后過期。 - s-maxage=:類似于
max-age
,但它僅適用于共享緩存(如代理服務器),并且優先級高于max-age
或Expires
頭。 - min-fresh=:要求返回的資源至少在未來給定秒數內仍然新鮮。
- max-stale[=]:指示客戶端愿意接受已過期的響應,可選參數指定了客戶端愿意接受的最大過期時間。
其他指令
- must-revalidate:一旦資源過期,在再次使用前必須先向源服務器驗證其有效性,不允許使用過期的數據。
- proxy-revalidate:與
must-revalidate
類似,但是僅對共享緩存有效。 - immutable:表示資源的內容不會隨時間變化,因此如果已經緩存了該資源,則無需重新驗證其有效性。這通常用于靜態資源,如 CSS 和 JavaScript 文件。
4.9、下載文件配置
假如是/var/www/downloads
目錄(下載目錄配置),配置如下:
server {listen 80;server_name yourdomain.com;############## 1、使用 alias ##############location /downloads/ {alias /usr/share/nginx/html/files/;autoindex on; # 啟用目錄瀏覽autoindex_exact_size off; # 顯示文件大小時更易讀autoindex_localtime on; # 使用本地時間顯示文件日期# 設置適當的默認類型default_type application/octet-stream;# 匹配多種文件類型并設置為附件下載if ($request_filename ~* ^.*?\.(jpg|jpeg|png|gif|pdf|txt|json|zip|rar|7z|doc|docx|xls|xlsx|ppt|pptx)$) {# 可選: 添加 Content-Disposition 頭部,強制瀏覽器下載而不是嘗試顯示文件add_header Content-Disposition 'attachment';}}############## 2、使用 root ##############location /files/ {root /usr/share/nginx/html/;autoindex on; # 啟用目錄瀏覽autoindex_exact_size off; # 顯示文件大小時更易讀autoindex_localtime on; # 使用本地時間顯示文件日期default_type application/octet-stream; # 設置適當的默認類型# 匹配多種文件類型并設置為附件下載if ($request_filename ~* ^.*?\.(jpg|jpeg|png|gif|pdf|txt|json|zip|rar|7z|doc|docx|xls|xlsx|ppt|pptx)$) {# 可選: 添加 Content-Disposition 頭部,強制瀏覽器下載而不是嘗試顯示文件add_header Content-Disposition 'attachment';}}
}
- alias:指定實際的文件系統路徑。注意這里使用的是
alias
而不是root
。對于帶有斜杠結尾的location
(如/downloads/
),alias
更適合,因為它會替換掉location
匹配的部分。 - autoindex on:啟用目錄列表功能,允許用戶瀏覽目錄內容。如果你不希望公開目錄結構,則可以去掉這一行。
- default_type application/octet-stream:設定默認 MIME 類型為二進制流,這樣大多數瀏覽器會選擇下載而不是直接打開文件。
- add_header Content-Disposition ‘attachment’:強制瀏覽器總是提示下載文件,而不是試圖直接在瀏覽器中打開它們。這對于確保所有類型的文件都被下載而不是被渲染非常重要。
注意事項
- 權限控制:確保 Nginx 進程對
/var/www/downloads
目錄及其子目錄具有正確的讀取權限。 - 訪問限制:考慮是否需要對某些敏感文件進行額外的安全措施,比如 IP 白名單、HTTP 基本認證等。
- 文件驗證:如果允許用戶上傳文件到下載目錄,請務必檢查文件名和內容以防止惡意文件上傳導致的安全問題。
4.10、其它
- 精確匹配優先:確定唯一的路徑使用
=
- 靜態資源用
^~
:確保快速響應且不被其他規則干擾 - 動態內容用正則:復雜匹配需求使用
~
或~*
- 通用路徑普通前綴:不需要特殊處理的普通路徑
5、常見錯誤排查
錯誤現象 | 可能原因 | 解決方法 |
---|---|---|
nginx: [emerg] bind() to 0.0.0.0:80 failed | 端口被占用 | sudo lsof -i :80 查看占用進程并停止 |
配置修改后無生效 | 未執行 nginx -s reload | 執行重載命令 |
502 Bad Gateway | 后端服務器不可用 | 檢查后端服務狀態及 proxy_pass 配置 |
靜態文件 404 錯誤 | 文件權限或路徑問題 | chown -R www-data:www-data /var/www |
日志顯示 too many open files | 文件描述符限制過低 | 修改 /etc/security/limits.conf 增加限制 |
完畢。