Nginx 配置 1
约 9908 字大约 33 分钟
2025-10-26
配置文件实例
#定义 nginx 运行的用户和用户组
user www www;
#nginx 进程数,建议设置为等于 CPU 总核心数。
worker_processes 8;
#nginx 默认没有开启利用多核 CPU, 通过增加 worker_cpu_affinity 配置参数来充分利用多核 CPU 以下是 8 核的配置参数
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;
#进程文件
pid /var/run/nginx.pid;
#一个 nginx 进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值 ulimit -n)与 nginx 进程数相除,但是 nginx 分配请求并不均匀,所以建议与 ulimit -n 的值保持一致。
worker_rlimit_nofile 65535;
#工作模式与连接数上限
events
{
#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll 模型是 Linux 2.6 以上版本内核中的高性能网络 I/O 模型,如果跑在 FreeBSD 上面,就用 kqueue 模型。
#epoll 是多路复用 IO(I/O Multiplexing) 中的一种方式,但是仅用于 linux2.6 以上内核,可以大大提高 nginx 的性能
use epoll;
############################################################################
#单个后台 worker process 进程的最大并发链接数
#事件模块指令,定义 nginx 每个进程最大连接数,默认 1024。最大客户连接数由 worker_processes 和 worker_connections 决定
#即 max_client=worker_processes*worker_connections, 在作为反向代理时:max_client=worker_processes*worker_connections / 4
worker_connections 65535;
############################################################################
}
#设定 http 服务器
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型
#charset utf-8; #默认编码
server_names_hash_bucket_size 128; #服务器名字的 hash 表大小
client_header_buffer_size 32k; #上传文件大小限制
large_client_header_buffers 4 64k; #设定请求缓
client_max_body_size 8m; #设定请求缓
sendfile on; #开启高效文件传输模式,sendfile 指令指定 nginx 是否调用 sendfile 函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成 off。
autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; #防止网络阻塞
tcp_nodelay on; #防止网络阻塞
##连接客户端超时时间各种参数设置##
keepalive_timeout 120; #单位是秒,客户端连接时时间,超时之后服务器端自动关闭该连接 如果 nginx 守护进程在这个等待的时间里,一直没有收到浏览发过来 http 请求,则关闭这个 http 连接
client_header_timeout 10; #客户端请求头的超时时间
client_body_timeout 10; #客户端请求主体超时时间
reset_timedout_connection on; #告诉 nginx 关闭不响应的客户端连接。这将会释放那个客户端所占有的内存空间
send_timeout 10; #客户端响应超时时间,在两次客户端读取操作之间。如果在这段时间内,客户端没有读取任何数据,nginx 就会关闭连接
################################
#FastCGI 相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
###作为代理缓存服务器设置#######
###先写到 temp 再移动到 cache
#proxy_cache_path /var/tmp/nginx/proxy_cache levels=1:2 keys_zone=cache_one:512m inactive=10m max_size=64m;
###以上 proxy_temp 和 proxy_cache 需要在同一个分区中
###levels=1:2 表示缓存级别,表示缓存目录的第一级目录是 1 个字符,第二级目录是 2 个字符 keys_zone=cache_one:128m 缓存空间起名为 cache_one 大小为 512m
###max_size=64m 表示单个文件超过 128m 就不缓存了 inactive=10m 表示缓存的数据,10 分钟内没有被访问过就删除
#########end####################
#####对传输文件压缩###########
#gzip 模块设置
gzip on; #开启 gzip 压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认 1.1,前端如果是 squid2.5 请使用 1.0)
gzip_comp_level 2; #压缩等级,gzip 压缩比,1 为最小,处理最快;9 为压缩比最大,处理最慢,传输速度最快,也最消耗 CPU;
gzip_types text/plain application/x-javascript text/css application/xml;
#压缩类型,默认就已经包含 text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个 warn。
gzip_vary on;
##############################
#limit_zone crawler $binary_remote_addr 10m; #开启限制 IP 连接数的时候需要使用
upstream blog.ha97.com {
#upstream 的负载均衡,weight 是权重,可以根据机器配置定义权重。weigth 参数表示权值,权值越高被分配到的几率越大。
server 192.168.80.121:80 weight=3;
server 192.168.80.122:80 weight=2;
server 192.168.80.123:80 weight=3;
}
#虚拟主机的配置
server {
#监听端口
listen 80;
#############https##################
#listen 443 ssl;
#ssl_certificate /opt/https/xxxxxx.crt;
#ssl_certificate_key /opt/https/xxxxxx.key;
#ssl_protocols SSLv3 TLSv1;
#ssl_ciphers HIGH:!ADH:!EXPORT57:RC4+RSA:+MEDIUM;
#ssl_prefer_server_ciphers on;
#ssl_session_cache shared:SSL:2m;
#ssl_session_timeout 5m;
####################################end
#域名可以有多个,用空格隔开
server_name www.ha97.com ha97.com;
index index.html index.htm index.php;
root /data/www/ha97;
location ~ .*.(php|php5)?$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
#图片缓存时间设置
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 10d;
}
#JS 和 CSS 缓存时间设置
location ~ .*.(js|css)?$ {
expires 1h;
}
#日志格式设定
log_format access '$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/ha97access.log access;
#对 "/" 启用反向代理
location / {
proxy_pass http://127.0.0.1:88;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
#后端的 Web 服务器可以通过 X-Forwarded-For 获取用户真实 IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#以下是一些反向代理的配置,可选。
proxy_set_header Host $host;
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
##代理设置 以下设置是 nginx 和后端服务器之间通讯的设置##
proxy_connect_timeout 90; #nginx 跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffering on; #该指令开启从后端被代理服务器的响应内容缓冲 此参数开启后 proxy_buffers 和 proxy_busy_buffers_size 参数才会起作用
proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers 缓冲区,网页平均在 32k 以下的设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_max_temp_file_size 2048m; #默认 1024m, 该指令用于设置当网页内容大于 proxy_buffers 时,临时文件大小的最大值。如果文件大于这个值,它将从 upstream 服务器同步地传递请求,而不是缓冲到磁盘
proxy_temp_file_write_size 512k; 这是当被代理服务器的响应过大时 nginx 一次性写入临时文件的数据量。
proxy_temp_path /var/tmp/nginx/proxy_temp; ##定义缓冲存储目录,之前必须要先手动创建此目录
proxy_headers_hash_max_size 51200;
proxy_headers_hash_bucket_size 6400;
#######################################################
}
#设定查看 nginx 状态的地址
location /nginxStatus {
stub_status on;
access_log on;
auth_basic "nginxStatus";
auth_basic_user_file conf/htpasswd;
#htpasswd 文件的内容可以用 apache 提供的 htpasswd 工具来产生。
}
#本地动静分离反向代理配置
#所有 jsp 的页面均交由 tomcat 或 resin 处理
location ~ .(jsp|jspx|do)?$ {
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_pass http://127.0.0.1:8080;
}
#所有静态文件由 nginx 直接读取不经过 tomcat 或 resin
location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{ expires 15d; }
location ~ .*.(js|css)?$
{ expires 1h; }
}
}基本规则
随着 Nginx 配置的增长,您有必要组织、管理配置内容。
使用 include 指令可将常用服务器配置移动到单独的文件中,并将特定代码附加到全局配置,上下文等中。
/etc/nginx/
├── nginx.conf # 主入口文件,保持极简
├── conf.d/ # 动态加载的配置片段(谨慎使用)
├── sites-available/ # 所有可用的虚拟主机配置(符号链接源)
├── sites-enabled/ # 已启用的虚拟主机(符号链接到 available)
│
├── master/ # 核心全局配置库 (您的核心思想)
│ ├── 00-global/ # 最基础的、被最先加载的配置
│ │ ├── nginx.conf.part # 主配置中 http 块内的内容
│ │ ├── security.conf # 基础安全头、策略
│ │ └── performance.conf # 全局性能参数 (sendfile, buffer等)
│ │
│ ├── 10-acls/ # 访问控制与变量定义
│ │ ├── geolocation.conf # 国家/地区代码映射
│ │ ├── bots.conf # 爬虫、扫描器 User-Agent 黑名单
│ │ ├── whitelist.conf # IP/网段白名单 (如管理后台)
│ │ └── map.conf # 各种 map 指令 (如重定向映射)
│ │
│ ├── 20-listen/ # 监听指令与 SSL 配置
│ │ ├── http.conf # 80 端口通用配置
│ │ ├── https.conf # 443 端口通用 SSL 配置 (协议、加密套件)
│ │ └── ssl/ # 域名 SSL 证书配置
│ │ ├── example.com.conf
│ │ └── app.example.com.conf
│ │
│ ├── 30-upstreams/ # 后端服务/上游定义
│ │ ├── backend_php.conf
│ │ ├── backend_nodejs.conf
│ │ └── backend_python.conf
│ │
│ ├── 40-servers/ # 虚拟主机配置块 (server {})
│ │ ├── templates/ # 配置模板
│ │ │ ├── php_app.conf.template
│ │ │ ├── static_site.conf.template
│ │ │ └── reverse_proxy.conf.template
│ │ └── enabled/ # 实际启用的 server 配置
│ │ ├── example.com.conf
│ │ └── app.example.com.conf
│ │
│ ├── 50-locations/ # 可复用的 location 片段
│ │ ├── location_php.conf
│ │ ├── location_static.conf
│ │ └── location_proxy.conf
│ │
│ └── 60-logging/ # 日志格式与配置
│ ├── log_formats.conf
│ └── error_pages.conf
│
├── modules/ # 动态模块配置
├── snippets/ # 通用的、简短的配置片段 (Nginx 社区常用名)
├── html/ # 默认静态文件根目录
│ ├── 50x.html # 自定义错误页面
│ └── maintenance.html # 维护页面
│
├── certs/ -> /etc/ssl/private/nginx/ # 证书目录 (符号链接)
└── scripts/ # 维护脚本
├── deploy-cert.sh
├── enable-site.sh
└── check-config.sh主配置文件 (nginx.conf)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
# 动态模块加载
load_module modules/ngx_http_geoip_module.so;
events {
worker_connections 1024;
use epoll;
}
http {
# 按顺序加载核心配置库
include /etc/nginx/master/00-global/nginx.conf.part;
include /etc/nginx/master/10-acls/*.conf;
include /etc/nginx/master/20-listen/*.conf;
include /etc/nginx/master/30-upstreams/*.conf;
include /etc/nginx/master/60-logging/*.conf;
# 加载所有启用的虚拟主机配置
include /etc/nginx/master/40-servers/enabled/*.conf;
# 兼容性:可包含传统位置的配置
include /etc/nginx/conf.d/*.conf;
}虚拟主机配置 (master/40-servers/enabled/example.com.conf)
# 现代、模块化的 Server 配置示例
server {
# 1. 包含监听和SSL配置 (IP:Port + TLS)
include /etc/nginx/master/20-listen/ssl/example.com.conf;
server_name example.com www.example.com;
# 2. 包含全局助手 (安全头、错误页面、基础设置)
include /etc/nginx/master/00-global/security.conf;
include /etc/nginx/master/60-logging/error_pages.conf;
# 3. 根路径和日志设置
root /var/www/example.com/public;
access_log /var/log/nginx/example.com.access.log main;
error_log /var/log/nginx/example.com.error.log;
# 4. 包含可复用的 Location 块
include /etc/nginx/master/50-locations/location_static.conf;
include /etc/nginx/master/50-locations/location_php.conf;
# 5. 特定于此站点的 Location 块
location /api/ {
include /etc/nginx/master/50-locations/location_proxy.conf;
proxy_pass http://backend_api;
}
location /admin/ {
include /etc/nginx/master/10-acls/whitelist.conf; # 应用IP白名单
deny all; # 默认拒绝所有
try_files $uri $uri/ /index.php?$query_string;
}
# 6. 最终兜底规则
location / {
try_files $uri $uri/ /index.html;
}
}SSL 配置片段 (master/20-listen/ssl/example.com.conf)
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
# 包含现代 SSL 安全配置
include /etc/nginx/master/20-listen/https.conf;最佳实践:
版本控制
- 将整个
/etc/nginx/目录(除了大文件证书和日志)纳入 Git 版本控制。 - 使用
.gitignore忽略sites-enabled/,conf.d/,certs/(仅保留模板或样例)。
基础设施即代码 (IaC)
- 使用 Ansible, Chef, Puppet 或 SaltStack 来自动化此配置结构的部署和同步。
配置验证与自动化
scripts/check-config.sh:
#!/bin/bash
echo "Checking Nginx configuration..."
if ! nginx -t; then
echo "ERROR: Nginx configuration test failed!"
exit 1
fi
echo "Configuration is valid."scripts/enable-site.sh:
#!/bin/bash
SITE=$1
ln -sf ../sites-available/$SITE.conf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx安全强化
- 在
master/00-global/security.conf中集中设置安全头 (如 CSP, HSTS)。 - 使用
master/10-acls/bots.conf管理恶意爬虫。 - 定期通过
ssl-config.mozilla.org更新master/20-listen/https.conf。
环境管理
- 使用模板和变量(如果使用 OpenResty 或 Nginx+)来管理不同环境(开发、预生产、生产)的差异。
- 或者,在 CI/CD 流水线中,使用工具(如
envsubst)在部署时渲染配置文件。
文档
- 在每个目录下放置
README.md,说明该目录下配置的用途和依赖关系。 - 在复杂的配置文件中使用清晰的注释,说明为何这样配置(而不仅仅是做了什么)。
重加载 Nginx 配置
systemctl reload nginx说明:现代 Linux 系统(Systemd)的标准服务管理命令
适用系统:CentOS 7+、Ubuntu 16.04+、Debian 8+
优点:标准化、有状态反馈、与系统服务管理集成
service nginx reload说明:传统的服务管理命令,通常是 Systemd 或 SysVinit 的包装器
适用系统:多数 Linux 发行版(向后兼容)
实际效果:通常转发到 systemctl reload nginx
/etc/init.d/nginx reload说明:SysVinit 系统的直接服务脚本调用
适用系统:较老的 Linux 系统(CentOS 6、Debian 7 等)
现代系统:通常作为兼容层存在
/usr/sbin/nginx -s reload说明:Nginx 二进制文件的直接信号命令
原理:向 Nginx master 进程发送 reload 信号
等效命令:nginx -s reload
kill -HUP $(cat /var/run/nginx.pid)
## 或
kill -HUP $(pgrep -f "nginx: master")说明:直接向 Nginx master 进程发送 HUP (Hang UP) 信号
原理:-s reload 的内部实现就是发送 HUP 信号
注意:需要确保获取到正确的 master 进程 PID
/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload完整路径带参数的重加载
说明:指定全局参数并执行重加载(不常见)
适用场景:特殊调试或非标准安装环境
工作原理
所有重加载方法的核心原理都是向 Nginx master 进程 发送信号,触发以下流程:
- 检查配置语法:
nginx -t的等效验证 - 启动新 worker:用新配置启动新的 worker 进程
- 优雅关闭旧 worker:通知旧 worker 处理完当前请求后退出
- 平滑过渡:实现零停机时间的配置更新
现代最佳实践推荐
# 1. 先测试配置语法
sudo nginx -t
# 2. 执行重加载(推荐)
sudo systemctl reload nginx
# 3. 验证服务状态
sudo systemctl status nginx备用方案(调试环境)
# 直接使用 nginx 命令
sudo nginx -s reload
# 或指定配置文件
sudo nginx -c /etc/nginx/nginx.conf -s reload完整的安全重加载流程
#!/bin/bash
echo "=== Nginx 配置重加载流程 ==="
# 1. 备份当前配置
echo "1. 备份配置..."
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup.$(date +%Y%m%d_%H%M%S)
# 2. 语法检查
echo "2. 检查配置语法..."
if ! sudo nginx -t; then
echo "❌ 配置语法错误,请检查配置文件"
exit 1
fi
# 3. 重加载配置
echo "3. 重加载 Nginx..."
if sudo systemctl reload nginx; then
echo "✅ Nginx 重加载成功"
else
echo "❌ 重加载失败,恢复备份..."
sudo cp /etc/nginx/nginx.conf.backup.* /etc/nginx/nginx.conf
sudo systemctl reload nginx
fi
# 4. 验证服务状态
echo "4. 检查服务状态..."
sudo systemctl status nginx --no-pager -l信号对比
| 信号 | 命令等价 | 作用 |
|---|---|---|
HUP | reload | 重加载配置,平滑重启 |
QUIT | quit | 优雅关闭 |
TERM, INT | stop | 立即停止 |
USR1 | reopen | 重新打开日志文件 |
USR2 | - | 升级可执行文件 |
WINCH | - | 优雅关闭 worker 进程 |
注意事项
- 权限要求:通常需要
sudo或root权限 - 配置验证:重加载前务必执行
nginx -t检查语法 - 工作进程:只影响 worker 进程,master 进程保持运行
- 连接保持:现有连接不会中断,实现平滑重载
- 路径差异:Nginx 二进制路径可能不同(
which nginx查看)
故障排查
如果重加载失败:
# 查看错误详情
sudo nginx -t
sudo journalctl -u nginx -f
sudo tail -f /var/log/nginx/error.log真正的"无感"更新条件
#!/bin/bash
set -e # 遇到错误立即退出
echo "=== Nginx 配置重加载流程 ==="
BACKUP_DIR="/etc/nginx/backup/$(date +%Y%m%d_%H%M%S)"
CURRENT_RESTORE_BACKUP=""
# 1. 完整备份配置
echo "1. 备份完整配置..."
sudo mkdir -p "$BACKUP_DIR"
sudo cp -a /etc/nginx/* "$BACKUP_DIR/" 2>/dev/null || true
echo " 配置已备份到: $BACKUP_DIR"
CURRENT_RESTORE_BACKUP="$BACKUP_DIR"
# 2. 详细语法检查
echo "2. 检查配置语法..."
if ! sudo nginx -t 2>&1; then
echo "❌ 配置语法错误,请检查以下问题:"
echo " 1. 括号是否匹配"
echo " 2. 指令语法是否正确"
echo " 3. 文件路径是否存在"
exit 1
fi
# 3. 预检查:测试关键功能
echo "3. 执行预检查..."
# 检查关键服务是否可达(如果有代理配置)
if grep -q "proxy_pass" /etc/nginx/nginx.conf; then
echo " ⚠️ 检测到代理配置,请确保后端服务正常"
fi
# 4. 重加载配置
echo "4. 重加载 Nginx..."
if sudo systemctl reload nginx; then
echo "✅ Nginx 重加载成功"
# 5. 健康检查
echo "5. 执行健康检查..."
sleep 2 # 等待 worker 进程完全切换
# 检查 Nginx 是否正常响应
if curl -f -s -o /dev/null -w "%{http_code}" http://localhost/nginx_status > /dev/null 2>&1; then
echo "✅ 服务健康检查通过"
else
echo "⚠️ 健康检查异常,但服务正在运行"
fi
else
echo "❌ 重加载失败,正在恢复备份..."
if [ -n "$CURRENT_RESTORE_BACKUP" ]; then
sudo cp -a "$CURRENT_RESTORE_BACKUP"/* /etc/nginx/
sudo systemctl reload nginx
echo "✅ 配置已恢复,服务已重启"
else
echo "❌ 无法恢复备份,请手动检查"
exit 1
fi
fi
# 6. 最终状态验证
echo "6. 检查服务状态..."
sudo systemctl status nginx --no-pager -l
# 7. 显示 worker 进程信息
echo "7. Worker 进程状态:"
sudo ps aux | grep "nginx: worker" | grep -v grep || echo " 无 worker 进程信息"新脚本的主要改进总结
备份机制全面增强
- 从单个文件备份 → 完整目录备份 (
cp -a /etc/nginx/*) - 创建结构化备份目录 (按时间戳组织)
- 备份路径记录 (
CURRENT_RESTORE_BACKUP变量)
错误处理更加健壮
set -e指令 - 遇到错误立即退出,避免后续问题- 备份恢复逻辑完善 - 确保能找到正确的备份文件
- 错误信息更详细 - 具体提示语法错误的可能原因
健康检查体系建立
- 预检查阶段 - 检测代理配置等关键功能
- 健康检查阶段 - 使用 curl 实际测试服务可用性
- 进程状态检查 - 验证 worker 进程正常运行
执行流程更加严谨
- 等待时间 (
sleep 2) - 确保 worker 进程完全切换 - 状态验证 - 多维度检查服务状态
- 信息反馈 - 每个步骤都有明确的状态输出
监听 80 和 443 端口
在 Nginx 中如何优雅地处理 HTTP (80端口) 和 HTTPS (443端口) 的监听配置,有两种不同的实践思路。
当使用完全相同的配置同时服务 HTTP 和 HTTPS 时(即单个 server 块同时监听 80 和 443 端口),Nginx 具备足够的智能:通过端口 80 接收的 HTTP 请求会自动忽略所有 SSL 相关的指令。
这意味着:你可以写一份配置,同时监听两个端口,Nginx 会根据访问的端口自动判断是否启用 SSL。
然而,社区推崇的最佳实践是:使用独立的 server 块分别处理 HTTP 和 HTTPS。
- 专门用一个
server块处理 HTTP 到 HTTPS 的重定向,配置应尽可能简单、硬编码,避免使用正则表达式。 - 另一个
server块则专注于处理主要的 HTTPS 业务逻辑。
优点:
- 维护性:职责分离,修改重定向规则不会影响主业务逻辑。
- 清晰性:配置意图明确,易于理解和调试。
- 可靠性:硬编码规则比复杂正则更稳定。
这在多域名托管(虚拟主机)时尤其有用:你可以将同一个监听指令(如 listen 10.240.20.2:80;)轻松复用到多个域的配置中,实现一个 IP 地址绑定多个域名。
对于 HTTPS,配置通常需要"硬编码"域名。因为你必须预先明确要为哪个域名提供相应的 SSL 证书。
关键要点总结
- 智能兼容:Nginx 能自动忽略非 HTTPS 端口上的 SSL 指令,允许单一配置处理双协议,但这不是最佳实践。
- 职责分离原则:最佳实践是使用两个独立的
server块:- 一个用于重定向:监听 80 端口,唯一职责是将 HTTP 流量 301 重定向到 HTTPS。
- 一个用于主服务:监听 443 端口,配置 SSL,处理所有业务逻辑。
- 配置策略:重定向部分的配置应简单、硬编码、避免正则表达式,以提升性能和可靠性。
- 多域名托管:分离监听指令的架构,更易于在单一 IP 上管理多个 HTTPS 域名(SNI)。
- HTTPS 的确定性:由于 SSL 证书与特定域名绑定,HTTPS 的
server块配置通常需要明确指定域名。
标准配置范例
# 1. HTTP 重定向服务器 (最佳实践:独立且简单)
server {
listen 80;
server_name example.com www.example.com;
# 硬编码重定向,避免复杂逻辑
return 301 https://example.com$request_uri;
}
# 2. HTTPS 主服务器 (专注于业务逻辑)
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL 配置必须硬编码指定证书路径
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/private.key;
# ... 主业务配置 ...
}# 专用重定向服务器 - 统一管理所有 HTTP 到 HTTPS
server {
listen 80;
server_name _; # 匹配所有域名
# server_name *.example.com;
# 统一重定向到 HTTPS
return 301 https://$host$request_uri;
}
# 或者针对特定域名组
server {
listen 80;
server_name example.com www.example.com api.example.com;
return 301 https://$server_name$request_uri;
}当新增域名时:
- 统一管理:自动继承重定向规则,无需额外配置
- 分散管理:每个新域名都要手动添加重定向配置
多域名统一重定向
# 单个 Server 块处理所有域名的 HTTP 重定向
server {
listen 80;
server_name
example.com
www.example.com
api.example.com
shop.example.com
*.example.com;
# 所有域名统一跳转到 HTTPS
return 301 https://$host$request_uri;
}分散重定向(不推荐)
# 每个域名单独配置 - 维护麻烦
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
listen 80;
server_name api.example.com;
return 301 https://api.example.com$request_uri;
}
server {
listen 80;
server_name blog.example.com;
return 301 https://blog.example.com$request_uri;
}Nginx 的 server_name 匹配优先级
Nginx 按以下顺序选择 server 块:
- 精确匹配
server_name example.com; - 通配符前缀
server_name *.example.com; - 通配符后缀
server_name example.*; - 正则表达式
server_name ~^www\.example\.com$; - 默认服务器
server_name _;或default_server
server_name _ 只匹配没有其他更具体配置的请求
不会"自动继承" - 如果有更具体的 server_name 匹配,就会绕过通用规则
真正的统一管理需要:要么显式列出所有域名,要么确保没有其他冲突的 server 块
DNS有A记录,但Nginx未配置该域名
显示结果:
会显示Nginx默认的欢迎页面,或者第一个匹配的server块内容
# 如果有这样的配置:
server {
listen 80;
server_name example.com; # 配置了example.com
}
server {
listen 80 default_server; # 或者 server_name _;
# 这是默认服务器,会捕获所有未明确配置的域名
}假设:
DNS:unknown-domain.com → 192.168.1.100
Nginx配置:
server {
listen 80;
server_name example.com;
return 200 "Hello example.com";
}
server {
listen 80 default_server;
return 404 "Domain not configured";
}直接访问服务器IP
会显示标记为 default_server 的server块内容,或者第一个listen块
# 情况A:有明确的default_server
server {
listen 80 default_server;
return 200 "This is the default server";
}
server {
listen 80;
server_name example.com;
return 200 "Hello example.com";
}直接访问IP显示:"This is the default server"
拒绝未知域名和IP直接访问
# 专用默认服务器,拒绝所有未知请求
server {
listen 80 default_server;
listen 443 ssl default_server;
ssl_certificate /path/to/default/cert.pem;
ssl_certificate_key /path/to/default/key.pem;
# 返回444会直接关闭连接,不发送任何内容
return 444;
# 或者返回自定义错误页
# return 404 "Domain not found";
}
# 正常的业务服务器
server {
listen 80;
server_name example.com;
# 正常业务逻辑...
}显示维护页面
server {
listen 80 default_server;
root /var/www/default;
location / {
# 显示友好的默认页面
try_files $uri $uri/ /index.html;
}
}跳转到主域名
server {
listen 80 default_server;
# 所有未知域名和IP访问都跳转到主站
return 301 https://www.company.com;
}显示指定监听的地址和端口
listen 指令的灵活性
- 完整格式:
listen <address>:<port> - 自动补全:如果省略 IP 或端口,Nginx 会用默认值填充
- 示例解析:
listen 192.168.252.10;→ 补全为192.168.252.10:80listen 80;→ 补全为*:80或0.0.0.0:80(监听所有IP)
server_name 的评估时机
- 条件限制:只有在
listen指令同一级别匹配时,才会评估server_name - 匹配顺序:先按
listen筛选,再按server_name精确匹配
常规网站配置
# 99% 的网站只需要这样配置
server {
listen 80; # HTTP 默认端口
listen 443 ssl; # HTTPS 默认端口
server_name example.com;
# ... 业务配置 ...
}特殊情况使用特定IP:端口
只有在特定场景下才需要指定具体IP和端口:
场景1:管理后台/敏感服务
# 管理后台只在内网特定IP监听
server {
listen 192.168.1.100:8080; # 非标准端口 + 内网IP
server_name admin.example.com;
# 管理面板配置...
}场景2:多IP服务器
# 服务器有多个IP,不同服务绑定不同IP
server {
listen 203.0.113.10:80; # 主网站IP
server_name example.com;
}
server {
listen 203.0.113.20:80; # 备用IP或特定服务IP
server_name api.example.com;
}场景3:开发测试环境
# 开发环境使用非标准端口
server {
listen 127.0.0.1:3000; # 本地开发
server_name localhost;
}标准配置(推荐)
# 面向公网的Web服务
server {
listen 80;
listen 443 ssl;
server_name example.com www.example.com;
# SSL证书、业务逻辑...
}特殊配置(按需使用)
# 只有真正需要时才指定IP和端口
server {
listen 192.168.1.100:8443; # 内网管理面板
server_name admin.internal.com;
# 额外的安全配置...
}listen 443 ssl;监听 443 端口并启用 SSL 协议。
就是说:
listen 443- 监听 443 端口(HTTPS 默认端口)ssl- 告诉 Nginx 在这个端口上使用 SSL/TLS 加密
简单说就是:这个服务器块专门处理 HTTPS 加密请求。
没有 ssl 参数就是普通 HTTP,有 ssl 就是加密的 HTTPS。
listen 443 ssl 就是明确告诉 Nginx:"在这个 443 端口上,必须使用 HTTPS 协议,给我走 SSL/TLS 加密流程。"
虽然 443 默认就是 HTTPS 端口,但 Nginx 要求你显式地加上 ssl 参数,它才会启用 SSL 处理。
没有 ssl 的话,Nginx 在 443 端口上就不知道要处理 SSL 握手、解密等操作。
防止使用未定义的服务器名称处理请求
Nginx 需要正确处理未定义服务器名称或使用 IP 地址的请求,防止配置错误导致流量被错误转发。
核心机制
- 默认服务器规则:如果没有明确设置
default_server参数,Nginx 会自动将第一个address:port配对的服务器作为默认服务器 - 请求匹配逻辑:基于 HTTP Host 头进行服务器匹配,不依赖 TLS SNI
- IP 地址请求:当客户端使用 IP 访问时,Host 头包含 IP 地址,Nginx 会尝试将其作为服务器名匹配
推荐配置方案
## 默认服务器配置,放置在配置文件开头
server {
## 关键参数:default_server 标记此服务器为默认
listen 10.240.20.2:443 default_server ssl;
## 匹配所有请求:无效域名、无 Host 头、其他未匹配请求
server_name _ "" default_server;
## 处理方式(三选一):
## 1. 直接关闭连接
return 444;
## 2. 返回错误页面
# location / {
# root /etc/nginx/error-pages/404;
# }
## 3. 重定向到指定页面
# return 301 https://example.com;
}
## 正常业务服务器配置
server {
listen 10.240.20.2:443 ssl;
server_name domain.com;
...
}
server {
listen 10.240.20.2:443 ssl;
server_name domain.org;
...
}SSL 要求:SSL 服务器必须配置证书和密钥(即使是自签名的)
显式声明:在多文件配置中,建议显式标记默认服务器以避免不确定性
server_name _ "" default_server 中的 default_server 仅为提高可读性,实际功能由 listen 指令的 default_server 参数控制
避免在 listen 或 upstream 中使用主机名
在 Nginx 配置中,应始终使用 IP 地址而非主机名来定义 listen 指令和 upstream 服务器地址。
错误做法及风险:
upstream {
server http://x-9s-web01-prod:8080; # 使用主机名
}
server {
listen rev-proxy-prod:80; # 使用主机名
...
}启动失败:如果 DNS 解析失败,Nginx 将无法绑定 TCP 端口,导致服务完全无法启动
依赖脆弱:增加对外部/内部 DNS 解析器的依赖,引入单点故障
调试困难:DNS 问题导致的错误往往难以追踪和诊断
性能损耗:每次都需要进行域名解析,增加不必要的开销
正确配置方案:
upstream {
server http://192.168.252.200:8080; # 使用明确的 IP 地址
}
server {
listen 10.10.100.20:80; # 使用明确的 IP 地址和端口
...
}明确性:始终使用 IP:端口 格式,避免任何形式的主机名引用
独立性:消除对外部解析服务的依赖,确保配置自包含
可靠性:防止因 DNS 问题导致的启动失败或运行时错误
性能优化:减少解析开销,提升响应速度
扩展提醒
- 同样应避免在
server_name指令中使用$hostname变量 - 确保所有网络端点都使用静态 IP 地址定义
- 在容器化环境中,使用服务发现的 IP 地址而非服务名称
补充:
以上建议是在大多数常见的 Nginx 部署场景下给出的最佳实践。通常情况下,Nginx 是部署在物理服务器、虚拟机或普通内网环境中,此时:
upstream中写主机名(hostname),例如x-9s-web01-prod,会触发 DNS 解析依赖;listen中写主机名更是不合理,系统无法将 Socket 绑定到一个需要解析的主机名;- 这些都会增加部署不确定性,因此推荐使用固定的 IP 地址来确保稳定性。
那什么时候才会有人写主机名?
只有在以下环境里才可能用到主机名或服务名:
| 场景 | 解释 |
|---|---|
| 内网 DNS 系统 | 大型企业内部维护了企业级 DNS,用 hostname 访问 |
| 容器集群(Docker Compose/Swarm) | 服务名可以自动解析,比如 backend:5000 |
| Kubernetes 服务发现 | 通过 Service 名访问,如 user-service.default.svc.cluster.local |
| Consul / Eureka / Nacos | 分布式服务发现系统动态注册服务 |
这些系统内部确实支持用主机名或服务名访问后端服务,因为它们有自己的 服务发现 + 内部 DNS。
如果你真的想用域名,必须做到:
- 本地或服务器内必须运行 DNS 解析服务(CoreDNS、Bind9、dnsmasq)
- 保证 Nginx 启动时 DNS 可用,否则启动失败
- 需要有 fallback 或 IP 直连兜底机制
- 有 DevOps 团队负责维护 DNS 服务稳定
总结这段补充:
不推荐在普通 Nginx 部署环境中使用主机名做 upstream 或 listen(因为需要依赖 DNS)。
如果真的要用主机名,那你必须有稳定的内部 DNS 服务或运行在容器集群/服务发现系统里,否则就是坑。
单一 SSL 配置最佳实践
在同一 IP 地址上运行多个 HTTPS 服务器时,应使用统一的 SSL 配置,确保协议、密码套件等参数的一致性。
配置架构
推荐方案:创建共享 SSL 配置文件
## https.conf - 共享 SSL 基础配置
listen 192.168.252.10:443 default_server ssl http2;
ssl_protocols TLSv1.2;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384";
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp521r1:secp384r1;
...具体实现
domain-a.com 配置:
server {
include /etc/nginx/https.conf; # 引入共享 SSL 配置
server_name domain-a.com;
ssl_certificate domain-a.com.crt; # 域名特定证书
ssl_certificate_key domain-a.com.key;
...
}domain-b.com 配置:
server {
include /etc/nginx/https.conf; # 引入共享 SSL 配置
server_name domain-b.com;
ssl_certificate domain-b.com.crt; # 域名特定证书
ssl_certificate_key domain-b.com.key;
...
}技术背景
- SSL 握手特性:在浏览器发送 HTTP 请求前已完成 SSL 连接,此时 Nginx 无法获知请求的服务器名称
- 默认服务器限制:未启用 SNI 时,只能提供默认服务器的证书
- SNI 扩展:现代解决方案,允许在 SSL 握手期间传递请求的服务器名称
关键优势
- 维护简便:SSL 参数集中管理,避免配置分散
- 调试友好:统一的加密设置,便于问题排查
- 配置一致:防止参数不匹配导致的兼容性问题
- 扩展灵活:新增域名只需引入共享配置并指定专属证书
注意事项
- 确保正确设置
default_server指令 - 所有基于同一 IP 的 HTTPS 服务器应使用相同的 SSL 参数
- 证书和私钥仍保持各域名独立
- 现代环境应启用 SNI 支持以获得更好的灵活性
HTTPS SSL 配置的精髓:SSL 基础配置大家都一样,证书各自管各自的
顶层共享配置 (ssl_base.conf):
## 这些SSL参数所有站点都一样
listen 443 ssl http2;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
...各站点配置:
## 站点A - 只用关心自己的证书
server {
include /etc/nginx/ssl_base.conf;
server_name site-a.com;
ssl_certificate /certs/site-a.crt;
ssl_certificate_key /certs/site-a.key;
}
## 站点B - 证书自己管,其他继承
server {
include /etc/nginx/ssl_base.conf;
server_name site-b.com;
ssl_certificate /certs/site-b.crt;
ssl_certificate_key /certs/site-b.key;
}一改全改:要调整 SSL 协议版本?改一个文件就行
各管各的:证书过期、轮换互不影响
减少重复:不用在每个 server 块里复制粘贴相同的 SSL 参数
避免手滑:防止某个站点配错了安全参数
使用 Geo/Map 模块替代 Allow/Deny
在 Nginx 中,allow 和 deny 是最基础的基于 IP 地址的访问控制指令,用于允许或拒绝某些客户端 IP 访问指定的资源或路径。
写在 server 或 location 里就能控制访问:
location /admin {
allow 192.168.1.10; # 允许这个 IP
allow 192.168.1.0/24; # 允许这个网段
deny all; # 拒绝其他所有访问
}常用规则语法说明
| 写法 | 说明 | 示例 |
|---|---|---|
allow IP | 允许指定 IP | allow 203.0.113.10; |
allow CIDR | 允许网段 | allow 192.168.1.0/24; |
deny all | 拒绝所有其他 IP | 必配 |
include | 引入外部 ACL 文件 | include conf.d/ip-whitelist.conf; |
典型使用场景
| 场景 | 配置 |
|---|---|
| 限制后台管理访问 | /admin 只允许内网进入 |
| 保护监控页面 | /status 仅管理员可访问 |
| 禁止外部调试接口 | /debug 拒绝所有人 |
Geo 和 Map 模块通过 IP 地址条件变量实现了更灵活、高效的访问控制,特别适用于大规模 IP 列表管理。
- 高效查找:Geo 模块在配置加载时构建内存基数树,提供极快的路由查找性能
- 按需计算:变量仅在使用时求值,避免不必要的请求处理开销
- 灵活扩展:支持复杂条件逻辑和变量组合
传统 Allow/Deny 方式:
location /internal {
include acls/internal.conf;
allow 192.168.240.0/24;
deny all;
...
}Geo/Map 模块方式:
location /internal {
if ($globals_internal_map_acl) {
set $pass 1;
}
if ($pass = 1) {
proxy_pass http://localhost:80;
}
if ($pass != 1) {
return 403;
}
...
}Map 模块示例:
map $remote_addr $globals_internal_map_acl {
default 0; # 默认拒绝
10.255.10.0/24 1; # 内部网络允许
10.255.20.0/24 1;
10.255.30.0/24 1;
192.168.0.0/16 1;
}Geo 模块示例:
geo $globals_internal_geo_acl {
default 0; # 默认拒绝
10.255.10.0/24 1; # 内部网络允许
10.255.20.0/24 1;
10.255.30.0/24 1;
192.168.0.0/16 1;
}适用场景建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 简单IP控制 | Allow/Deny | 配置直观,维护简单 |
| 大规模IP列表 | Geo/Map | 查找性能更优 |
| 复杂条件逻辑 | Geo/Map | 支持变量组合和条件判断 |
| 需要复用规则 | Geo/Map | 变量可在多个位置引用 |
最佳实践总结
- 性能优先:对于大规模 IP 列表(超过 1000 条),Geo 模块的基数树查找性能显著优于传统的 Allow/Deny 链式匹配
- 灵活性:Geo/Map 生成的变量可以在整个配置中复用,支持更复杂的访问控制逻辑
- 维护性:将 IP 列表集中定义,便于统一管理和更新
- 渐进采用:简单场景仍可使用 Allow/Deny,复杂需求逐步迁移到 Geo/Map
- 注意成本:Geo 模块在配置加载时可能消耗较多资源构建基数树,但运行时性能极佳
Geo 和 Map 模块为大规模、复杂的访问控制场景提供了更优的解决方案,特别是在需要高性能查找和灵活条件判断时表现突出。
为所有未匹配的路径设置根路径
在服务器级别设置全局根路径,确保所有请求(包括未匹配特定 location 的请求)都有基本的文件路径指向。
server {
server_name domain.com;
## 设置全局根路径 - 作为所有请求的默认文件路径
root /var/www/domain.com/public;
location / {
## 继承全局根路径:/var/www/domain.com/public
try_files $uri $uri/ /index.html;
}
location /api {
## 继承全局根路径:/var/www/domain.com/public
proxy_pass http://backend_server;
}
location /static {
## 覆盖全局根路径:使用专用静态文件目录
root /var/www/domain.com/static;
expires 1y;
add_header Cache-Control "public, immutable";
}
## 所有未明确匹配的 location 都会自动使用全局根路径
}try_files $uri $uri/ /index.html; 这一句是 Nginx 在做按顺序尝试匹配文件,它的意思是:
顺序检查文件是否存在,找到就用它,否则继续下一个,全部失败就走最后一个。
分解一下这个写法:
try_files $uri $uri/ /index.html;等价于:
- 先试试
$uri—— 当前请求路径对应的文件是否存在 - 不存在的话再试
$uri/—— 当前路径是否是一个目录 - 如果都找不到,就使用
/index.html作为 fallback(比如 SPA 应用的入口)
比如访问:https://domain.com/about
按顺序检查:
| 试什么? | 真实路径 | 结果 |
|---|---|---|
$uri → /about | /var/www/domain.com/public/about | 文件不存在 |
$uri/ → /about/ | /var/www/domain.com/public/about/ | 如果存在目录,就返回这个目录的 index.html |
/index.html | /var/www/domain.com/public/index.html | 最终 fallback |
为什么要写两次 $uri?
| 写法 | 检查类型 | 用途 |
|---|---|---|
$uri | 文件 | 静态文件请求 |
$uri/ | 目录 | 目录下自动找 index.html |
/index.html | 默认文件 | 支持前端单页应用(SPA)重定向 |
这句写法是 Nginx 处理静态资源+SPA路由的经典标准写法。
$uri → 查静态文件
$uri/ → 查目录
/index.html → Vue/React SPA 刷新也能正常返回页面
执行顺序说明
全局根路径设置:
root /var/www/domain.com/public;- 影响所有 location 块
- 为未匹配的请求提供默认文件路径
继承行为:
/和/apilocation 继承全局根路径- 请求
/api/user会查找/var/www/domain.com/public/api/user
局部覆盖:
location /static {
root /var/www/domain.com/static;
}- 请求
/static/logo.png会查找/var/www/domain.com/static/static/logo.png - 注意:
location路径会追加到root路径后
使用 alias 的替代方案
如果需要更精确的路径映射,可以使用 alias:
location /static {
## 使用 alias 时,location 路径不会追加到路径后
alias /var/www/domain.com/static;
## 请求 /static/logo.png 会查找 /var/www/domain.com/static/logo.png
}最佳实践
- 始终设置全局根路径:防止未匹配请求出现文件路径错误
- 位置块顺序:将精确匹配的 location 放在前面,通用匹配放在后面
- 合理覆盖:只有特定目录需要不同文件路径时才覆盖
root指令 - 测试验证:确保所有预期的文件路径都能正确解析
使用 return 指令进行 URL 重定向
基本语法
return [响应码] [URL];HTTP 到 HTTPS 重定向
server {
listen 80;
server_name example.com www.example.com;
## 方法1:使用 $host 变量(推荐)
return 301 https://$host$request_uri;
## 方法2:明确指定域名
# return 301 https://www.example.com$request_uri;
}非 www 到 www 重定向
server {
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}www 到非 www 重定向
server {
server_name www.example.com;
return 301 $scheme://example.com$request_uri;
}旧域名到新域名重定向
server {
server_name old-domain.com www.old-domain.com;
return 301 https://new-domain.com$request_uri;
}特定路径重定向
server {
server_name example.com;
location /old-page {
return 301 https://example.com/new-page;
}
location /blog {
return 301 https://blog.example.com$request_uri;
}
}可用变量说明
$host:请求的主机名(自动处理 www 与否)$request_uri:完整的请求 URI(包含查询参数)$scheme:请求协议(http 或 https)$uri:请求 URI(不包含查询参数)
响应码选择
301:永久重定向(SEO 友好,浏览器会缓存)302:临时重定向(不缓存,用于临时维护等场景)
低效的正则表达式方式
server {
server_name ~^www\.(.*)$;
rewrite ^(.*)$ https://$1$request_uri permanent;
}高效的 return 方式
server {
server_name www.example.com;
return 301 https://example.com$request_uri;
}完整示例
## HTTP 到 HTTPS 重定向
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
## 非 www 到 www 统一
server {
listen 443 ssl;
server_name example.com;
return 301 https://www.example.com$request_uri;
}
## 主站点配置
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/cert.crt;
ssl_certificate_key /path/to/private.key;
## 正常业务逻辑
location / {
root /var/www/html;
index index.html;
}
}访问加密
| 指令 | 作用 |
|---|---|
auth_basic | 启用访问认证并设置提示文本 |
auth_basic_user_file | 指定密码文件位置 |
基本用法示例(给整个站点加访问密码)
server {
listen 80;
server_name example.com;
auth_basic "Restricted Area"; # 登录提示文字
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
root /var/www/html;
}
}给指定路径加密码保护(常用)
location /admin {
auth_basic "Admin Only";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:8080;
}密码文件生成
Nginx 使用 htpasswd 格式的密码文件,可用 openssl 或 htpasswd 生成
使用 openssl(Linux 默认有)
printf "admin:$(openssl passwd -crypt 123456)\n" | sudo tee -a /etc/nginx/.htpasswd面这行创建了用户 admin,密码 123456
常用增强技巧(白名单 + 密码双重保护)
location /admin {
allow 192.168.1.0/24;
deny all;
auth_basic "Login Required";
auth_basic_user_file /etc/nginx/.htpasswd;
}这个配置同时支持:
- 内网免密码
- 外网必须密码才可访问