Nginx配置文件介绍和基本使用
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 增加限制 |
完毕。