React SPA 部署到 Nginx 的核心原理与 Ubuntu 生产配置
1. 为什么 React 项目不能直接扔进 Nginx 就完事?——从开发服务器到生产环境的本质跨越
你刚用 create-react-app 跑通了第一个 Todo 应用,本地 npm start 一切丝滑,心里一热:“上线!”。于是把 build 目录整个拖进 /var/www/html ,改了下 Nginx 配置, sudo systemctl restart nginx ,浏览器一刷——404。再刷——白屏。再刷——控制台报错 Failed to load resource: the server responded with a status of 404 (Not Found) ,路径指向 /static/js/main.xxxxxx.js 。你盯着这行红字,手悬在键盘上,突然意识到: React 不是静态 HTML,Nginx 也不是文件浏览器 。
这根本不是配置写错了那么简单。这是两种运行范式的碰撞: react-scripts start 启动的是一个带热重载、模块解析、路由代理的全功能开发服务器;而 Nginx 是一个极简、高速、面向 HTTP 协议的反向代理与静态资源服务引擎。它不理解 import ,不执行 JSX ,更不会帮你把 /dashboard/user/123 这种前端路由映射到 index.html 。它只做一件事:收到请求,按路径找文件,有就发,没有就 404。
我第一次部署时也栽在这儿。当时以为只要 build 出来一堆 .js 和 .css ,丢给 Nginx 就万事大吉。结果用户点了个侧边栏菜单,URL 变成 /settings/profile ,刷新一下——404。因为 Nginx 看到这个路径,去 /var/www/html/settings/profile 下找文件,当然找不到。而 React Router 的 BrowserRouter 正是依赖浏览器 History API 来管理这些“伪路径”,它需要所有非 API 请求都 fallback 到 index.html ,由 React 自己解析路由。这个“fallback”机制,就是生产部署里最常被忽略的底层契约。
关键词 React 、 Nginx 、 Ubuntu 在这里不是并列关系,而是层级依赖: React 生成的是单页应用(SPA)结构, Ubuntu 提供的是稳定可靠的 Linux 运行基座,而 Nginx 承担着三重角色——静态资源分发器、前端路由兜底网关、以及后续可能扩展的 API 反向代理入口。跳过任何一层的理解,都会让部署变成一场和 404 的拉锯战。所以,这不是一个“怎么配”的问题,而是一个“为什么必须这样配”的问题。接下来,我们就从 Ubuntu 系统准备开始,一层层拆解这个看似简单、实则精密的交付链条。
2. Ubuntu 环境筑基:不只是装个 Nginx,而是构建可复现的生产基线
很多教程一上来就 sudo apt install nginx ,仿佛 Ubuntu 就是个空白画布。但真实运维中,画布本身就有纹理。Ubuntu 的版本选择、系统更新策略、用户权限模型,直接决定了后续部署的稳定性与可维护性。我见过太多项目,因为用了 Ubuntu 20.04 的旧版 OpenSSL,在接入 HTTPS 时被现代浏览器直接拦截;也见过因未禁用 root SSH 登录,导致服务器被暴力破解后植入挖矿脚本。部署 React 应用的第一步,从来不是写 Nginx 配置,而是把 Ubuntu 这块地基夯得足够结实。
2.1 版本选择与系统初始化:LTS 是铁律,而非选项
截至 2024 年,Ubuntu 22.04 LTS(Jammy Jellyfish)是当前最稳妥的选择。它的生命周期支持到 2027 年 4 月,这意味着关键安全补丁、内核更新、Nginx 主线版本(1.18+)都能得到官方长期维护。而 Ubuntu 24.04 虽已发布,但其生态兼容性(尤其是某些 Node.js 二进制包、Docker 镜像)仍在收敛期,对于生产环境,保守永远优于激进。
初始化一台新 Ubuntu 服务器,我的标准流程是:
# 1. 更新系统索引与核心组件(注意:不立即升级内核,避免意外中断)
sudo apt update && sudo apt upgrade -y
# 2. 安装基础工具链(curl、wget、git、unzip 是后续所有操作的基石)
sudo apt install -y curl wget git unzip vim
# 3. 配置时区与时间同步(Nginx 日志、SSL 证书验证都依赖准确时间)
sudo timedatectl set-timezone Asia/Shanghai
sudo systemctl enable systemd-timesyncd
sudo systemctl start systemd-timesyncd
# 4. 创建专用部署用户(绝对禁止用 root 部署!)
sudo adduser deployer
sudo usermod -aG sudo deployer
# 切换过去,后续所有操作在此用户下进行
su - deployer
提示:
deployer用户不是为了“多此一举”,而是为了建立清晰的责任边界。当某天发现 Nginx 配置被误删,你能立刻定位到是哪个用户的操作日志;当需要审计文件修改记录,sudo journalctl -u nginx --since "2024-05-01"的输出会清晰显示是deployer执行了systemctl reload nginx。这种隔离,是专业运维与“能跑就行”的分水岭。
2.2 Nginx 的安装与最小化加固:拒绝默认配置的诱惑
Ubuntu 官方仓库的 nginx 包( nginx-full )完全满足 React 部署需求,无需源码编译。但安装后,必须立刻进行三项“外科手术式”清理:
-
移除默认站点 :
/etc/nginx/sites-enabled/default是一个充满注释和示例的“教学配置”,它监听 80 端口,返回欢迎页,并包含大量location块。它与你的 React 站点配置冲突,且暴露了 Nginx 版本信息(通过Server头),这是安全扫描器的第一靶子。sudo rm /etc/nginx/sites-enabled/default sudo rm /etc/nginx/sites-available/default -
关闭 Server Token :默认情况下,Nginx 响应头会带上
Server: nginx/1.18.0 (Ubuntu)。攻击者可据此判断你的软件栈版本,寻找已知漏洞。在/etc/nginx/nginx.conf的http块内添加:server_tokens off;这行代码成本为零,却能抹去一个显著的攻击面。
-
启用 Gzip 压缩 :React 构建产物中的
.js和.css文件体积巨大。Nginx 内置的 Gzip 模块能在传输前实时压缩,通常可将 JS 文件体积减少 60%-70%。在http块中确认以下配置存在(Ubuntu 默认已开启,但需检查):gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 1000;
完成这三步,你的 Nginx 就不再是那个“开箱即用”的玩具,而是一个精简、沉默、高效的生产级服务引擎。它不再主动说话( server_tokens off ),只在必要时高效传递( gzip ),并且清除了所有干扰项(移除 default)。这才是 React 应用值得托付的基础设施。
3. React 构建产物的深度解析: build 目录里的每一个文件都在诉说部署逻辑
npm run build 这条命令,是连接开发与生产的魔法咒语。但它吐出的 build 目录,绝非一个简单的“打包好”的文件夹。它是一个经过精心编排的、自洽的前端运行时环境。理解其中每个文件的角色与约束,是写出正确 Nginx 配置的前提。我曾花整整一天,用 tree -L 3 build/ 命令逐层分析一个中型 React 项目的构建产物,最终发现了一个被忽略的细节: manifest.json 文件的 start_url 字段,它直接决定了 Nginx 的 root 指令该指向哪里。
3.1 build 目录的骨架与灵魂: index.html 与 static 的共生关系
一个典型的 build 目录结构如下:
build/
├── index.html # 入口 HTML,所有 JS/CSS 的加载起点
├── manifest.json # PWA 清单,定义应用名称、图标、启动 URL
├── robots.txt # 搜索引擎爬虫指令
├── static/ # 所有编译后的静态资源
│ ├── css/ # CSS 文件(含哈希名,如 main.abc123.css)
│ └── js/ # JS 文件(含哈希名,如 main.def456.js)
└── asset-manifest.json # 资源映射表,记录哈希文件与原始文件名的对应关系
关键点在于 index.html 的内容。打开它,你会看到类似这样的 <script> 标签:
<script src="/static/js/main.abc123.js"></script>
注意那个开头的 / 。这表示这是一个 绝对路径 ,它告诉浏览器:“请从网站根目录( / )开始,去找 static/js/main.abc123.js 这个文件”。这意味着,无论用户当前访问的是 / 、 /about 还是 /dashboard ,浏览器发起的 JS 请求,都是 GET /static/js/main.abc123.js 。因此,Nginx 的 root 指令,必须精确地指向 build 目录的 父目录 ,而不是 build 目录本身。
假设你的项目部署在 /var/www/my-react-app ,那么 build 目录就在 /var/www/my-react-app/build 。此时,Nginx 的 root 必须设为 /var/www/my-react-app/build 。如果错误地设为 /var/www/my-react-app ,那么当浏览器请求 /static/js/main.abc123.js 时,Nginx 会在 /var/www/my-react-app/static/js/... 下寻找,而实际文件在 /var/www/my-react-app/build/static/js/... ,必然 404。
3.2 manifest.json 的 start_url :一个被严重低估的部署开关
manifest.json 是 Progressive Web App (PWA) 的核心配置文件。其中 start_url 字段定义了当用户从桌面图标或书签启动应用时,浏览器应该加载的初始 URL。它的值通常是 . 或 / 。
- 如果
start_url: ".",它表示“相对于当前页面路径”。这在开发环境下没问题,但在 Nginx 部署时,它会导致一个诡异现象:当用户从/dashboard页面刷新,PWA 启动时,start_url会被解析为/dashboard/,然后尝试加载/dashboard/index.html,这显然不存在。 - 如果
start_url: "/",它明确指定根路径,确保无论从何处启动,都回到应用的主入口。
因此,在 public/manifest.json 中,务必确保:
{
"start_url": "/",
"display": "standalone"
}
这个看似微小的改动,能避免大量因 PWA 启动逻辑引发的 404 问题。它不是一个“锦上添花”的特性,而是 React 应用在生产环境中保持路由一致性的底层保障。
3.3 asset-manifest.json :构建时的“地图”,部署时的“路标”
这个文件是 create-react-app 构建过程的副产品,它以 JSON 格式记录了所有产出文件的哈希映射关系。例如:
{
"files": {
"main.js": "static/js/main.abc123.js",
"main.css": "static/css/main.def456.css",
"index.html": "index.html"
}
}
它的主要价值在于构建时的缓存控制(通过哈希名实现文件内容变更即 URL 变更),但在部署阶段,它为我们提供了一个重要的验证手段: 你可以用它来校验 Nginx 是否真的能访问到所有必需的文件 。
一个简单的 Bash 脚本就能完成这项工作:
#!/bin/bash
# check-build.sh
BUILD_DIR="/var/www/my-react-app/build"
MANIFEST="$BUILD_DIR/asset-manifest.json"
if [ ! -f "$MANIFEST" ]; then
echo "Error: $MANIFEST not found!"
exit 1
fi
# 提取所有 files 键下的路径
FILES=$(jq -r '.files | to_entries[] | .value' "$MANIFEST")
for file in $FILES; do
if [ ! -f "$BUILD_DIR/$file" ]; then
echo "MISSING: $BUILD_DIR/$file"
fi
done
将此脚本放在部署流程的最后一步,它能瞬间告诉你,是否遗漏了某个 CSS 文件,或者 index.html 是否被意外覆盖。这种基于事实的验证,远比“我觉得应该都传上去了”要可靠得多。
4. Nginx 配置的终极解法:一份能扛住所有 React 路由的 location 块
现在,我们终于来到核心——Nginx 配置。网上流传着无数种写法,从最简陋的 root /path/to/build; ,到复杂的 try_files 嵌套。但真相是: 99% 的 React SPA 部署,只需要一个精准的 location / 块,配合一个正确的 try_files 指令 。其他所有花哨的 location ~* \.js$ 或 location /api ,都是为未来扩展预留的接口,而非当前部署的必需品。
4.1 try_files 的工作原理:一次请求,三次试探
try_files 是 Nginx 处理前端路由的“瑞士军刀”。它的语法是 try_files file1 file2 ... uri; ,意思是:“依次检查 file1 , file2 ,如果都不存在,就把请求重写(rewrite)到 uri ”。
对于 React,我们的目标是: 所有对静态资源( .js , .css , .png )的请求,正常返回;所有对前端路由( /dashboard , /user/123 )的请求,都返回 index.html ,交由 React Router 处理 。
因此,最核心的配置是:
location / {
try_files $uri $uri/ /index.html;
}
让我们拆解这行代码的每一次试探:
-
$uri:这是 Nginx 接收到的原始 URI。如果用户请求https://example.com/static/js/main.abc123.js,$uri就是/static/js/main.abc123.js。Nginx 会去root指定的目录下,查找这个路径对应的物理文件。如果存在(它确实存在),就直接返回,结束流程。 -
$uri/:这是在$uri后加一个/。它用于处理目录请求。例如,用户请求https://example.com/assets/,Nginx 会去查找assets/这个目录是否存在。对于 React 项目,这通常不匹配,进入下一步。 -
/index.html:这是兜底项。当以上两个都失败时,Nginx 会将请求内部重写为/index.html,并再次匹配location /。由于index.html是一个真实存在的文件,Nginx 会找到它并返回。浏览器拿到index.html后,执行其中的 JavaScript,React Router 读取当前 URL(/dashboard),并渲染对应的组件。
这个逻辑完美闭环。它不需要正则表达式,不依赖复杂的 if 判断,性能极高,且完全符合 HTTP 协议规范。
4.2 完整的、可直接复制粘贴的 Nginx 站点配置
下面是一份经过我线上项目千锤百炼的完整配置,保存为 /etc/nginx/sites-available/my-react-app :
# /etc/nginx/sites-available/my-react-app
# 一个为 React SPA 量身定制的、最小可行的 Nginx 配置
server {
# 监听标准 HTTP 端口
listen 80;
# 替换为你自己的域名,或使用 IP 地址
server_name example.com;
# 指向 build 目录的绝对路径
# 注意:这里必须是 build 目录本身,不是其父目录!
root /var/www/my-react-app/build;
index index.html;
# 关键:处理所有前端路由
location / {
try_files $uri $uri/ /index.html;
}
# 优化:为静态资源设置长缓存
# React 构建产物的文件名已包含哈希,可以放心缓存一年
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 安全:禁止访问敏感文件
location ~ /\.ht {
deny all;
}
# 安全:禁止访问构建产物中的源码映射文件(.map)
location ~* \.map$ {
deny all;
}
}
启用此配置:
# 创建符号链接
sudo ln -sf /etc/nginx/sites-available/my-react-app /etc/nginx/sites-enabled/
# 测试配置语法
sudo nginx -t
# 重新加载 Nginx,无需重启,零停机
sudo systemctl reload nginx
注意:
expires 1y这个指令,是针对js|css|png等静态资源的。它利用了create-react-app的哈希命名机制——文件内容变了,文件名就变,URL 就变。因此,浏览器可以永久缓存,不用担心内容过期。这是提升首屏加载速度最有效的手段之一,比任何 CDN 都来得直接。
4.3 为什么不用 alias ?一个关于路径映射的致命误区
新手常犯的一个错误,是试图用 alias 指令来“映射”路径:
# ❌ 错误示范!
location / {
alias /var/www/my-react-app/build/;
}
alias 的行为是: 将 location 的匹配路径,完全替换为 alias 指定的路径 。也就是说, location / 匹配所有请求, alias 会把 / 替换成 /var/www/my-react-app/build/ ,那么请求 /static/js/main.js 就会去 /var/www/my-react-app/build/static/js/main.js 查找——这看起来是对的。
但问题出在 index.html 上。当用户访问根路径 / 时, alias 会把 / 替换成 /var/www/my-react-app/build/ ,Nginx 会去这个目录下找一个叫 index.html 的文件。然而, /var/www/my-react-app/build/ 是一个目录,里面并没有一个叫 index.html 的文件,它有的是 /var/www/my-react-app/build/index.html 。 alias 的路径拼接逻辑在这里失效了。
root 指令则不同,它是“根目录”,Nginx 会把 location 的路径 追加 到 root 后面。 root /var/www/my-react-app/build; + location / + 请求 / = /var/www/my-react-app/build/ + / = /var/www/my-react-app/build// ,Nginx 会自动规范化为 /var/www/my-react-app/build/index.html 。这就是 root 与 alias 的本质区别: root 是追加, alias 是替换。对于 React 这种需要同时服务根文件和子路径文件的场景, root 是唯一安全的选择。
5. 实战排障:从 404 白屏到控制台报错的完整排查链路
即使你严格按照上述步骤操作,部署后依然可能出现各种诡异问题。这时候,一套标准化的排查流程,比任何“万能解决方案”都管用。我把它总结为“四层漏斗法”:从网络层、Nginx 层、浏览器层、到 React 层,层层过滤,直达病灶。
5.1 第一层:网络与 DNS —— 确认请求是否真正抵达服务器
这是最容易被忽视,却最基础的一层。很多“404”问题,根源在于请求压根没走到 Nginx。
- 检查端口监听 :在服务器上执行
sudo ss -tlnp | grep :80。你应该看到nginx进程正在监听*:80。如果没有,说明 Nginx 没有成功启动,或配置有严重语法错误(nginx -t会告诉你)。 - 检查防火墙 :Ubuntu 默认使用
ufw。执行sudo ufw status,确认80端口是ALLOW状态。如果不是,运行sudo ufw allow 80。 - 本地
curl测试 :在服务器本机执行curl -I http://localhost。如果返回HTTP/1.1 200 OK,说明 Nginx 工作正常;如果返回Connection refused,说明服务没起来;如果返回404,说明 Nginx 起来了,但配置指向了错误的root。
提示:永远先在服务器本地测试。这能瞬间排除 DNS 解析、公网路由、CDN 缓存等外部因素,把问题域锁定在你的服务器内部。
5.2 第二层:Nginx 日志 —— 服务器视角的“监控录像”
Nginx 的 access.log 和 error.log 是最忠实的记录者。它们不会撒谎,只会告诉你发生了什么。
-
access.log:记录每一次成功的 HTTP 请求。格式通常是IP - - [时间] "METHOD PATH PROTOCOL" STATUS SIZE "REFERER" "USER-AGENT"。当你在浏览器看到 404,立刻去看这条日志。如果日志里没有这条记录,说明请求被防火墙或 DNS 拦截了;如果日志里有,且STATUS是404,那就看PATH是什么。是/?还是/static/js/main.js?这直接指明了问题出在root路径,还是try_files配置。 -
error.log:记录所有错误。最常见的错误是open() "/var/www/my-react-app/build/static/js/main.js" failed (2: No such file or directory)。这个错误信息无比珍贵,它精确地告诉你,Nginx 去哪个路径找了哪个文件,结果没找到。你只需把这个路径和你build目录的实际路径对比,就能立刻发现root配置是多了/build,还是少了/build。
一个高效的排查命令是:
# 实时跟踪最新的 10 条错误日志
sudo tail -n 10 /var/log/nginx/error.log
# 或者,当问题发生时,实时监控
sudo tail -f /var/log/nginx/error.log
5.3 第三层:浏览器开发者工具 —— 客户端的“显微镜”
F12 打开开发者工具,切换到 Network 标签页,然后刷新页面。这是诊断前端问题的黄金视图。
- 查看
index.html的状态码 :如果它是200,说明 Nginx 成功返回了 HTML。如果它是404,问题出在root或index指令。 - 查看
.js和.css文件的状态码 :如果它们是404,问题出在root路径或try_files的第一层$uri匹配失败。此时,点击这个 404 请求,看Headers标签页里的Request URL是什么。它应该是http://your-domain.com/static/js/main.xxx.js。然后,用ls -l /var/www/my-react-app/build/static/js/去服务器上确认这个文件是否存在。 - 查看
Console标签页 :如果index.html和main.js都是200,但页面是白屏,Console里大概率会有Uncaught SyntaxError: Unexpected token '<'。这个错误意味着,浏览器期望加载一个 JS 文件,但 Nginx 返回了index.html的 HTML 内容(因为try_files把它兜底了)。这通常发生在main.js的 URL 路径写错了,比如src="js/main.js"(相对路径),而 Nginx 的root指向了错误的位置,导致 Nginx 去找/js/main.js,找不到,就返回了index.html,于是 JS 解析器看到了<符号,报错。
5.4 第四层:React 构建配置 —— 源头上的“基因检测”
如果前三层都没发现问题,那就要怀疑源头了。 create-react-app 的 homepage 字段,是决定所有静态资源路径的“总开关”。
在 package.json 中,检查是否有:
{
"homepage": "https://example.com/my-app"
}
如果设置了这个字段, npm run build 会生成所有资源路径都以 /my-app/ 为前缀的 HTML。例如, <script src="/my-app/static/js/main.js"> 。此时,你的 Nginx root 就不能再指向 /var/www/my-react-app/build ,而必须指向 /var/www/my-react-app ,并且 location 块需要调整为:
location /my-app/ {
alias /var/www/my-react-app/build/;
try_files $uri $uri/ /my-app/index.html;
}
这是一个完全不同的部署模式,称为“子路径部署”。它适用于一个服务器托管多个 React 应用的场景。但如果你没有在 package.json 中设置 homepage ,就绝对不要用 alias ,否则必踩坑。
我建议,除非有明确的子路径需求,否则永远将 homepage 设为 "." 或干脆删除它。这样,构建产物就是为根路径 ( / ) 优化的,Nginx 配置也最简洁、最健壮。
6. 进阶实践:从单机部署到生产就绪的平滑演进
当你的 React 应用在单台 Ubuntu 服务器上稳定运行后,真正的挑战才刚刚开始:如何让它具备高可用、可扩展、易维护的生产级能力?这并非一蹴而就,而是一个循序渐进的过程。我将分享几个最关键的、从第一天起就该考虑的演进方向。
6.1 构建与部署的自动化:告别手动 scp 和 rsync
手动上传 build 目录,是效率最低、风险最高的方式。一次 rm -rf 的误操作,就能让线上服务瞬间瘫痪。自动化部署的核心思想是: 将“构建”与“部署”分离,并通过可重复、可审计的脚本驱动 。
一个最轻量的方案,是使用 GitHub Actions。在你的 React 项目根目录创建 .github/workflows/deploy.yml :
name: Deploy to Ubuntu Server
on:
push:
branches: [main]
paths: ["src/**", "public/**", "package.json"]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install and Build
run: |
npm ci
npm run build
- name: Deploy via SSH
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
source: "build/"
target: "/var/www/my-react-app/build/"
这个工作流会在每次向 main 分支推送代码时,自动在 GitHub 的服务器上完成 npm run build ,然后将 build 目录安全地复制到你的 Ubuntu 服务器。 secrets 是 GitHub 的加密变量,用于存储服务器地址、用户名和私钥。整个过程无需人工干预,且每次部署都有完整的 Git 提交记录可追溯。
6.2 HTTPS 的强制实施: Let's Encrypt 与 certbot 的无缝集成
HTTP 是不安全的。现代浏览器会对所有 HTTP 站点标记为“不安全”,这会严重影响用户信任。强制 HTTPS 不再是可选项,而是底线。
certbot 是 Let's Encrypt 的官方客户端,它能免费、自动地为你的域名颁发和续期 SSL 证书。在 Ubuntu 上安装并配置它,只需几步:
# 1. 安装 certbot
sudo apt install -y certbot python3-certbot-nginx
# 2. 获取证书(certbot 会自动修改你的 Nginx 配置,添加 443 端口监听和证书路径)
sudo certbot --nginx -d example.com
# 3. certbot 会自动设置一个每日的 systemd timer 来续期证书
# 你可以手动测试续期是否工作
sudo certbot renew --dry-run
执行完 certbot --nginx 后,它会生成一个全新的 server 块,监听 443 端口,并将原来的 80 端口 server 块修改为一个简单的重定向:
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
这个重定向,确保了所有 HTTP 流量都被强制升级到 HTTPS。 certbot 的伟大之处在于,它把一个原本极其繁琐的证书申请、配置、续期流程,压缩成了一个命令。它不是“高级技巧”,而是现代 Web 开发者的必备基础设施。
6.3 监控与告警:让服务器自己“说话”
一个没有监控的生产系统,就像一辆没有仪表盘的汽车。你不知道油量还剩多少,不知道发动机温度是否异常,只能靠感觉。
最简单的监控,是 nginx 自带的 stub_status 模块。它提供了一个极简的文本接口,返回当前 Nginx 的连接数、请求数等基本指标。启用它,只需在你的 server 块内添加:
location /nginx_status {
stub_status;
allow 127.0.0.1; # 只允许本地访问
deny all;
}
然后,你可以用一个简单的 curl http://localhost/nginx_status 来获取数据。但这只是第一步。更进一步,你可以用 Prometheus (一个开源监控系统)来抓取这个指标,再用 Grafana (一个开源可视化平台)来绘制漂亮的图表,甚至设置告警:当 5xx 错误率超过 1%,就发邮件给你。
这个演进路径是清晰的:从手动 curl ,到脚本定时采集,再到专业的监控栈。每一步都让你对系统的健康状况多一分掌控。而这一切的起点,就是你在 nginx.conf 里添加的那一行 stub_status 。
我在实际操作中发现,部署的成败,往往不在于技术有多炫酷,而在于你是否愿意为那些“看不见”的事情投入精力——比如写一个 10 行的部署脚本,比如花 15 分钟配置好 certbot ,比如每天花 30 秒看看 nginx error.log 。这些微小的习惯,日积月累,就是区分一个“能跑就行”的开发者,和一个“生产就绪”的工程师的鸿沟。
更多推荐




所有评论(0)