diff --git a/nginx/SKILL.md b/nginx/SKILL.md index e9829ba..debd2c2 100644 --- a/nginx/SKILL.md +++ b/nginx/SKILL.md @@ -1,168 +1,48 @@ --- name: nginx -description: Nginx Web 服务器管理 — 站点配置、SSL 证书管理、反向代理、负载均衡、热重载、 Let's Encrypt 自动续期 +description: Nginx 站点配置、反向代理、SSL 证书、热重载 --- -# Nginx 管理助手 +# Nginx 管理 -## 功能概述 +## 快速命令 -本 Skill 提供完整的 Nginx 操作能力,包括站点管理、SSL/HTTPS 配置、反向代理、负载均衡、Let's Encrypt 证书管理等。支持直接编辑配置文件并热重载生效。 +| 命令 | 说明 | +|------|------| +| `sudo nginx -t` | 测试配置语法 | +| `sudo systemctl reload nginx` | 热重载生效 | +| `ls /etc/nginx/sites-enabled/` | 查看已启用站点 | +| `sudo nginx -T` | 查看完整加载配置 | -## 系统环境(用户环境) +## 站点配置 -``` -系统:Ubuntu Linux -Nginx 版本:1.24.0 -配置目录:/etc/nginx/ -主配置:/etc/nginx/nginx.conf -站点配置:/etc/nginx/sites-available/ (可用) / sites-enabled/ (启用) -额外配置:/etc/nginx/conf.d/ -SSL 模板:/etc/letsencrypt/options-ssl-nginx.conf -DH 参数:/etc/letsencrypt/ssl-dhparams.pem -日志路径:/var/log/nginx/error.log, /var/log/nginx/access.log -``` +站点配置放在 `/etc/nginx/sites-available/`,软链接到 `/etc/nginx/sites-enabled/` 启用。 -## 一、基础操作 +### 反向代理模板 -### 查看 Nginx 状态 - -```bash -# 查看运行状态 -sudo systemctl status nginx - -# 测试配置语法 -sudo nginx -t - -# 查看已加载的配置 -sudo nginx -T - -# 查看版本和编译参数 -nginx -V -``` - -### 启停管理 - -```bash -# 启动 -sudo systemctl start nginx - -# 停止 -sudo systemctl stop nginx - -# 重启(完全停止再启动) -sudo systemctl restart nginx - -# 热重载(加载新配置,不中断连接) -sudo systemctl reload nginx - -# 禁用/启用开机自启 -sudo systemctl disable nginx -sudo systemctl enable nginx -``` - -## 二、站点管理 - -### 创建新站点 - -**步骤:** -1. 在 `/etc/nginx/sites-available/` 创建配置文件 -2. 在 `/etc/nginx/sites-enabled/` 创建软链接 -3. 测试配置:`sudo nginx -t` -4. 重载生效:`sudo systemctl reload nginx` - -**示例 — 静态网站:** ```nginx server { listen 80; - server_name example.com www.example.com; - root /var/www/example.com; - index index.html index.htm; - - location / { - try_files $uri $uri/ =404; - } -} -``` - -**示例 — HTTP 跳转到 HTTPS:** -```nginx -server { - listen 80; - server_name example.com www.example.com; + server_name www.xsinfo.vip; return 301 https://$host$request_uri; } -``` -### 反向代理配置 - -```nginx server { - listen 80; - server_name api.example.com; + listen 443 ssl http2; + server_name www.xsinfo.vip; + + ssl_certificate /etc/letsencrypt/live/www.xsinfo.vip/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/www.xsinfo.vip/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { - proxy_pass http://127.0.0.1:8080; + proxy_pass http://127.0.0.1:1234; proxy_http_version 1.1; 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; - - # WebSocket 支持 - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # 超时设置 - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - } -} -``` - -### HTTPS + SSL 配置 - -```nginx -server { - listen 443 ssl http2; - server_name example.com www.example.com; - - # SSL 证书路径(Let's Encrypt) - ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; - - # 使用 Certbot 提供的安全 SSL 配置模板 - include /etc/letsencrypt/options-ssl-nginx.conf; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - - root /var/www/example.com; - index index.html; - - location / { - try_files $uri $uri/ /index.html; - } -} -``` - -### 负载均衡 - -```nginx -upstream backend { - least_conn; # 最少连接优先 - server 10.0.0.2:8080 weight=3; - server 10.0.0.3:8080 weight=2; - server 10.0.0.4:8080 backup; # 备用服务器 -} - -server { - listen 80; - server_name example.com; - - location / { - proxy_pass http://backend; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; } } ``` @@ -170,347 +50,27 @@ server { ### 启用/禁用站点 ```bash -# 启用站点(创建软链接) sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite - -# 禁用站点(删除软链接) sudo rm /etc/nginx/sites-enabled/mysite - -# 测试并重载 -sudo nginx -t && sudo systemctl reload nginx ``` -### 删除站点 +## SSL 证书 ```bash -# 1. 禁用站点 -sudo rm /etc/nginx/sites-enabled/mysite +# 申请 Let's Encrypt 证书 +sudo certbot --nginx -d www.xsinfo.vip -# 2. 删除配置文件(可选,保留备份) -sudo rm /etc/nginx/sites-available/mysite - -# 3. 重载 -sudo systemctl reload nginx -``` - -## 三、SSL / HTTPS 管理 - -### 查看已有证书 - -```bash -# Let's Encrypt 证书目录 -ls /etc/letsencrypt/live/ - -# 查看证书到期时间 -sudo certbot certificates - -# 或者手动查看 -openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates -``` - -### 申请 Let's Encrypt 证书(Certbot) - -```bash -# 安装 certbot(如未安装) -sudo apt install certbot python3-certbot-nginx - -# 为单个域名申请证书 -sudo certbot --nginx -d example.com -d www.example.com - -# 自动配置 Nginx(Certbot 会修改配置文件) -# 或使用 --nginx 参数让它自动配置 SSL - -# 仅获取证书,不修改 Nginx 配置 -sudo certbot certonly --nginx -d example.com -``` - -### 手动配置 SSL(已有证书) - -在站点配置中加入: -```nginx -listen 443 ssl http2; -ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; -include /etc/letsencrypt/options-ssl-nginx.conf; -ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; -``` - -### 强制 HTTPS 跳转 - -```nginx -server { - listen 80; - server_name example.com www.example.com; - return 301 https://$host$request_uri; -} -``` - -### 证书自动续期 - -Let's Encrypt 证书有效期 90 天,Certbot 安装后自动配置定时任务: - -```bash -# 查看自动续期配置 +# 续期测试 sudo certbot renew --dry-run -# 手动触发续期 -sudo certbot renew - -# 查看续期定时任务 -sudo systemctl list-timers | grep certbot +# 查看已有证书 +sudo certbot certificates ``` -### SSL 证书检查 +## 常见问题 -```bash -# 检查 SSL 配置是否正确 -openssl s_client -connect example.com:443 -servername example.com - -# 查看证书信息 -openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep -E "Issuer|Subject|Validity" -``` - -## 四、反向代理和 upstream 进阶 - -### 长连接 upstream - -```nginx -upstream api_backend { - keepalive 32; # 保持长连接数 - - server 127.0.0.1:8001; - server 127.0.0.1:8002; -} - -server { - location /api/ { - proxy_pass http://api_backend; - proxy_http_version 1.1; - proxy_set_header Connection ""; - } -} -``` - -### 路径重写 - -```nginx -location /api/v1/ { - rewrite ^/api/v1/(.*)$ /api/$1 break; - proxy_pass http://127.0.0.1:8080; -} -``` - -### WebSocket 代理 - -```nginx -location /ws/ { - proxy_pass http://127.0.0.1:9000; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_read_timeout 86400; -} -``` - -### 限制访问(IP 白名单) - -```nginx -location /admin/ { - allow 192.168.1.0/24; - allow 10.0.0.0/8; - deny all; - - proxy_pass http://127.0.0.1:8080; -} -``` - -## 五、日志和调试 - -### 查看日志 - -```bash -# 错误日志 -sudo tail -20 /var/log/nginx/error.log - -# 访问日志 -sudo tail -20 /var/log/nginx/access.log - -# 实时查看访问日志 -sudo tail -f /var/log/nginx/access.log - -# 实时查看错误日志 -sudo tail -f /var/log/nginx/error.log -``` - -### 查看连接数 - -```bash -# 查看 Nginx 进程连接数 -sudo ss -s - -# 查看连接状态 -sudo netstat -anp | grep nginx -``` - -### 常用调试命令 - -```bash -# 完整测试并显示配置 -sudo nginx -T - -# 检查配置语法(不检查合法性) -sudo nginx -t - -# 查看已启用的站点 -ls /etc/nginx/sites-enabled/ - -# 查看默认 SSL 配置 -cat /etc/letsencrypt/options-ssl-nginx.conf -``` - -## 六、工作流程 - -### 创建新站点(完整流程) - -1. **创建目录**:`sudo mkdir -p /var/www/example.com` -2. **编写配置**:在 `/etc/nginx/sites-available/example.com` 创建配置 -3. **创建软链接**:`sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com` -4. **测试**:`sudo nginx -t` -5. **重载**:`sudo systemctl reload nginx` -6. **如需 HTTPS**:执行 `sudo certbot --nginx -d example.com -d www.example.com` - -### 修改站点配置(完整流程) - -1. **编辑配置**:`sudo nano /etc/nginx/sites-available/example.com` -2. **测试**:`sudo nginx -t` -3. **重载**:`sudo systemctl reload nginx` -4. **验证**:检查 `sudo systemctl status nginx` - -### 启用 HTTPS(已有站点) - -1. **申请证书**:`sudo certbot --nginx -d example.com -d www.example.com` -2. **Certbot 自动**:修改配置文件,添加 HTTPS server 块,自动配置重定向 -3. **验证**:`sudo systemctl reload nginx && openssl s_client -connect example.com:443` - -## 七、安全最佳实践 - -1. **使用 TLS 1.2+**:ssl_protocols 仅启用 TLSv1.2 TLSv1.3 -2. **使用 Certbot 配置模板**:`include /etc/letsencrypt/options-ssl-nginx.conf` -3. **启用 HSTS**(可选):`add_header Strict-Transport-Security "max-age=31536000" always;` -4. **禁止显示 Nginx 版本**:`server_tokens off;`(在主配置 http 块中) -5. **定期更新证书**:配置自动续期后无需手动操作 -6. **限制请求方法**:仅允许 GET/POST/HEAD - ```nginx - if ($request_method !~ ^(GET|POST|HEAD)$) { - return 405; - } - ``` - -## 八、故障排查 - -### 反向代理常见错误 - -#### "URL 拼写可能存在错误" - -这个错误**不是 Nginx 本身返回的**,而是后端服务(如 Spring Boot、Node.js、Vite 等)返回的。 - -**排查步骤:** -```bash -# 第1步:直接测试后端服务(排除 Nginx 影响) -curl -v http://127.0.0.1:1234/ - -# 如果直接访问也报错 → 问题在后端,与 Nginx 无关 -# 如果直接访问正常 → 问题在 Nginx 配置 -``` - -#### proxy_pass 路径陷阱 - -```nginx -# ❌ 错误:末尾多了斜杠,会把 /app/ 替换成 / -location /app/ { - proxy_pass http://127.0.0.1:8080/; -} - -# ✅ 正确:末尾无斜杠,保持原路径 -location /app/ { - proxy_pass http://127.0.0.1:8080; # 不加 / -} - -# 特殊情况:需要去掉前缀时 -location /api/ { - # rewrite + proxy_pass 末尾斜杠 = 去掉 /api 前缀 - rewrite ^/api/(.*)$ /$1 break; - proxy_pass http://127.0.0.1:8080/; # 这里需要斜杠 -} -``` - -#### 必备的代理请求头 - -```nginx -location / { - proxy_pass http://127.0.0.1:1234; - proxy_http_version 1.1; - 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; -} -``` - -### 配置测试失败 - -```bash -# 查看详细错误 -sudo nginx -t 2>&1 - -# 查看错误日志 -sudo tail -30 /var/log/nginx/error.log -``` - -### 服务启动失败 - -```bash -# 查看 systemctl 日志 -sudo journalctl -xe --no-pager | tail -50 - -# 查看端口占用 -sudo lsof -i :80 -sudo lsof -i :443 -``` - -### 502 Bad Gateway - -1. 检查后端服务是否运行:`curl -I http://127.0.0.1:8080` -2. 检查 upstream 配置 -3. 查看错误日志确认原因 - -### 证书过期 - -```bash -# 强制续期 -sudo certbot renew --force-renewal - -# 或者重新申请 -sudo certbot certonly --nginx -d example.com -``` - -### 快速诊断命令 - -```bash -# 1. 检查 Nginx 和后端端口 -sudo lsof -i :1234 -sudo netstat -tlnp | grep nginx - -# 2. 直接测试后端 -curl -v http://127.0.0.1:1234/ - -# 3. 测试 Nginx 配置 -sudo nginx -t - -# 4. 查看实时日志 -sudo tail -f /var/log/nginx/access.log -sudo tail -f /var/log/nginx/error.log - -# 5. 查看完整的已加载配置 -sudo nginx -T -``` \ No newline at end of file +| 问题 | 排查 | +|------|------| +| 502 Bad Gateway | `curl http://127.0.0.1:1234` 确认后端运行 | +| 配置无效 | `sudo nginx -t` 检查语法 | +| proxy_pass 路径错 | 末尾斜杠含义不同:无斜杠保持路径,有斜杠替换路径 | \ No newline at end of file