Nginx限制IP访问,拉黑恶意爬虫IP配置
前言
网站被恶意爬虫狂刷,服务器CPU跑满?或者有人恶意攻击你的网站?可以用 Nginx 直接把这些 IP 拉黑,不让他们访问。本文讲一下怎么配置 IP 访问控制。
怎么找到恶意 IP
先看 Nginx 访问日志,找出访问最频繁的 IP:
# 统计访问次数最多的前 20 个 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
如果某个 IP 访问量特别大,可能就是恶意爬虫或者攻击。
拉黑单个 IP
在 Nginx 配置里加:
server {
listen 80;
server_name www.example.com;
root /var/www/html;
# 拉黑某个 IP
location / {
deny 192.168.1.100;
allow all;
}
}
被拉黑的 IP 访问会返回 403 Forbidden。
拉黑 IP 段
拉黑整个 C 段
deny 192.168.1.0/24;
就是拉黑 192.168.1.1 到 192.168.1.255。
拉黑多个 IP
deny 192.168.1.100;
deny 192.168.1.101;
deny 192.168.1.102;
白名单模式(只允许某些 IP 访问)
如果想只允许特定 IP 访问(比如后台管理页面):
# 只允许内网 IP 访问 /admin
location /admin {
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
}
其他 IP 访问 /admin 都会返回 403。
用 include 单独管理黑名单
IP 多了不想写在主配置里,可以单独放一个文件:
第一步:创建黑名单文件
vi /etc/nginx/conf.d/blacklist.conf
内容:
deny 192.168.1.100;
deny 192.168.1.101;
deny 10.0.0.0/8;
第二步:在主配置里引入
server {
listen 80;
server_name www.example.com;
root /var/www/html;
# 引入黑名单
include /etc/nginx/conf.d/blacklist.conf;
location / {
try_files $uri $uri/ =404;
}
}
这样以后加黑名单只要改 blacklist.conf 文件,然后重载 Nginx 就行。
对某个目录单独限制
比如只对 /admin 目录限制:
location /admin {
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
root /var/www/html;
index index.php;
}
检查配置并重载
nginx -t
nginx -s reload
用防火墙拉黑(更彻底)
如果想在系统层面拉黑,用 firewall-cmd:
# 拉黑单个 IP
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' reject"
# 重新加载
firewall-cmd --reload
或者用 iptables:
iptables -I INPUT -s 192.168.1.100 -j DROP
常见坑
坑1:改了黑名单忘了 reload
加了黑名单,但 IP 还能访问。
原因: Nginx 没重载。
解决:
nginx -s reload
坑2:把自己 IP 拉黑了
测试的时候不小心把自己 IP 也拉黑了,自己也访问不了了。
解决: 先从服务器上用 curl 测试:
curl -I http://127.0.0.1
确认没问题再 reload。
坑3:CDN 后面拿不到真实 IP
用了 CDN 之后,日志里全是 CDN 的 IP,看不到用户真实 IP。
解决: 先配置 Nginx 获取真实 IP:
set_real_ip_from CDN的IP段;
real_ip_header X-Forwarded-For;
这样日志里才能看到用户真实 IP,才能正确拉黑。
总结
| 操作 | 命令/配置 |
|---|---|
| 拉黑单个 IP | deny 192.168.1.100; |
| 拉黑 IP 段 | deny 192.168.1.0/24; |
| 白名单模式 | allow 127.0.0.1; deny all; |
| 单独黑名单文件 | include /etc/nginx/conf.d/blacklist.conf; |
| 重载生效 | nginx -s reload |
提醒: 拉黑 IP 之前先确认是不是真的恶意,别误杀正常用户。
遇到问题加QQ23979811 协助处理
Nginx反向代理配置,代理后端PHP服务
前言
LNMP 架构里,Nginx 收到 PHP 请求之后,要转发给 PHP-FPM 处理。这个转发的配置就是 fastcgi_pass。本文讲一下完整的 Nginx 代理 PHP 服务配置。
两种代理方式
Nginx 代理后端服务有两种方式:
- proxy_pass:代理 HTTP 服务(比如 Node.js、Java、Python)
- fastcgi_pass:代理 FastCGI 服务(就是 PHP-FPM)
PHP 用的是 fastcgi_pass,不是 proxy_pass,别搞混了。
基础配置
完整 LNMP 配置示例
server {
listen 80;
server_name www.example.com;
root /var/www/html;
index index.php index.html;
# 访问根目录
location / {
try_files $uri $uri/ =404;
}
# PHP 请求转发给 PHP-FPM
location ~ \.php$ {
root /var/www/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
关键参数说明
| 参数 | 作用 |
|---|---|
fastcgi_pass 127.0.0.1:9000 |
PHP-FPM 监听的地址和端口 |
fastcgi_pass unix:/run/php-fpm/www.sock |
用 socket 文件方式(更高效) |
fastcgi_index index.php |
默认首页 |
SCRIPT_FILENAME |
PHP 文件的完整路径 |
include fastcgi_params |
引入其他参数 |
socket 方式 vs 端口方式
端口方式(TCP)
fastcgi_pass 127.0.0.1:9000;
优点:跨服务器可以用
缺点:多了一层 TCP 开销,稍微慢一点
Socket 方式(Unix Domain Socket)
fastcgi_pass unix:/run/php-fpm/www.sock;
优点:更快,少了 TCP 开销
缺点:只能在同一台服务器上用
生产环境推荐用 socket 方式,更快。
完整生产环境配置
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/www.crt;
ssl_certificate_key /etc/nginx/ssl/www.key;
root /var/www/html;
index index.php index.html;
# 日志
access_log /var/log/nginx/www.access.log;
error_log /var/log/nginx/www.error.log;
# 静态资源直接返回
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 30d;
}
# PHP 请求转发
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 超时设置
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}
# 禁止访问 .ht 等文件
location ~ /\.ht {
deny all;
}
}
常见坑
坑1:SCRIPT_FILENAME 路径不对
配置了 SCRIPT_FILENAME /var/www/html$fastcgi_script_name;,但 root 不是这个路径。
原因: 写死了路径,换个目录就错了。
解决: 用 $document_root:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
坑2:socket 路径不一致
Nginx 配置里写的 socket 路径和 PHP-FPM 实际的不一致。
检查 PHP-FPM 的 socket 路径:
grep listen /etc/php-fpm.d/www.conf
确保两边路径一模一样。
坑3:PHP 不解析,直接下载
访问 index.php,浏览器直接下载了文件,没解析。
原因: Nginx 没把 .php 请求转发给 PHP-FPM。
检查: 配置里有没有 location ~ \.php$ 这一段,有没有 fastcgi_pass。
坑4:404 Not Found
访问 PHP 文件报 404。
原因: SCRIPT_FILENAME 路径不对,PHP-FPM 找不到文件。
解决: 确认 root 和 SCRIPT_FILENAME 配置正确。
检查配置并重载
nginx -t
nginx -s reload
总结
| 配置项 | 说明 |
|---|---|
fastcgi_pass |
PHP-FPM 地址(端口或socket) |
SCRIPT_FILENAME |
PHP 文件完整路径 |
fastcgi_params |
其他参数集合 |
expires |
静态资源缓存 |
| 超时设置 | fastcgi_connect_timeout 等 |
记住: PHP 用 fastcgi_pass,不是 proxy_pass,别搞混了。
遇到问题加QQ23979811 协助处理
Nginx 403 Forbidden权限不足原因与解决
前言
打开网站突然报 403 Forbidden,权限不足。这是 Nginx 最常见的报错之一。本文讲一下 403 的常见原因和解决办法。
403 是什么意思
403 Forbidden 表示服务器理解请求,但拒绝执行。说白了就是 Nginx 不让你访问这个文件/目录。
常见原因和解决办法
原因1:文件/目录权限不对
最常见的原因。Nginx 运行的用户(一般是 www)没有权限读文件。
检查权限:
ls -l /var/www/html/index.html
如果是 644 以下,或者属主是 root,Nginx 就读不了。
解决:
# 改文件权限
chmod 644 /var/www/html/index.html
# 改目录权限
chmod 755 /var/www/html
# 改属主
chown -R www:www /var/www/html
原因2:首页文件不存在
访问网站根目录,但没有 index 首页文件。
检查:
ls /var/www/html/
看看有没有 index.html 或 index.php。
解决:
- 把首页文件名改成 index.html 或 index.php
- 或者在 Nginx 配置里指定 index
index index.html index.php;
原因3:目录没有索引权限
访问一个目录,目录里没有首页文件,Nginx 又没开目录列表。
解决方法一: 放一个 index.html 进去
解决方法二: 开目录列表(不推荐,不安全)
location /uploads/ {
autoindex on;
}
原因4:SELinux 没关
CentOS7 默认开了 SELinux,会拦截 Nginx 访问文件。
检查 SELinux 状态:
getenforce
如果是 Enforcing,说明开着。
解决:
# 临时关闭
setenforce 0
# 永久关闭
vi /etc/selinux/config
# 改成 SELINUX=disabled
原因5:Nginx 配置了访问控制
Nginx 配置里限制了 IP 访问,或者需要密码。
检查配置:
grep -i "deny\|allow\|auth_basic" /etc/nginx/conf.d/*.conf
如果有 deny all 或者 IP 白名单,把你的 IP 加上或者去掉限制。
原因6:文件路径不对
Nginx 配置的 root 路径和实际文件路径不一致。
检查配置:
grep root /etc/nginx/conf.d/*.conf
确认 root 指向的目录里确实有你的文件。
排查步骤
- 先看错误日志
tail -f /var/log/nginx/error.log
日志里会写得很清楚是什么原因。
- 检查文件权限
ls -l /var/www/html/
- 检查 SELinux
getenforce
- 检查 Nginx 配置
nginx -t
常见坑
坑1:只改了文件权限没改目录权限
文件权限是 644,但上级目录权限不对,Nginx 还是进不去。
解决: 一级一级改目录权限:
chmod 755 /var
chmod 755 /var/www
chmod 755 /var/www/html
坑2:上传的文件是 root 创建的
用 root 上传了文件,文件属主是 root,Nginx 用户读不了。
解决:
chown -R www:www /var/www/html
坑3:SELinux 改了没重启
临时关了 SELinux,但重启服务器又开了。
解决: 改配置文件永久关闭,别只 setenforce 0。
坑4:用了 CDN 或 WAF
前面有 CDN 或 WAF,它们拦截了请求。
解决: 直接用服务器 IP 访问,看看是不是还是 403。如果直接 IP 访问没问题,就是 CDN/WAF 的问题。
总结
| 原因 | 解决办法 |
|---|---|
| 文件权限不对 | chmod 644 文件、chmod 755 目录 |
| 首页不存在 | 放个 index.html 进去 |
| SELinux 拦截 | 关闭 SELinux |
| IP 被限制 | 检查 Nginx allow/deny 配置 |
| 路径不对 | 检查 root 配置 |
| 属主不对 | chown www:www 目录 |
记住: 403 先看错误日志,大部分问题日志里都写得很清楚。
遇到问题加QQ23979811 协助处理
Nginx静态资源缓存配置,提升网站访问速度
前言
网站访问慢?很大一部分原因是静态资源(图片、CSS、JS)每次都要重新从服务器下载。配置浏览器缓存之后,用户第二次访问就直接从本地缓存读了,速度快很多。本文讲一下 Nginx 怎么配置静态资源缓存。
缓存原理
浏览器第一次访问网站,服务器返回静态资源的时候,加上 Cache-Control 头,告诉浏览器"这个文件你缓存多久"。
第二次访问的时候,浏览器发现本地有缓存,且还没过期,就直接用本地的,不用再请求服务器了。
配置方法
按文件类型设置缓存时间
在 Nginx 配置里加:
server {
listen 443 ssl http2;
server_name www.example.com;
root /var/www/html;
index index.html;
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|swf|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# HTML 文件不缓存
location ~* \.html$ {
expires -1;
}
}
缓存时间说明
| 文件类型 | 建议缓存时间 | 说明 |
|---|---|---|
| 图片(jpg/png/gif) | 30天 | 图片一般不怎么改 |
| CSS/JS | 7天 | 改了文件版本号就能更新 |
| HTML | 不缓存 | 保证用户看到最新页面 |
| 字体文件 | 30天 | 基本不变 |
更精细的配置
# 图片缓存 30 天
location ~* \.(jpg|jpeg|png|gif|ico)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# CSS JS 缓存 7 天
location ~* \.(css|js)$ {
expires 7d;
add_header Cache-Control "public";
}
# 字体文件缓存 30 天
location ~* \.(woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# HTML 不缓存
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
参数说明
| 参数 | 作用 |
|---|---|
expires 30d |
缓存30天 |
expires 1h |
缓存1小时 |
expires -1 |
不缓存 |
Cache-Control public |
允许所有缓存(浏览器、CDN) |
Cache-Control private |
只允许浏览器缓存 |
Cache-Control no-cache |
不缓存(每次都要验证) |
Cache-Control no-store |
完全不缓存 |
immutable |
文件永远不变(不用问服务器了) |
怎么验证缓存生效了
打开浏览器 F12 → Network → 点一个静态资源 → 看 Response Headers:
Cache-Control: max-age=2592000
Expires: xxx
有这两个头就说明缓存生效了。
常见坑
坑1:改了 CSS 但页面没更新
更新了 CSS 文件,但用户看到的还是老版本。
原因: 浏览器缓存了老 CSS。
解决:
- 改文件名:
style.css→style.v2.css - 或者加版本号:
style.css?v=20261007
这样浏览器就会当成新文件重新下载。
坑2:HTML 也被缓存了
页面内容更新了,但用户看到的还是老页面。
原因: HTML 文件也被缓存了。
解决: HTML 文件设置不缓存:
location ~* \.html$ {
expires -1;
}
坑3:缓存时间太长
设置了一年缓存,万一文件要改怎么办?
解决: 用文件指纹(版本号)的方式,比如:
app.3a7b2c.jsstyle.8d9e1f.css
文件内容变了,文件名就变了,缓存自然就失效了。
坑4:配置了缓存但不生效
加了 expires 但浏览器还是每次都请求。
原因1: 开发模式下浏览器禁用了缓存。
解决: F12 → Network → 把 "Disable cache" 的勾去掉。
原因2: Nginx 没重载。
解决:
nginx -t
nginx -s reload
总结
| 步骤 | 操作 |
|---|---|
| 图片缓存 | expires 30d |
| CSS/JS 缓存 | expires 7d |
| HTML 不缓存 | expires -1 |
| 改了文件怎么更新 | 加版本号或改文件名 |
| 验证生效 | F12 看 Response Headers |
提醒: 缓存配置好之后,网站打开速度能快好几倍,特别是图片多的网站。
遇到问题加QQ23979811 协助处理
Nginx设置跨域,前端请求接口跨域配置示例
前言
前端页面和后端接口不在同一个域名下,浏览器报跨域错误。这是前后端分离开发最常见的问题。本文讲一下怎么用 Nginx 配置跨域。
什么是跨域
浏览器的同源策略:协议、域名、端口有一个不一样,就是跨域。
比如:
- 前端:
https://www.example.com - 后端接口:
https://api.example.com
这两个域名不一样,浏览器就不让前端直接请求后端接口。
Nginx 配置跨域
简单配置(允许所有域名)
在接口的 server 块里加:
server {
listen 443 ssl http2;
server_name api.example.com;
# 跨域配置
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
return 204;
}
root /var/www/api;
index index.php;
}
指定允许的域名(推荐)
生产环境不要用 *,指定具体域名更安全:
# 允许单个域名
add_header Access-Control-Allow-Origin https://www.example.com;
# 允许多个域名
set $cors_origin "";
if ($http_origin ~* "^https://(www\.example\.com|m\.example\.com)$") {
set $cors_origin $http_origin;
}
add_header Access-Control-Allow-Origin $cors_origin;
带 Cookie 的跨域
如果跨域请求要带 Cookie,光加 * 不行:
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
注意: 带 Cookie 的时候,Allow-Origin 不能用 *,必须指定具体域名。
完整配置示例
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/nginx/ssl/api.crt;
ssl_certificate_key /etc/nginx/ssl/api.key;
# 跨域配置
set $cors_origin "";
if ($http_origin ~* "^https://(www\.example\.com|admin\.example\.com)$") {
set $cors_origin $http_origin;
}
add_header Access-Control-Allow-Origin $cors_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $cors_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header Access-Control-Max-Age 86400;
return 204;
}
root /var/www/api;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
检查配置并重载
nginx -t
nginx -s reload
常见坑
坑1:OPTIONS 请求 404
浏览器发 OPTIONS 预检请求,Nginx 直接返回 404。
原因: 没处理 OPTIONS 请求。
解决: 加上面那个 if ($request_method = 'OPTIONS') 的判断,直接返回 204。
坑2:跨域配置不生效
加了跨域配置还是报跨域错误。
原因1: PHP 后端也输出了跨域头,两边冲突了。
解决: 只留一处跨域配置,要么在 Nginx 配,要么在后端代码里配,不要两边都配。
原因2: Nginx 重载失败了。
解决: 确认 nginx -t 没问题,再 nginx -s reload。
坑3:带 Cookie 的跨域失败
配置了跨域,但是带 Cookie 请求还是失败。
原因: Allow-Origin 用了 *,浏览器不允许。
解决: 改成具体域名,加上 Access-Control-Allow-Credentials true。
坑4:POST 请求跨域失败
GET 请求没问题,POST 请求跨域了。
原因: 没允许 POST 方法或者 Content-Type 头。
解决: 把 POST 和 Content-Type 加到 Allow-Methods 和 Allow-Headers 里。
总结
| 配置项 | 作用 |
|---|---|
Access-Control-Allow-Origin |
允许哪个域名访问 |
Access-Control-Allow-Methods |
允许哪些请求方法 |
Access-Control-Allow-Headers |
允许哪些请求头 |
Access-Control-Allow-Credentials |
是否允许带 Cookie |
Access-Control-Max-Age |
预检请求缓存时间 |
生产环境建议: 不要用 *,指定具体域名更安全。
遇到问题加QQ23979811 协助处理
Nginx 负载均衡配置
Nginx 负载均衡配置
网站流量大了,单台服务器扛不住,就需要负载均衡。这篇讲 Nginx 怎么配负载均衡。
1. 什么是负载均衡
简单说就是把请求分发到多台服务器上,分担压力,提高网站可用性。
2. 基础配置
http {
# 定义后端服务器组
upstream backend {
server 192.168.1.101:80;
server 192.168.1.102:80;
server 192.168.1.103:80;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
3. 负载均衡策略
轮询(默认):
按顺序逐个分发,每台服务器轮流来。
加权轮询:
服务器性能不一样,给好的服务器多分点流量。
upstream backend {
server 192.168.1.101 weight=3;
server 192.168.1.102 weight=2;
server 192.168.1.103 weight=1;
}
ip_hash(会话保持):
同一个 IP 的请求永远分发到同一台服务器,保持登录状态。
upstream backend {
ip_hash;
server 192.168.1.101;
server 192.168.1.102;
}
4. 健康检查
服务器挂了自动跳过,不把请求发过去。
upstream backend {
server 192.168.1.101 max_fails=3 fail_timeout=30s;
server 192.168.1.102 max_fails=3 fail_timeout=30s;
}
- max_fails:失败几次标记为下线
- fail_timeout:多久后重新检查
5. 常用配置说明
location / {
proxy_pass http://backend;
# 传递真实IP
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_connect_timeout 5s;
proxy_read_timeout 60s;
}
6. 常见问题
1)Session 丢失:
- 多台服务器 Session 不共享
- 解决方案:Session 存 Redis,或者用 ip_hash
2)静态文件 404:
- 每台服务器都要有静态文件
- 或者用共享存储
3)服务器性能不均:
- 用 weighted 加权轮询
总结
Nginx 负载均衡要点:
- upstream 定义后端服务器组
- 轮询、加权、ip_hash 三种策略
- 配置健康检查自动下线故障服务器
- Session 要共享或用 ip_hash
做网站架构,负载均衡是必备技能。
Nginx 配置 HTTPS 详解
Nginx 配置 HTTPS 详解
现在网站都要求上 HTTPS,Nginx 配置 HTTPS 是运维必备技能。
1. 申请 SSL 证书
免费证书推荐:
- Let's Encrypt(免费 90 天)
- 阿里云/腾讯云免费 DV 证书
用 acme.sh 申请 Let's Encrypt:
# 安装 acme.sh
curl https://get.acme.sh | sh
# 申请证书
~/.acme.sh/acme.sh --issue -d www.example.com --webroot /www/wwwroot/example.com/
# 安装证书
~/.acme.sh/acme.sh --install-cert -d www.example.com \
--key-file /www/server/ssl/private.key \
--fullchain-file /www/server/ssl/cert.crt
2. Nginx 基础 HTTPS 配置
server {
listen 443 ssl;
server_name www.example.com;
# 证书文件
ssl_certificate /www/server/ssl/cert.crt;
ssl_certificate_key /www/server/ssl/private.key;
# SSL 优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /www/wwwroot/example.com;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
3. HTTP 自动跳转 HTTPS
server {
listen 80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
4. 优化 HTTPS 性能
开启 HTTP/2:
listen 443 ssl http2;
HSTS 强制 HTTPS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
开启 OCSP Stapling:
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 114.114.114.114 valid=300s;
5. 常见问题
1)证书不生效:
- 检查证书路径对不对
- 证书文件格式是否正确
- Nginx 配置重载了吗
2)混合内容问题:
- 页面里有 http:// 的资源,浏览器会拦截
- 全部改成 https:// 或 // 协议相对路径
3)证书过期:
- 免费证书 90 天过期
- 用 acme.sh 自动续期
# acme.sh 自动安装了定时任务
crontab -l | grep acme
6. 检查配置
# 检查 Nginx 配置
nginx -t
# 重载配置
nginx -s reload
# 测试证书
curl -I https://www.example.com
总结
Nginx 配置 HTTPS 要点:
- 申请 SSL 证书
- 配置 443 端口和证书路径
- HTTP 跳转 HTTPS
- 开启 HTTP/2 和 SSL 优化
- 设置自动续期
现在没有 HTTPS 的网站浏览器都标"不安全",赶紧给网站配上。
Nginx配置HTTPS证书,http自动跳转https
前言
现在网站都要上 HTTPS,搜索引擎也更喜欢 HTTPS 的网站。本文讲一下 Nginx 怎么配置 HTTPS 证书,以及怎么把 HTTP 请求自动跳转到 HTTPS。
第一步:申请 SSL 证书
免费证书(Let's Encrypt)
用 certbot 自动申请:
# 安装 certbot
yum install certbot python3-certbot-nginx -y
# 自动申请并配置
certbot --nginx -d www.example.com -d example.com
certbot 会自动修改 Nginx 配置,不用手动改。
自己上传证书
如果是从阿里云、腾讯云申请的证书,下载 Nginx 版本的,一般有两个文件:
xxx.crt(证书文件)xxx.key(私钥文件)
上传到服务器:
mkdir -p /etc/nginx/ssl
把两个文件传到 /etc/nginx/ssl/ 目录下。
第二步:Nginx 配置 HTTPS
编辑 Nginx 配置文件:
vi /etc/nginx/conf.d/example.conf
配置内容:
server {
listen 443 ssl http2;
server_name www.example.com example.com;
# 证书路径
ssl_certificate /etc/nginx/ssl/xxx.crt;
ssl_certificate_key /etc/nginx/ssl/xxx.key;
# SSL 优化配置
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 网站根目录
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
第三步:HTTP 自动跳转 HTTPS
在同一个配置文件里,加一个 80 端口的 server:
# HTTP 跳转 HTTPS
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$host$request_uri;
}
这样访问 http://www.example.com 就会自动跳转到 https://www.example.com。
第四步:检查配置并重载
检查 Nginx 配置有没有语法错误:
nginx -t
没问题就重载:
nginx -s reload
完整配置示例
# HTTP 跳转 HTTPS
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$host$request_uri;
}
# HTTPS 配置
server {
listen 443 ssl http2;
server_name www.example.com example.com;
ssl_certificate /etc/nginx/ssl/xxx.crt;
ssl_certificate_key /etc/nginx/ssl/xxx.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ =404;
}
}
常见坑
坑1:证书文件路径不对
配置里写的证书路径和实际路径不一致,Nginx 启动报错。
解决: 确认证书文件确实在配置写的那个位置。
坑2:443 端口没开放
配置了 HTTPS 但访问不了。
原因: 防火墙没开 443 端口。
解决:
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
坑3:跳转死循环
HTTP 跳 HTTPS 后又跳回 HTTP,无限循环。
原因: 用了 CDN 或者负载均衡,后端以为还是 HTTP。
解决: Nginx 配置里加:
set $flag 0;
if ($http_x_forwarded_proto = 'http') {
set $flag 1;
}
if ($flag = 1) {
return 301 https://$host$request_uri;
}
坑4:证书过期了
HTTPS 证书一般一年有效期,忘了续签就会过期。
解决: 用 certbot 的话自动续签:
certbot renew
加个定时任务自动续签:
0 3 1 * * certbot renew --quiet
总结
| 步骤 | 命令/操作 |
|---|---|
| 申请证书 | certbot --nginx -d 域名 |
| 配置 HTTPS | 写 443 端口的 server 块 |
| HTTP 跳转 | return 301 https://$host$request_uri |
| 检查配置 | nginx -t |
| 重载 | nginx -s reload |
| 开防火墙 | firewall-cmd --permanent --add-service=https |
提醒: HTTPS 证书要定期续签,别等过期了才想起。
遇到问题加QQ23979811 协助处理
Nginx报502 Bad Gateway完整排查思路(PHP-FPM场景)
前言
502 Bad Gateway 是 Nginx 最常见的报错之一,尤其是 LNMP 架构下,Nginx 把 PHP 请求转发给 PHP-FPM,PHP-FPM 出问题了 Nginx 就报 502。本文讲一下完整的排查思路。
502 是什么意思
502 表示 Nginx 作为反向代理,去请求后端服务(PHP-FPM)的时候,后端没响应或者报错了。
注意: 502 不是 Nginx 的问题,是后端 PHP-FPM 的问题。
排查步骤
第一步:检查 PHP-FPM 服务是否在运行
systemctl status php-fpm
如果显示 inactive (dead),说明 PHP-FPM 挂了,启动它:
systemctl start php-fpm
systemctl enable php-fpm
第二步:检查 Nginx 和 PHP-FPM 的通信配置
看 Nginx 配置里的 fastcgi_pass 对不对:
grep fastcgi_pass /etc/nginx/nginx.conf
常见的配置:
# 用 socket 文件
fastcgi_pass unix:/run/php-fpm/www.sock;
# 用 TCP 端口
fastcgi_pass 127.0.0.1:9000;
问题1:socket 文件路径不对
Nginx 配置里写的 socket 路径和 PHP-FPM 实际的不一致。
PHP-FPM 的 socket 路径在 /etc/php-fpm.d/www.conf 里:
grep listen /etc/php-fpm.d/www.conf
确保两边路径一致。
问题2:端口被占
如果用 9000 端口,检查一下是不是被别的进程占了:
lsof -i:9000
第三步:看错误日志
Nginx 错误日志:
tail -f /var/log/nginx/error.log
PHP-FPM 错误日志:
tail -f /var/log/php-fpm/error.log
PHP 慢日志:
tail -f /var/log/php-fpm/www-slow.log
根据日志里的报错信息找原因。
第四步:常见原因
原因1:PHP-FPM 进程数不够
访问量大的时候,PHP-FPM 进程都被占满了,新请求排队超时。
解决: 增加 PHP-FPM 进程数。
编辑 /etc/php-fpm.d/www.conf:
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
改完重启:
systemctl restart php-fpm
原因2:PHP 脚本执行超时
PHP 脚本执行时间太长,超过了 Nginx 的超时时间。
解决: 调大超时时间。
Nginx 配置里:
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
PHP 配置里:
max_execution_time = 300
原因3:PHP 内存不足
PHP-FPM 进程内存溢出,导致进程崩溃。
解决: 调大 PHP 内存限制:
memory_limit = 256M
或者减少 PHP-FPM 进程数,避免内存不够。
原因4:文件权限不对
Nginx 运行的用户和 PHP-FPM 运行的用户不一致,导致 PHP-FPM 读不到文件。
解决: 确保 Nginx 和 PHP-FPM 用同一个用户(一般是 www)。
PHP-FPM 配置 /etc/php-fpm.d/www.conf:
user = www
group = www
然后把网站文件的属主改成 www:
chown -R www:www /var/www/html
第五步:重启所有服务
改完配置后重启:
systemctl restart php-fpm
systemctl restart nginx
常见坑
坑1:只重启了 Nginx
改了 PHP 配置但只重启了 Nginx,PHP-FPM 还是老配置。
解决: PHP 配置改了要重启 PHP-FPM,Nginx 配置改了要重启 Nginx。
坑2:socket 文件权限不对
PHP-FPM 的 socket 文件权限是 600,Nginx 用户读不到。
解决: 改 socket 文件权限:
listen.mode = 0666
或者改 socket 文件的属主:
listen.owner = www
listen.group = www
坑3:PHP-FPM 挂了但没自动重启
PHP-FPM 进程崩溃了,没人自动拉起来。
解决: 配置 systemd 自动重启:
systemctl edit php-fpm
加:
[Service]
Restart=always
RestartSec=2
总结
502 排查步骤:
- 先看 PHP-FPM 是不是挂了 →
systemctl status php-fpm - 再看 Nginx 配置对不对 → fastcgi_pass 路径/端口
- 看错误日志 → Nginx error.log + PHP-FPM error.log
- 常见原因 → 进程数不够、超时太短、权限不对、内存不足
记住:502 问题出在后端,不是 Nginx 的锅。
遇到问题加QQ23979811 协助处理
Nginx配置gzip压缩,提高网站加载速度
前言
网站加载慢,很大原因是没开压缩。CSS、JS 文件动辄几百 KB,开了 gzip 之后能压缩到原来的 1/3,加载速度提升明显。本文就讲一下怎么在 Nginx 里配置 gzip 压缩。
为什么要开 gzip
举个例子:
- 一个 CSS 文件原始大小 100KB
- 开了 gzip 之后变成 20KB
- 传输体积减少 80%
浏览器收到压缩内容后自动解压,用户无感知。
基础配置
在 nginx.conf 的 http 块里加上:
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_vary on;
}
配置项说明
gzip on:
开启 gzip 压缩。
gzip_types:
哪些类型的文件需要压缩。
text/plain:文本text/css:CSSapplication/json:JSONapplication/javascript:JSimage/svg+xml:SVG 图片
gzip_min_length:
小于 1KB 的文件不压缩(压缩本身也占 CPU,小文件不值得压)。
gzip_comp_level:
压缩级别,1 到 9,6 比较合适(越大压得越狠,但越占 CPU)。
gzip_vary on:
给响应头加 Vary: Accept-Encoding,告诉 CDN 和缓存,这个内容是压缩过的。
完整示例
http {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_vary on;
gzip_buffers 16 8k;
gzip_http_version 1.1;
}
检查并重载
nginx -t
systemctl reload nginx
验证 gzip 是否生效
用 curl 测试
curl -H "Accept-Encoding: gzip" -I https://www.example.com
如果返回头里有:
Content-Encoding: gzip
说明 gzip 生效了。
用浏览器 F12 测试
打开浏览器 F12 → Network → 点一个 JS/CSS 文件 → Response Headers,看有没有 Content-Encoding: gzip。
注意事项
不要压缩图片
JPG、PNG 这些图片本身已经是压缩过的,再压 gzip 没什么效果,还浪费 CPU。所以 gzip_types 里不要加 image/jpeg、image/png 这些。
不要压缩太小的文件
太小的文件(比如小于 1KB)压缩完反而可能变大,所以用 gzip_min_length 过滤掉。
压缩级别不要太高
gzip_comp_level 设到 9 没意义,压不了多少,CPU 占用还高。6 就够了。
常见坑
坑1:开了 gzip 但没生效
配置写了,但浏览器看到的还是没压缩的。
排查:
- 看文件大小是不是小于
gzip_min_length - 看
gzip_types里有没有包含这种类型 - 看浏览器请求头里有没有
Accept-Encoding: gzip
坑2:HTML 没压缩
只压缩了 CSS 和 JS,HTML 没压缩。
原因: gzip_types 里没写 text/html。
注意: text/html 是默认就压缩的,不用写在 gzip_types 里。
坑3:CDN 缓存了没压缩的版本
开了 gzip,但 CDN 上缓存的还是旧的没压缩的文件。
解决: 清一下 CDN 缓存,或者等 CDN 自动更新。
总结
gzip 配置很简单,就几行:
| 配置项 | 推荐值 | 作用 |
|---|---|---|
gzip |
on |
开启压缩 |
gzip_types |
text/css application/javascript ... | 压缩哪些文件 |
gzip_min_length |
1k |
小于多少不压 |
gzip_comp_level |
6 |
压缩级别 |
gzip_vary |
on |
加 Vary 头 |
开了 gzip 网站加载速度立马快一截,零成本优化,一定要开。
遇到问题加QQ23979811 协助处理
Nginx配置访问日志,日志切割和分析
前言
Nginx 默认就会记录访问日志,放在 /var/log/nginx/ 目录下。但日志每天都在涨,时间长了占满磁盘,还不好查。本文就讲一下 Nginx 日志配置、切割和分析方法。
默认日志位置
Nginx 默认日志文件:
/var/log/nginx/
├── access.log # 访问日志
└── error.log # 错误日志
日志格式
Nginx 默认的日志格式叫 combined,记录这些信息:
- 客户端 IP
- 访问时间
- 请求方法和路径
- 状态码
- 响应大小
- Referer
- User-Agent
自定义日志格式
在 nginx.conf 的 http 块里可以自定义日志格式:
http {
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;
}
常用变量
| 变量 | 说明 |
|---|---|
$remote_addr |
客户端 IP |
$time_local |
本地时间 |
$request |
请求行 |
$status |
状态码 |
$body_bytes_sent |
响应大小 |
$http_referer |
来源页面 |
$http_user_agent |
浏览器信息 |
$request_time |
请求耗时 |
按站点分日志
不同站点的日志分开存,方便排查问题:
server {
listen 80;
server_name www.example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}
日志切割
用 logrotate 切割
CentOS7 装完 Nginx 就自动配了 logrotate,不用管。配置文件在:
/etc/logrotate.d/nginx
内容大概是:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
notifempty
create 0640 nginx adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
意思是:
- 每天切割一次
- 保留 14 天
- 压缩旧日志
- 空日志不切割
手动测试切割
logrotate -f /etc/logrotate.d/nginx
日志分析常用命令
查看访问量前 10 的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
查看访问量前 10 的页面
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
查看状态码统计
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
查看爬虫访问
grep 'Googlebot' /var/log/nginx/access.log
查看某个 IP 的访问
grep '192.168.1.1' /var/log/nginx/access.log
常见坑
坑1:日志越来越大占满磁盘
日志不切割,时间长了把磁盘占满。
解决: 确认 logrotate 在运行:
cat /var/lib/logrotate.status
或者手动执行一次:
logrotate -f /etc/logrotate.d/nginx
坑2:日志里 IP 不对
日志里全是 127.0.0.1,不是真实用户 IP。
原因: Nginx 前面还有一层代理(比如 CDN),或者配了反向代理。
解决: 用 $http_x_forwarded_for 代替 $remote_addr:
log_format main '$http_x_forwarded_for - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
坑3:日志级别太高
错误日志里全是 notice,没用还占空间。
解决: 把错误日志级别调高一点:
error_log /var/log/nginx/error.log warn;
可选级别:debug、info、notice、warn、error、crit。
总结
Nginx 日志的常用操作:
| 操作 | 命令 |
|---|---|
| 看访问日志 | tail -f /var/log/nginx/access.log |
| 看错误日志 | tail -f /var/log/nginx/error.log |
| 统计 IP | awk '{print $1}' access.log \| sort \| uniq -c |
| 统计页面 | awk '{print $7}' access.log \| sort \| uniq -c |
| 手动切割 | logrotate -f /etc/logrotate.d/nginx |
日志是排查问题的第一手资料,学会看日志比什么都重要。
遇到问题加QQ23979811 协助处理
Nginx配置静态网站,前端项目部署到服务器
前言
前端项目写完了,怎么部署到服务器上让别人访问?现在前端都是 Vue、React 这种单页应用,打包出来一堆静态文件,扔到 Nginx 上就能跑。本文就讲一下怎么用 Nginx 部署前端静态网站。
第一步:打包前端项目
前端项目一般用 npm 或 yarn 打包:
npm run build
打包完会生成一个 dist 目录,里面就是所有静态文件(HTML、CSS、JS)。
第二步:上传到服务器
把 dist 目录上传到服务器上,比如放到 /var/www/html/my-app:
# 用 scp 上传
scp -r dist/ root@你的服务器IP:/var/www/html/my-app
或者用 FTP 工具上传。
第三步:配置 Nginx
最简单的配置
server {
listen 80;
server_name www.example.com;
root /var/www/html/my-app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
关键配置说明
root 网站根目录:
root /var/www/html/my-app;
就是你上传静态文件的目录。
index 默认首页:
index index.html;
用户访问网站根目录的时候,默认打开 index.html。
try_files 路由支持:
try_files $uri $uri/ /index.html;
这个很重要!Vue/React 这种单页应用,前端路由是靠 H5 History API 实现的。如果用户直接访问 /about 这种路径,Nginx 找不到对应的文件,就会 404。
加了 try_files 之后,Nginx 找不到文件就返回 index.html,交给前端路由处理。
检查并重载
nginx -t
systemctl reload nginx
测试
浏览器访问 www.example.com,应该能看到你的前端页面了。
加上 HTTPS
如果要配 HTTPS,加上 SSL 配置:
server {
listen 80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
root /var/www/html/my-app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
常见优化配置
开启 gzip 压缩
server {
# ... 其他配置
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1k;
gzip_comp_level 6;
}
开启 gzip 之后,文件传输体积小很多,加载更快。
静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
静态资源缓存 30 天,不用每次都重新下载。
隐藏 Nginx 版本号
http {
server_tokens off;
}
在 nginx.conf 的 http 块里加上这行,安全一点。
常见坑
坑1:刷新页面 404
路由是 /about,刷新就 404。
原因: Nginx 找不到 /about 对应的文件。
解决: 加 try_files:
location / {
try_files $uri $uri/ /index.html;
}
坑2:JS/CSS 404
打包完访问页面,JS 和 CSS 全 404。
原因: 打包的时候 publicPath 没配对。
解决: Vue 项目在 vue.config.js 里配:
module.exports = {
publicPath: '/'
}
React 项目在 .env 里配:
PUBLIC_URL=/
坑3:跨域问题
前端调后端接口,浏览器报跨域错误。
解决: 用 Nginx 反向代理把接口请求转发到后端,不要让前端直接请求后端地址。
location /api/ {
proxy_pass http://后端地址;
}
坑4:权限不够
访问报 403 Forbidden。
原因: Nginx 没有读取文件的权限。
解决:
chown -R nginx:nginx /var/www/html/my-app
chmod -R 755 /var/www/html/my-app
总结
前端项目部署到 Nginx 的完整流程:
- 打包:
npm run build - 上传:把
dist目录传到服务器 - 配置 Nginx:root 指向静态文件目录,加
try_files - 重载:
nginx -t && systemctl reload nginx - 测试:浏览器访问域名
部署静态网站是前端开发的必备技能,记住 try_files 那行就不会踩刷新 404 的坑了。
遇到问题加QQ23979811 协助处理
Nginx反向代理配置,把请求转发到后端服务
前言
现在做后端开发,后端服务一般跑在 3000、8080 这种端口上,总不能让用户直接访问 IP:端口 吧?这时候就需要 Nginx 反向代理,把 80 端口的请求转发到后端服务。本文就讲一下 Nginx 反向代理的配置方法。
什么是反向代理
简单说,反向代理就是:
- 用户访问 Nginx(80 端口)
- Nginx 把请求转发给后端服务(比如 3000 端口)
- 后端服务返回结果给 Nginx
- Nginx 再返回给用户
用户不知道后端服务的存在,只跟 Nginx 打交道。
基本配置
最简单的反向代理
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
就这么简单,所有访问 www.example.com 的请求都会被转发到 http://127.0.0.1:3000。
检查并重载
nginx -t
systemctl reload nginx
常用配置项
proxy_pass 后端地址
proxy_pass http://127.0.0.1:3000;
后端服务的地址,可以是 IP 加端口,也可以是域名。
传递真实客户端 IP
默认情况下,后端服务看到的是 Nginx 的 IP,不是真实用户的 IP。需要加上几个请求头:
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
这样后端服务就能拿到真实用户的 IP 了。
代理 WebSocket
如果后端服务用了 WebSocket,需要额外配置:
location /ws {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
超时设置
location / {
proxy_pass http://127.0.0.1:3000;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
如果后端服务响应慢,可以把超时时间调大一点。
按路径分流
不同路径转发到不同后端服务:
server {
listen 80;
server_name www.example.com;
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
location /admin/ {
proxy_pass http://127.0.0.1:8080;
}
location / {
root /var/www/html;
index index.html;
}
}
这样:
/api/开头的请求 → 3000 端口/admin/开头的请求 → 8080 端口- 其他请求 → 静态文件
常见坑
坑1:502 Bad Gateway
访问报 502,说明 Nginx 连不上后端服务。
排查:
- 看后端服务有没有启动:
curl http://127.0.0.1:3000 - 看后端服务监听的地址对不对,是不是只监听了 127.0.0.1
- 看防火墙有没有挡住
坑2:后端拿不到真实 IP
日志里全是 Nginx 的 IP,不是用户真实 IP。
解决: 加上那几个请求头:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
坑3:静态资源 404
前端是 Vue/React 这种单页应用,刷新页面就 404。
原因: Nginx 找不到对应的静态文件。
解决: 加个 try_files:
location / {
root /var/www/html;
index index.html;
try_files $uri $uri/ /index.html;
}
所有找不到的路径都返回 index.html,交给前端路由处理。
坑4:HTTPS 代理后端 HTTP
前端是 HTTPS,后端是 HTTP,浏览器报混合内容错误。
解决: 确保 Nginx 和后端之间是 HTTP 没问题,但要让后端知道原始请求是 HTTPS:
proxy_set_header X-Forwarded-Proto $scheme;
总结
Nginx 反向代理的核心就是 proxy_pass,把请求转发到后端服务。常用配置:
| 配置项 | 作用 |
|---|---|
proxy_pass |
后端服务地址 |
proxy_set_header Host |
传递域名 |
proxy_set_header X-Real-IP |
传递真实 IP |
proxy_set_header X-Forwarded-For |
传递完整 IP 链 |
proxy_read_timeout |
读取超时时间 |
反向代理是 Nginx 最常用的功能之一,做 Web 开发必备。
遇到问题加QQ23979811 协助处理
Nginx配置HTTPS,Let's Encrypt免费SSL证书申请
前言
现在网站没个 HTTPS 都不好意思拿出来,浏览器直接标"不安全"。申请 SSL 证书以前要花钱买,现在有了 Let's Encrypt,免费申请,90天有效期,还能自动续期。本文就讲一下怎么用 Let's Encrypt 给 Nginx 配 HTTPS。
前提条件
申请 SSL 证书之前,先确认:
- 域名已经解析到服务器 IP
- 80 端口已经开放(防火墙、安全组都要开)
- Nginx 已经能正常跑 HTTP
这三个条件满足了才能申请成功。
第一步:安装 certbot
certbot 是 Let's Encrypt 官方的证书申请工具。
yum install certbot python2-certbot-nginx -y
这个包会自动装 certbot 和 Nginx 插件。
第二步:申请证书
自动申请并配置
certbot --nginx -d www.example.com -d example.com
参数说明:
--nginx:自动修改 Nginx 配置-d:指定域名,可以写多个
执行过程中会问你:
- 邮箱地址:填你的邮箱,证书过期了会提醒你
- 同意服务条款:输入 A
- 是否接收邮件:输入 N
- 是否把 HTTP 跳转到 HTTPS:选 2(跳转)
等待申请完成,一般几秒钟就好。
第三步:测试 HTTPS
浏览器访问 https://www.example.com,应该能看到小锁标志了。
HTTP 访问 http://www.example.com 会自动跳转到 HTTPS。
证书文件位置
申请完的证书文件都在 /etc/letsencrypt/live/域名/ 目录下:
/etc/letsencrypt/live/www.example.com/
├── cert.pem # 证书
├── chain.pem # 中间证书
├── fullchain.pem # 证书+中间证书(Nginx用这个)
└── privkey.pem # 私钥
Nginx 配置里用的是:
ssl_certificate /etc/letsencrypt/live/域名/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/域名/privkey.pem;
自动续期
Let's Encrypt 证书有效期只有 90 天,需要定期续期。
测试自动续期
certbot renew --dry-run
如果没报错,说明自动续期配置没问题。
自动续期定时任务
certbot 装完会自动加一个定时任务,不用管。可以看看:
crontab -l
或者:
systemctl list-timers | grep certbot
手动配置 HTTPS
如果不想用 certbot 自动改配置,也可以手动写 Nginx 配置。
Nginx HTTPS 配置示例
server {
listen 80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /var/www/html/test;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
检查并重载
nginx -t
systemctl reload nginx
常见坑
坑1:域名没解析就申请
域名还没解析到服务器,就开始申请证书,结果申请失败。
解决: 先 ping 一下域名,确认解析到你服务器 IP 了再申请。
坑2:80 端口没开
防火墙或安全组没开 80 端口,Let's Encrypt 验证不了你的域名,申请失败。
解决: 先开 80 端口:
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
云服务器还要在安全组里开 80 端口。
坑3:证书到期了没续期
忘了续期,证书过期了,浏览器报不安全。
解决: certbot 会自动续期,不用管。但要确认自动续期服务在运行:
systemctl status certbot-renew.timer
坑4:HTTPS 配置完了 404
配完 HTTPS 访问 404,一般是 root 目录或者 server_name 写错了。
排查:
- 看 Nginx 配置里的
server_name对不对 - 看
root目录对不对 nginx -t检查配置语法
总结
Nginx 配置 HTTPS 的完整流程:
- 装 certbot:
yum install certbot python2-certbot-nginx -y - 申请证书:
certbot --nginx -d www.example.com - 自动续期:certbot 自动搞定,不用管
- 测试:浏览器访问 HTTPS,看小锁标志
Let's Encrypt 免费证书是现在最流行的方案,不用花钱就能给网站上 HTTPS。
遇到问题加QQ23979811 协助处理
Nginx安装配置完整教程,从安装到运行
前言
刚装好 CentOS 服务器,想跑个网站,第一步就是装 Nginx。Nginx 是目前最流行的 Web 服务器,性能高、占用资源少,还能做反向代理和负载均衡。本文就从安装 Nginx 开始,一步步讲怎么配置一个能跑的网站。
第一步:安装 Nginx
1. 安装 EPEL 源
CentOS7 默认源里的 Nginx 版本比较老,先装 EPEL 源:
yum install epel-release -y
2. 安装 Nginx
yum install nginx -y
3. 启动 Nginx
systemctl start nginx
4. 设置开机自启
systemctl enable nginx
5. 开放防火墙
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
6. 测试
浏览器访问你的服务器 IP,应该能看到 Nginx 默认欢迎页面。
第二步:Nginx 配置文件结构
Nginx 的配置文件都在 /etc/nginx/ 目录下:
/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/ # 子配置文件目录
│ └── default.conf # 默认站点配置
├── fastcgi.conf
├── mime.types
└── ...
一般我们写站点配置,都放在 conf.d/ 目录下,每个站点一个文件。
第三步:配置第一个站点
1. 创建网站根目录
mkdir -p /var/www/html/test
2. 写一个测试页面
echo "Hello Nginx" > /var/www/html/test/index.html
3. 创建站点配置文件
vi /etc/nginx/conf.d/test.conf
写入:
server {
listen 80;
server_name www.example.com;
root /var/www/html/test;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
4. 检查配置是否正确
nginx -t
输出 test is successful 就是没问题。
5. 重新加载 Nginx
systemctl reload nginx
6. 测试
浏览器访问 www.example.com,应该能看到 "Hello Nginx"。
注意: 要把域名解析到你服务器的 IP 上,或者在本地 hosts 文件里加一条记录。
常用配置说明
listen 监听端口
listen 80;
监听 80 端口,HTTP 默认端口。
如果要监听 HTTPS 的 443 端口:
listen 443 ssl;
server_name 域名
server_name www.example.com example.com;
可以写多个域名,用空格隔开。
root 网站根目录
root /var/www/html/test;
网站文件放在这个目录下。
index 默认首页
index index.html index.htm;
用户访问网站根目录的时候,默认找哪个文件。
配置 PHP 支持
如果要跑 PHP 网站,还需要配置 PHP-FPM。
1. 安装 PHP-FPM
yum install php-fpm php-mysql -y
2. 启动 PHP-FPM
systemctl start php-fpm
systemctl enable php-fpm
3. 修改 Nginx 配置
在站点配置里加上 PHP 支持:
server {
listen 80;
server_name www.example.com;
root /var/www/html/test;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
4. 重启 Nginx
systemctl restart nginx
5. 测试 PHP
创建一个 info.php 文件:
echo "<?php phpinfo(); ?>" > /var/www/html/test/info.php
浏览器访问 www.example.com/info.php,应该能看到 PHP 信息页面。
常见坑
坑1:403 Forbidden
访问网站报 403,一般是权限问题。
排查:
- 看文件权限是不是 644,目录是不是 755
- 看所有者是不是 nginx
- 看 SELinux 是不是开着
chown -R nginx:nginx /var/www/html/test
chmod -R 755 /var/www/html/test
坑2:502 Bad Gateway
访问网站报 502,说明 Nginx 连不上 PHP-FPM。
排查:
- 看 PHP-FPM 有没有启动:
systemctl status php-fpm - 看配置里的
fastcgi_pass地址对不对
坑3:配置改完不生效
改了 Nginx 配置,没 reload,结果配置没生效。
解决: 改完配置记得 reload:
nginx -t
systemctl reload nginx
坑4:域名解析了还是打不开
域名解析了,但还是打不开。
排查:
- 看防火墙有没有开 80 端口
- 看安全组有没有开 80 端口(云服务器)
- 看域名解析有没有生效:
ping www.example.com
总结
Nginx 安装配置的完整流程:
- 安装 Nginx:
yum install nginx -y - 启动并开机自启:
systemctl start nginx && systemctl enable nginx - 开放防火墙:80 和 443 端口
- 写站点配置:在
conf.d/下创建配置文件 - 检查并重载:
nginx -t && systemctl reload nginx
Nginx 是 Web 服务器的入门必备,装完这个就能跑网站了。
遇到问题加QQ23979811 协助处理
Nginx报502 Bad Gateway完整排查思路(PHP-FPM场景)
Nginx 出现 502 Bad Gateway 是最常见的报错之一,90% 的情况都是 PHP-FPM 出了问题。下面是完整的排查思路,按顺序一步步来,基本都能解决。
1. 先看 PHP-FPM 是否在运行
systemctl status php-fpm
如果显示 failed 或 inactive,直接重启:
systemctl restart php-fpm
注意:CentOS 7 一般是
php-fpm,Ubuntu 可能是php7.4-fpm之类的,看你装的版本。
2. 看 Nginx 错误日志(最关键)
tail -f /var/log/nginx/error.log
常见错误信息:
错误1:connect() failed (111: Connection refused) while connecting to upstream
说明 PHP-FPM 没启动,或者监听地址不对。
错误2:upstream timed out
PHP 脚本执行超时了,或者 PHP-FPM 进程不够用。
错误3:Primary script unknown
Nginx 配置里的 SCRIPT_FILENAME 路径不对,找不到 PHP 文件。
3. 检查 Nginx 配置是否正确
nginx -t
如果显示 test is successful 说明配置语法没问题。
重点检查 fastcgi_pass 这一行:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; # 或者 unix:/run/php-fpm/www.sock
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
常见问题:
- fastcgi_pass 地址和 PHP-FPM 实际监听地址不一致
- SCRIPT_FILENAME 路径写错了
4. 检查 PHP-FPM 监听地址
netstat -tlnp | grep php-fpm
或者:
ss -tlnp | grep php-fpm
看 PHP-FPM 是监听在 9000 端口还是 unix sock 文件,然后和 Nginx 配置里的 fastcgi_pass 对应上。
5. 检查 PHP-FPM 进程数是否够
看 PHP-FPM 配置:
vi /etc/php-fpm.d/www.conf
重点参数:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
如果访问量大,进程数不够就会 502。
6. 检查 PHP 错误日志
tail -f /var/log/php-fpm/www-error.log
有时候 PHP 代码本身报错,也会导致 502。
7. 其他常见原因
磁盘满了
df -h
内存不够
free -h
如果内存不足,PHP-FPM 进程会被杀掉,也会 502。
SELinux 没关
参考我之前的文章,关掉 SELinux 试试。
排查顺序总结
- 重启 PHP-FPM → 看能不能恢复
- 看 Nginx 错误日志 → 定位具体错误
- 检查 Nginx 配置 → fastcgi_pass 和 SCRIPT_FILENAME
- 检查 PHP-FPM 状态 → 监听地址、进程数
- 检查系统资源 → 磁盘、内存
- 检查 SELinux
遇到服务器、Nginx、MySQL 报错,可以加微信远程协助排查问题。
Nginx 日志分析技巧
Nginx 日志分析技巧
Nginx 日志是排查问题、分析流量的重要工具。学会看日志,网站问题排查效率翻倍。
1. 日志位置
# 默认访问日志
/var/log/nginx/access.log
# 默认错误日志
/var/log/nginx/error.log
可以在 nginx.conf 里自定义:
access_log /var/log/nginx/www.access.log;
error_log /var/log/nginx/www.error.log;
2. 日志格式
默认日志格式:
127.0.0.1 - - [04/Oct/2026:10:00:00 +0800] "GET / HTTP/1.1" 200 612 "https://www.baidu.com/" "Mozilla/5.0..."
各字段含义:
- IP 地址
- 请求时间
- 请求方法和路径
- 状态码
- 响应大小
- 来源页面
- User-Agent
3. 常用分析命令
# 查看访问量前10的IP
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head 10
# 查看访问量前10的页面
awk '{print $7}' access.log | sort | uniq -c | sort -nr | head 10
# 查看状态码分布
awk '{print $9}' access.log | sort | uniq -c | sort -nr
# 查看 404 请求
grep ' 404 ' access.log
# 查看 502 错误
grep ' 502 ' access.log
4. 排查问题
排查 502 错误:
grep ' 502 ' access.log | tail 20
排查慢请求:
开启慢日志:
slow_request_log /var/log/nginx/slow.log;
slow_request_time 5s;
排查爬虫:
grep 'Baiduspider' access.log
grep 'Googlebot' access.log
5. 流量统计
# 今天总访问量
grep '04/Oct/2026' access.log | wc -l
# 今天总流量
grep '04/Oct/2026' access.log | awk '{sum+=$10} END {print sum/1024/1024 " MB"}'
# 每小时访问量
awk '{print $4}' access.log | cut -d: -f2 | uniq -c
6. 日志切割
日志太大要切割,用 logrotate:
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
notifempty
create 0640 nginx adm
postrotate
systemctl reload nginx
endscript
}
7. 常用工具
- GoAccess:实时日志分析工具
- ELK:Elasticsearch + Logstash + Kibana
- Zabbix:监控告警
总结
Nginx 日志分析核心:
- 位置:/var/log/nginx/
- 命令:awk + sort + uniq
- 排查:看状态码、看慢请求
- 切割:用 logrotate
学会这些,日常日志分析基本够用了。
Nginx 负载均衡配置
Nginx 负载均衡配置实战
网站流量大了,单台服务器扛不住,就得用负载均衡。Nginx 做负载均衡很简单,几行配置就行。
1. 基本配置
http {
upstream backend {
server 192.168.1.101:80;
server 192.168.1.102:80;
server 192.168.1.103:80;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://backend;
}
}
}
默认是轮询(round robin),请求轮流分到三台服务器。
2. 四种分配策略
轮询(默认):一个一个来。
权重(weight):按比例分配,性能好的服务器多分担。
upstream backend {
server 192.168.1.101 weight=3;
server 192.168.1.102 weight=2;
server 192.168.1.103 weight=1;
}
3:2:1 的比例,第一台分一半请求。
ip_hash:同一个 IP 固定分到同一台服务器,解决 session 问题。
upstream backend {
ip_hash;
server 192.168.1.101;
server 192.168.1.102;
}
least_conn:最少连接数优先,分给当前最闲的服务器。
upstream backend {
least_conn;
server 192.168.1.101;
server 192.168.1.102;
}
3. 健康检查
upstream backend {
server 192.168.1.101 max_fails=3 fail_timeout=30s;
server 192.168.1.102 max_fails=3 fail_timeout=30s;
}
一台服务器挂了,自动从列表里摘掉,恢复了再加回来。
4. 常用参数
- max_fails:失败几次算挂了,默认1次
- fail_timeout:挂了多久再重试,默认10秒
- down:标记服务器下线,不分配请求
- backup:备用服务器,其他都挂了才用
5. 完整示例
upstream backend {
server 192.168.1.101 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.102 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.103 backup;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
总结
Nginx 负载均衡核心:
- upstream 定义服务器组
- 四种策略:轮询、权重、ip_hash、最少连接
- 健康检查自动摘除故障节点
- 生产环境用权重 + 健康检查就够了
搞懂这些,多台服务器集群就跑起来了。
Nginx 反向代理配置
Nginx 反向代理配置详解
Nginx 反向代理是最常用的服务器配置之一,把请求转发给后端服务。本文讲清楚核心配置。
1. 基本配置
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
2. 传递真实IP
后端服务要拿到用户真实IP,需要配置:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
3. 负载均衡
多台后端服务器,用 upstream 做负载均衡:
upstream backend {
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=2;
}
server {
location / {
proxy_pass http://backend;
}
}
4. 超时设置
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
5. 静态文件处理
静态文件直接由 Nginx 处理,不用转发给后端:
location ~* \.(js|css|png|jpg|gif)$ {
root /data/www;
expires 30d;
}
6. HTTPS 反向代理
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
总结
Nginx 反向代理的核心就是 proxy_pass,配上 proxy_set_header 传递必要信息,再加上超时和静态文件处理,基本够用了。
Nginx 日志分析技巧
Nginx 日志分析常用命令
Nginx 日志是排查问题、分析流量的重要工具。掌握几个常用命令,线上排查效率翻倍。
1. 查看访问量
# 总请求数
wc -l access.log
# 今天的请求数
grep "04/Oct/2026" access.log | wc -l
2. 分析 IP 访问量
# 访问最多的前10个IP
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10
3. 分析 URL 访问量
# 访问最多的前10个URL
awk '{print $7}' access.log | sort | uniq -c | sort -nr | head -10
4. 分析状态码
# 统计各状态码数量
awk '{print $9}' access.log | sort | uniq -c | sort -nr
# 404错误数量
grep " 404 " access.log | wc -l
5. 分析流量
# 总流量
awk '{sum += $10} END {print sum/1024/1024 " MB"}' access.log
6. 实时监控
# 实时查看最新日志
tail -f access.log
# 实时查看502错误
tail -f access.log | grep " 502 "
7. 查找慢请求
# 响应时间超过1秒的请求
awk '$NF > 1' access.log | head -10
8. 排查爬虫
# 百度爬虫访问量
grep "Baiduspider" access.log | wc -l
总结
Nginx 日志分析主要靠 awk + sort + uniq 组合,掌握这几个命令,日常排查基本够用。复杂分析可以用 GoAccess 等可视化工具。