/home/zmy/software/nginx /home/zmy/software/nginx/nginx-1.30.0 保留源码,方便后期升级或添加新的模块/home/zmy/software/nginx/install--with-http_ssl_module 开启 HTTPS# 环境准备 Debian/Ubuntu 系统(旧版本的系统需要安装 libpcre3-dev)
sudo apt-get update
sudo apt-get install -y build-essential libssl-dev libpcre2-dev zlib1g-dev
# 编译,安装
cd /home/zmy/software/nginx/nginx-1.30.0
./configure \
--prefix=/home/zmy/software/nginx/install \
--with-http_ssl_module \
--with-http_gzip_static_module
make
make install
# 更新
## 下载新版本
curl -O https://nginx.org/download/nginx-1.31.0.tar.gz
## 原编译参数
nginx -V
## 使用相同编译参数进行构建并编译
cd /home/zmy/software/nginx/nginx-1.30.0
./configure \
--prefix=/home/zmy/software/nginx/install \
--with-http_ssl_module \
--with-http_gzip_static_module
make
## 备份旧的二进制文件
cp /home/zmy/software/nginx/install/sbin/nginx /home/zmy/software/nginx/install/sbin/nginx-1.30.0
## 替换二进制文件
cp objs/nginx /home/zmy/software/nginx/install/sbin/nginx
# 生成自签名证书
mkdir -p /home/zmy/software/nginx/install/conf/ssl
cd /home/zmy/software/nginx/install/conf/ssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout nginx.key \
-out nginx.crt \
-subj "/C=CN/ST=Jiangsu/L=Nanjing/O=Test/CN=zmy-aliyun" \
-addext "subjectAltName=DNS:zmy-aliyun,DNS:localhost,IP:42.121.255.213,IP:127.0.0.1"
# 配置nginx
user zmy;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 443 ssl;
server_name localhost;
ssl_certificate ssl/nginx.crt;
ssl_certificate_key ssl/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
}
# 普通用户无法监听1024以下的端口,使用 setcap 赋予 nginx 二进制文件网络绑定能力
sudo setcap 'cap_net_bind_service=+ep' /home/zmy/software/nginx/install/sbin/nginx
# 如果依然无法监听1024以下端口,使用 root 运行,user 指令设置为 zmy
sudo /home/zmy/software/nginx/install/sbin/nginx
# 配置为服务 sudo 只让 cat 有了 root 权限去读,但后面的 > 写入文件 操作依然是以 zmy 身份尝试写入 /etc/...,而 zmy 没有权限写入该目录
sudo tee /etc/systemd/system/nginx.service > /dev/null <<EOF
[Unit]
Description=Nginx Service
Documentation=https://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/home/zmy/software/nginx/install/logs/nginx.pid
ExecStartPre=/home/zmy/software/nginx/install/sbin/nginx -t -c /home/zmy/software/nginx/install/conf/nginx.conf
ExecStart=/home/zmy/software/nginx/install/sbin/nginx -c /home/zmy/software/nginx/install/conf/nginx.conf
ExecStop=/home/zmy/software/nginx/install/sbin/nginx -s stop -c /home/zmy/software/nginx/install/conf/nginx.conf
ExecReload=/home/zmy/software/nginx/install/sbin/nginx -s reload -c /home/zmy/software/nginx/install/conf/nginx.conf
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
# 开机自启
sudo systemctl enable nginx
start nginx,Linux: nginxnginx -s stop(快速停止nginx) 或 nginx -s quit(完整有序的停止nginx)start nginx 开启nginx服务nginx -s stop 关闭nginx服务,快速停止nginx,可能并不保存相关信息nginx -s quit 关闭nginx服务,完整有序的停止nginx,并保存相关信息nginx -s reload 重载nginx服务,当你改变了nginx配置信息并需要重新载入这些配置时可以使用此命令重载nginxnginx -s reopen 重新打开日志文件命令nginx -vnginx -v 命令只是简单显示nginx的版本信息(nginx version)nginx -V 不但显示nginx的版本信息,而且还显示nginx的配置参数信息。nginx -c </path/to/config> 此命令参数指定一个新的nginx配置文件来替换默认的nginx配置文件,如果你不确定新的nginx配置文件语法是否正确,可以通过 nginx -t 参数来测试,-t 参数代表不运行配置文件,而仅仅只是测试配置文件,即 nginx -t -c </path/to/config>nginx -T 查看当前 Nginx 最终的配置使用正则表达式时,proxy_pass 中不可携带 uri (端口后的那部分路径)
taskkill /f /t /im nginx.exenetstat -aontasklist | find /i "nginx.exe" || exittaskkill /im nginx.exe /f# nginx.conf 主配置文件结构
main上下文 # 全局配置
├── events上下文 # 事件模型配置
├── http上下文 # HTTP服务配置
│ ├── server上下文 # 虚拟主机配置
│ │ ├── location上下文 # URL匹配配置
│ │ └── location上下文
│ └── upstream上下文 # 负载均衡配置
└── stream上下文 # TCP/UDP代理配置
# 指令(指令名) 参数(值);
# ↓ ↓ ↓
error_log /var/log/nginx/error.log info;
# 指令 参数1 参数2
# 上下文指令(开启一个配置块)
events {
# 块内指令
worker_connections 1024;
}
user USERNAME [GROUP] 指定运行 Nginx 的 woker 子进程的属主和属组,其中组可以不指定。worker_rlimit_nofile 20480; 指定 worker 子进程可以打开的最大文件句柄数。worker_rlimit_core 指定 worker 子进程异常终止后的 core 文件,用于记录分析问题worker_rlimit_core 50M; # 存放大小限制working_directory /opt/nginx/tmp; # 存放目录worker_cpu_affinity 将每个 worker 子进程与我们的 cpu 物理核心绑定。worker_cpu_affinity 0001 0010 0100 1000; # 4个物理核心,4个worker子进程worker_priority 指定 worker 子进程的 nice 值,以调整运行 Nginx 的优先级,通常设定为负值,以优先调用 Nginx 。worker_priority -10; # 120-10=110,110就是最终的优先级worker_shutdown_timeout 5s; 指定 worker 子进程优雅退出时的超时时间。daemon off; 指定 Nginx 的运行方式,前台还是后台,默认 on,前台用于调试,后台用于生产。error_log /var/log/nginx/error.log warn; 错误日志路径和级别:debug|info|notice|warn|error|crit|alert|emergpid /var/run/nginx.pid; 记录pidworker_processes auto; worker进程数use select|poll|kqueue|epoll|/dev/poll|eventport; Nginx 使用何种事件驱动模型。不推荐配置它,让nginx自己选择worker_connectionsworker 1024; 子进程能够处理的最大并发连接数。accept_mutex on; 是否打开负载均衡互斥锁。默认是off关闭的,推荐打开events {
# 关键参数
worker_connections 1024; # 最大连接数 = worker_processes * worker_connections
# Linux优化
use epoll; # epoll(Linux)、kqueue(BSD)、select
accept_mutex on; # 避免"惊群"问题
accept_mutex_delay 500ms;
# 高性能配置
multi_accept on; # 一次接受所有新连接
epoll_events 512; # epoll事件数
}
http {
include /etc/nginx/mime.types; # MIME类型映射
include /etc/nginx/conf.d/xxx.conf; # 包含自定义配置
default_type application/octet-stream; # 默认类型
charset utf-8; # 设置UTF-8编码
# 定义日志格式和名字
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; # 优化数据包发送
tcp_nodelay on; # 禁用Nagle算法
keepalive_timeout 65; # 长连接超时
types_hash_max_size 2048;
# 缓冲区优化
client_body_buffer_size 128k;
client_max_body_size 10m; # 最大上传文件大小
client_header_buffer_size 1k; # 请求头缓冲区大小
large_client_header_buffers 4 8k; # 4个8k缓冲区
# 超时设置
client_body_timeout 10s;
client_header_timeout 10s;
send_timeout 10s;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1k;
gzip_types text/plain text/css application/json application/javascript; # 压缩类型
gzip_comp_level 6; # 1-9,数字越大压缩率越高
gzip_min_length 1k; # 只压缩大于1KB的文件
gzip_vary on; # 添加Vary: Accept-Encoding头
# 缓存设置
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
server_name www.nginx.com; 指定虚拟主机域名或IP,四种写法server_name www.nginx.com;server_name *.nginx.com;server_name www.nginx.*;server_name ~^www\.nginx\.*$;root path; 指定静态资源目录位置,它可以写在 http 、 server 、 location 等配置中。location /image {
root /opt/nginx/static;
}
# 当用户访问 www.test.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
alias 它也是指定静态资源目录位置,它只能写在 location 中location /image {
alias /opt/nginx/static/image/;
}
# 当用户访问 www.test.com/image/1.png 时,实际在服务器找的路径是 /opt/nginx/static/image/1.png
location ~ ^/images/(.*\.(gif|jpg|jpeg))$ {
alias /var/www/images/$1; # 可以
# root /var/www/images; # 不行!
}
[ = | ~ | ~* | !~ | !~* | @ ] uri {...}= 表示精确匹配,如果找到,立即停止搜索并立即处理此请求。~ 表示执行一个正则匹配,区分大小写匹配~* 表示执行一个正则匹配,不区分大小写匹配!~ 区分大小写不匹配!~* 不区分大小写不匹配^~ 使用前缀匹配,禁止正则,即表示只匹配普通字符(空格)。^ 表示 “非”,即不查询正则表达式。如果匹配成功,则不再匹配其他 location。@ 指定一个命名的 location,一般只用于内部重定向请求。例如 error_page, try_files/ < [不加] < [~/~*] < [^~] < [=],按优先级顺序匹配,不是按配置文件顺序,正则匹配按配置文件顺序,第一个匹配的生效,普通前缀匹配按最长路径原则location /test {
...
}
location /test/ {
...
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d; # 长期缓存
add_header Cache-Control "public, immutable";
# 启用缓存
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
# 禁用访问日志,优化性能
access_log off;
}
# ❌ 过多正则匹配影响性能
location ~* \.(jpg|jpeg|png|gif|ico|css|js|txt|xml|json|html|htm|php|pdf)$ {
# 这个正则包含很多扩展名,每次请求都要匹配
}
# ✅ 优化:将静态文件分开
location ~* \.(css|js)$ {
expires 1h;
}
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 30d;
}
index index.html index.htm index.php; # 默认首页try_files $uri $uri/ /index.html; # 尝试静态文件,不存在则返回index.htmlinternal; # 重要:只能内部访问return 停止处理请求,直接返回响应码或重定向到其他 URL;执行 return 指令后,location 中后续指令将不会被执行。return 404; # 直接返回状态码
return 404 "pages not found"; # 返回状态码 + 一段文本
return 302 /bbs ; # 返回状态码 + 重定向地址
return https://www.baidu.com; # 返回重定向地址
return 200 '{"status": "ok", "message": "Service is running"}'; # 返回json
return 200 '<!DOCTYPE html><html><body><h1>Custom HTML</h1></body></html>'; # 返回html
rewrite 根据指定正则表达式匹配规则,重写 URL 。上下文:server、location、if
rewrite 正则表达式 要替换的内容 [flag];rewirte /images/(.*\.jpg)$ /pic/$1; $1 是前面括号 (.*\.jpg) 的反向引用flag 可选值的含义:last 重写后的 URL 发起新请求,再次进入 server 段,重试 location 的中的匹配;默认值break 直接使用重写后的 URL ,不再匹配其它 location 中语句;redirect 返回302临时重定向;permanent 返回301永久重定向;if (condition) {...} 上下文:server、location
$variable 仅为变量时,值为空或以0开头字符串都会被当做 false 处理;= 或 != 相等或不等;~ 正则匹配;! ~ 非正则匹配;~* 正则匹配,不区分大小写;-f 或 ! -f 检测文件存在或不存在;-d 或 ! -d 检测目录存在或不存在;-e 或 ! -e 检测文件、目录、符号链接等存在或不存在;-x 或 ! -x 检测文件可以执行或不可执行;autoindex 用户最终请求以 / 结尾时,列出目录结构,可以用于快速搭建静态资源下载网站。
server {
listen 80;
server_name fe.lion-test.club;
location /download/ {
root /opt/source;
autoindex on; # 打开 autoindex,,可选参数有 on | off
autoindex_exact_size on; # 修改为off,以KB、MB、GB显示文件大小,默认为on,以bytes显示出⽂件的确切⼤⼩
autoindex_format html; # 以html的方式进行格式化,可选参数有 html | json | xml
autoindex_localtime off; # 显示的⽂件时间为⽂件的服务器时间。默认为off,显示的⽂件时间为GMT时间
}
}
upstream name {} 上下文:httphash key 哈希负载均衡算法;hash $request_uri 表示使用 request_uri 变量作为 hash 的 key 值,只要访问的 URI 保持不变,就会一直分发给同一台服务器。ip_hash 依据 IP 进行哈希计算的负载均衡算法;只要 ip 地址不变就永远分配到同一台主机。它可以有效解决后台服务器 session 保持的问题least_conn 最少连接数负载均衡算法;各个 worker 子进程通过读取共享 zoon 内存的数据,来获取后端服务器的信息least_time 最短响应时间负载均衡算法;random 随机负载均衡算法;server id [parameters] 上游服务器地址, parameters 可选值:weight=number 权重值,默认为1;max_conns=number 上游服务器的最大并发连接数;fail_timeout=time 服务器不可用的判定时间;max_fails=numer 服务器不可用的检查次数;backup 备份服务器,仅当其他服务器都不可用时才会启用;down 标记服务器长期不可用,离线维护zone name 10M 定义共享内存名字和大小,用于跨 worker 子进程;keepalive 16 限制每个 worker 子进程与上游服务器空闲长连接的最大数量。keepalive_requests 100 一个长连接最多请求 HTTP 的个数;keepalive_timeout 60s 空闲情形下,一个长连接的超时时长;proxy_pass url 上下文:location、if、limit_except# API代理
location /api/ {
proxy_pass http://backend/; # 注意结尾的/
# 头部传递
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_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# WebSocket支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
proxy_pass 主机+端口 这种类型,将访问地址直接加到后面,即主机+端口+访问路径proxy_pass 主机+端口+ 访问路径(包括根路径),需要去掉location后面的匹配路径,然后将剩余的添加到proxy_pass后面。# 假设访问路径为 http://192.168.1.9/proxy/test.html
# 主机+端口类型
location /proxy {
proxy_pass http://127.0.0.1:81;
}
# 会被代理到http://127.0.0.1:81/proxy/test.html 这个url。
# 主机+端口+路径类型
location /proxy {
proxy_pass http://127.0.0.1:81/fly/;
}
# 会被代理到http://127.0.0.1:81/fly//test.html 这个url。 请注意这里的双斜杠。
location /proxy/ {
proxy_pass http://127.0.0.1:81/fly/;
}
# 代理到http://127.0.0.1:81/fly/test.html,把 test.html 拼到后面
location /proxy {
proxy_pass http://127.0.0.1:81/fly;
}
# 代理到http://127.0.0.1:81/fly/test.html,把 /test.html 拼到后面
proxy_cache zoon|off zoon 是共享内存名称,默认值 off,上下文:http、server、locationproxy_cache_path path [level=levels] 默认值 offproxy_cache_ke key 设置缓存文件的 key。proxy_cache_valid [code] time 配置什么状态码可以被缓存以及时间proxy_no_cache string; 设置不保存到缓存的条件,字符串中至少一个不为空且不等于0proxy_cache_bypass string 定义条件,在该条件下将不会从缓存中获取响应upstream_cache_status 变量,存储了缓存是否被命中的信息,设置在响应头信息中,调试时有用MISS: 未命中缓存HIT: 命中缓存EXPIRED: 缓存过期STALE: 命中了陈旧缓存REVALIDDATED: Nginx验证陈旧缓存依然有效UPDATING: 内容陈旧,但正在更新BYPASS: X响应从原始服务器获取server {
listen 443 ssl http2 default_server; # SSL 访问端口号为 443
server_name lion.club; # 填写绑定证书的域名(这里是随便写的)
ssl_certificate /etc/nginx/https/lion.club_bundle.crt; # 证书地址
ssl_certificate_key /etc/nginx/https/lion.club.key; # 私钥地址
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # 支持ssl协议版本,默认为后三个,主流版本是[TLSv1.2]
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; # # 加密算法
ssl_prefer_server_ciphers on; # 优先服务器选择的加密套件
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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 "strict-origin-when-cross-origin" always;
# 内容安全策略
add_header Content-Security-Policy "default-src 'self'" always;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
# 开启详细日志
error_log /var/log/nginx/error.log debug;
# 调试特定客户端
server {
set $debug 0;
if ($remote_addr = "192.168.1.100") {
set $debug 1;
}
access_log /var/log/nginx/debug.log combined if=$debug;
}
# 验证配置文件
nginx -t
nginx -T # 打印完整配置

| 变量名 | 含义 |
|---|---|
| request | 完整请求行:GET /api HTTP/1.1 |
| server_protocol | 服务器协议:HTTP/1.0、HTTP/1.1 |
| uri | 请求的 URI,只有路径,不包含参数 |
| request_uri | 请求的 URI,包含参数 |
| scheme | 协议名,http 或 https |
| request_method | 请求方法,GET、POST、PUT、DELETE等 |
| args | 查询参数字符串:id=1&name=test |
| query_string | 与 args 相同 |
| arg_参数名 | 获取特定参数值 |
| is_args | URI 中是否有参数,有的话返回 "?",否则返回空 |
| host | 请求信息中的 Host,如果请求中没有 Host 行,则在请求头中找,最后使用 nginx 中设置的 server_name |
| 变量名 | 含义 |
|---|---|
| http_* | 所有请求头,如$http_user_agent、$http_host |
| http_user_agent | 用户代理:Mozilla/5.0... |
| http_referer | 来源页面URL, 从哪些连接过来的请求 |
| http_host | 请求的Host头 |
| http_cookie | Cookie头 |
| http_accept | Accept头 |
| http_accept_language | Accept-Language头 |
| http_accept_encoding | Accept-Encoding头 |
| http_content_type | Content-Type头 |
| http_content_length | Content-Length头 |
| http_authorization | Authorization头 |
| http_via | 每经过一层代理服务器,都会添加相应的信息 |
| 变量名 | 含义 |
|---|---|
| remote_addr | 客户端 IP 地址 |
| remote_port | 客户端端口 |
| remote_user | Basic认证的用户名 |
| server_addr | 服务端 IP 地址 |
| server_port | 服务端端口 |
| binary_remote_addr | 二进制格式的客户端 IP 地址 |
| connection | TCP 连接的序号,递增 |
| connection_request | TCP 连接当前的请求数量 |
| https | 是否开启了 https,是返回 on,否则返回空 |
| 变量名 | 含义 |
|---|---|
| proxy_protocol_addr | PROXY协议传递的客户端IP |
| proxy_protocol_port | PROXY协议传递的客户端端口 |
| proxy_add_x_forwarded_for | 追加IP到X-Forwarded-For |
| proxy_host | proxy_pass指定的主机 |
| proxy_port | proxy_pass指定的端口 |
| 变量名 | 含义 |
|---|---|
| status | 响应状态码:200、404、500等 |
| body_bytes_sent | 发送给客户端的body字节数 |
| bytes_sent | 发送的总字节数 |
| senthttp* | 响应头,如$sent_http_content_type |
| sent_http_content_type | 响应Content-Type |
| sent_http_content_length | 响应Content-Length |
| sent_http_cache_control | 响应Cache-Control |
| request_length | 请求长度(包括请求行、头、体) |
| request_time | 请求处理时间(秒,毫秒精度) |
| upstream_response_time | 上游服务器响应时间 |
| upstream_status | 上游服务器状态码 |
| upstream_addr | 上游服务器地址 |
| upstreamhttp* | 上游服务器的响应头 |
| request_filename | 磁盘文件系统等待访问文件的完整路径 |
| 变量名 | 含义 |
|---|---|
| time_iso8601 | ISO 8601格式:2023-12-20T10:30:00+08:00 |
| time_local | 本地时间格式:20/Dec/2023:10:30:00 +0800 |
| msec | 当前时间戳,毫秒:1703039400.123 |
| request_time | 请求处理时间 |
| upstream_response_time | 上游响应时间 |
| upstream_connect_time | 上游连接时间 |
| upstream_header_time | 上游接收头时间 |
| 变量名 | 含义 |
|---|---|
| document_root | 当前请求的root/alias目录 |
| realpath_root | 规范化后的$document_root |
| document_uri | 同$uri |
| request_filename | 请求的文件路径 |
| fastcgi_script_name | FastCGI脚本名 |
| 变量名 | 含义 |
|---|---|
| arg_* | 查询参数,如arg_name |
| cookie_* | Cookie值,如$cookie_session |
| http_* | 请求头 |
| senthttp* | 响应头 |
| 变量名 | 含义 |
|---|---|
| ssl_protocol | SSL/TLS协议版本:TLSv1.2 |
| ssl_cipher | SSL加密套件 |
| ssl_client_s_dn | 客户端证书主题 |
| ssl_client_i_dn | 客户端证书颁发者 |
| ssl_client_verify | 客户端证书验证结果 |
| ssl_session_id | SSL会话ID |
| ssl_server_name | SNI服务器名称 |
| 变量名 | 含义 |
|---|---|
| document_root | 由 URI 和 root/alias 规则生成的文件夹路径 |
| limit_rate | 返回响应时的速度上限值 |