核心是确认worker用户、proxy_cache_path路径、proxy_temp_path路径三者权限匹配:逐级检查每层目录的x(进入)和w(写入)权限,确保属主一致,同时排查selinux/apparmor拦截。

排查 Nginx proxy_cache 写入临时文件权限不足的问题,核心是确认缓存路径、临时目录、worker 进程用户三者之间的权限匹配是否正确。Nginx 在写缓存时会先写入临时文件(如 proxy_temp 下的随机名文件),再原子重命名为最终缓存键路径;若临时目录不可写,就会静默失败或报错(取决于日志级别)。
确认 Nginx worker 进程运行用户
执行 ps aux | grep nginx,查看 master 和 worker 进程的 USER 列(通常是 www-data、nginx 或 daemon)。注意:worker 进程用户由配置中 user 指令指定,而非启动脚本或 systemd 用户。若未显式配置 user,默认为 nobody(极不推荐)。
- 检查主配置:
grep "^user" /etc/nginx/nginx.conf - 确保该用户对后续所有目录有读、写、执行(进入目录)权限
检查 proxy_cache_path 中的 path 和 proxy_temp_path
proxy_cache_path 的 path 是最终缓存存放目录,但写入过程依赖 proxy_temp_path(或默认的 proxy_temp 子目录)。二者必须独立检查权限:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 运行
nginx -T | grep -E "(proxy_cache_path|proxy_temp_path)"获取实际路径 - 例如:
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=mycache:10m;→ 主目录是/var/cache/nginx/proxy - 默认
proxy_temp_path是/var/cache/nginx/proxy_temp(与 cache_path 同级),除非显式配置了proxy_temp_path - 用
ls -ld /var/cache/nginx /var/cache/nginx/proxy /var/cache/nginx/proxy_temp查看属主和权限
验证目录权限与 SELinux/AppArmor(如启用)
即使属主正确,也可能因权限位或强制访问控制被拦截:
- 每个目录需至少
drwxr-xr-x(755),且属主为 worker 用户;子目录可更宽松,但父目录必须允许进入(x 权限) - 常见错误:
/var/cache/nginx属主是root:root且权限为700→ worker 用户无法进入 - SELinux:运行
ausearch -m avc -ts recent | grep nginx,若看到denied { write },需修复上下文,例如:sudo semanage fcontext -a -t httpd_cache_t "/var/cache/nginx(/.*)?",然后restorecon -Rv /var/cache/nginx - AppArmor(Ubuntu/Debian):检查
/etc/apparmor.d/usr.sbin.nginx是否放行对应路径
复现并观察错误日志
主动触发一次缓存未命中请求(如加 Cache-Control: no-cache 或清空本地缓存),再查 Nginx 错误日志:
- 在
http或location块中临时添加proxy_cache_bypass 1;确保走缓存逻辑 - 用
curl -I http://your-site/发起请求 - 立刻检查
error_log(通常/var/log/nginx/error.log),搜索关键词:open() "/var/cache/nginx/proxy_temp/...、mkdir() "/var/cache/nginx/proxy/...、Permission denied - 若无明确报错,将 error_log 级别临时调高:
error_log /var/log/nginx/error.log debug;(仅调试用,避免线上开启)
不复杂但容易忽略:Nginx 不会在缓存写入失败时返回 500,而是降级为不缓存、直接回源,表现就是“缓存始终不生效”,所以必须结合日志和目录状态交叉验证。










