新站刚部署,首页打开 403 Forbidden。403 和 404 不一样,404 是“没找到”,403 是“找到了但不给你看”,所以问题一定出在服务端某一层权限上。Nginx 报 403 的原因集中在三层:文件系统权限、SELinux、Nginx 自身的访问控制规则,按这个顺序查,基本不会漏。
先说最常见的文件系统权限。Nginx worker 进程通常以 nginx 用户跑,它要能穿过站点目录的每一级父目录(父目录必须有 x 执行位),还要能读目标文件(至少 r 位)。你用 root 把文件解压出来的场景最容易踩:文件属于 root 且权限是 600,nginx 用户自然读不到。
# 看 worker 进程的运行用户
ps aux | grep "nginx: worker" | grep -v grep
# 检查站点目录链路上每一级的权限
namei -l /www/example.com/public/index.html
# 修正属主与权限(目录 755、文件 644 是底线)
chown -R nginx:nginx /www/example.com
chmod -R u=rwX,g=rX,o=rX /www/example.com
权限没问题还 403,就要怀疑 SELinux。CentOS、Rocky 这类发行版默认 enforcing,就算你 chmod 777,SELinux 的策略不放过照样 403。验证方法很简单:临时切到 permissive 看 403 是否消失,同时去 audit.log 里确认是否有 denied 记录。确认是 SELinux 后别图省事直接关掉,正确做法是给目录打上 httpd_sys_content_t 上下文。
getenforce # Enforcing 说明在生效
setenforce 0 # 临时放行,403 消失即基本锁定
ausearch -m avc -ts recent | tail -5 # 看审计日志里的 denied 明细
# 确认后恢复 enforcing 并打上下文标签
setenforce 1
semanage fcontext -a -t httpd_sys_content_t "/www/example.com(/.*)?"
restorecon -Rv /www/example.com
前两层都排完还 403,剩下的就是 Nginx 自己的规则了。两种情况:一是配置里有 deny 指令,ngx_http_access_module 的 allow/deny 按顺序匹配,一条 deny all 写在后面会覆盖前面所有 allow;二是请求命中的目录下没有 index 指令指定的文件,而 autoindex 又是默认的 off,Nginx 不愿意给你列目录,就回 403。
# 检查访问控制规则与 index 配置
nginx -T 2>/dev/null | grep -nE "deny|allow|autoindex"
# 用 curl 看响应头,403 前面若有 WWW-Authenticate 是另一回事(auth_basic)
curl -I https://你的域名/
# 快速确认是不是“目录没 index”这种情况:手动访问一个存在的文件
curl -I https://你的域名/index.html # 这个能 200 就是 index 没配对
排查 403 有个原则:从外往里剥。先 curl -I 拿到状态码,再按文件权限、SELinux、Nginx 规则的顺序逐层排除,每改一层验证一次,不要三层一起动。动态权限变更别忘了一步:改完 chmod 或 SELinux 上下文不需要 reload Nginx,它每次请求都会重新走一遍 open,立即生效;改了配置才需要 nginx -t 加 reload。
相关阅读:403 是接入层排查的经典案例。《服务器故障排查总纲:按现象反查的五层定位法》把权限、SELinux、deny 规则这类“看起来一样、病根不同”的故障按层拆开,总纲建议收藏备查。
A5创业网 版权所有