ACME HTTP-01 验证返回 403 的本质是 Nginx worker 进程(如 www-data)无权读取 .well-known/acme-challenge/ 路径下文件,需从运行用户、目录权限链(每级必须含 x)、属主归属、Nginx 配置拦截及 SELinux 等五层逐项排查验证。

ACME 验证返回 403 错误,本质是 Let’s Encrypt 的 HTTP-01 挑战请求被 Nginx 拒绝访问 .well-known/acme-challenge/ 下的验证文件。这不是“找不到”,而是“不给读”——权限问题必须从 Nginx worker 进程视角出发,逐层验证。
确认 Nginx 实际工作用户
配置文件里的 user 指令可能未生效,得看真实运行身份:
- 运行
ps -eo pid,user,comm,args | grep nginx | grep -v master,找出 worker 进程的 USER(常见为www-data或nginx) - 别依赖
grep "user " /etc/nginx/nginx.conf,它可能被注释、未加载,或被 systemd 启动脚本覆盖 - 若用 acme.sh 的 webroot 模式,可临时加一行 PHP 脚本验证:
<?php echo posix_getpwuid(posix_geteuid())['name']; ?>
检查 .well-known/acme-challenge 目录权限链
Linux 中访问文件需路径上每一级目录都具备执行(x)权限,缺一不可:
- 假设网站根目录是
/home/www.example.com,则完整路径为/home/www.example.com/.well-known/acme-challenge - 逐级执行
ls -ld /home /home/www.example.com /home/www.example.com/.well-known /home/www.example.com/.well-known/acme-challenge - 重点看每级权限位是否含
x:例如drw-r--r--表示无x,Nginx 根本进不去该目录 - 常见陷阱:父目录属主是
root,权限750,而 Nginx 用户既非 owner 也非 group 成员
验证并修复归属与最小权限
修复不是简单 chmod 777,而是精准授权:
- 把整个
.well-known目录及其内容属主设为 Nginx 用户,例如:sudo chown -R www-data:www-data /home/www.example.com/.well-known - 设权限时区分文件与目录:
sudo find /home/www.example.com/.well-known -type f -exec chmod 644 {} \;;sudo find /home/www.example.com/.well-known -type d -exec chmod 755 {} \; - 测试是否真能读取:
sudo -u www-data cat /home/www.example.com/.well-known/acme-challenge/test.txt(先手动建个测试文件)
排除 Web 配置与安全模块拦截
即使权限正确,也可能被显性或隐性规则拦住:
- 检查 Nginx 配置中是否有
location ^~ /.well-known/块,且里面没写allow all;或漏了try_files回退逻辑 - 在 CentOS/RHEL 系统上运行
sestatus,若为enforcing,临时执行sudo setenforce 0测试是否恢复;若恢复,说明 SELinux 在拦截,长期方案是打标签:sudo semanage fcontext -a -t httpd_sys_content_t "/home/www.example.com/.well-known(/.*)?" && sudo restorecon -Rv /home/www.example.com/.well-known - 查看错误日志:
sudo tail -n 30 /var/log/nginx/error.log,找含(13: Permission denied)或open() ... failed的行,定位具体卡在哪一级路径


















