You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Let's Encrypt SSL权限拒绝问题:Node.js无法读取privkey.pem

解决Node.js访问Let's Encrypt证书时的EACCES权限问题

你遇到的核心问题是运行Node.js的普通用户没有权限遍历/etc/letsencrypt的目录结构——哪怕重新生成了证书,Let's Encrypt默认的权限设置依然会阻止非root用户访问这些文件。下面一步步帮你解决:

问题根源分析

从你贴出的权限信息能看出关键问题:

  • /etc/letsencrypt目录是drwx------ 3 root root:只有root用户能进入这个目录,其他用户连遍历路径的权限都没有
  • 虽然archive和live下的证书文件本身是-rw-r--r--(允许其他用户读取),但如果上层目录没有执行权限(x),普通用户根本无法到达这些文件的路径

解决方案(按推荐程度排序)

1. 调整目录权限,让Node.js用户能访问证书路径

这种方法不需要移动证书,适合需要保留Let's Encrypt自动续期功能的场景:

  • 先确定运行Node.js的用户(比如www-data、你的普通用户名,假设是nodeuser)
  • 依次执行以下命令,给上层目录添加其他用户的执行权限(目录的执行权限等同于允许进入该目录):
    sudo chmod o+x /etc/letsencrypt
    sudo chmod o+x /etc/letsencrypt/archive
    sudo chmod o+x /etc/letsencrypt/live
    sudo chmod o+x /etc/letsencrypt/live/domain.work
    
  • 现在你的Node.js进程应该能正常读取privkey.pem和cert.pem了

2. 将证书复制到Node.js有权限的目录

如果不想修改系统目录的权限,可以把证书复制到你的项目目录下:

  • 复制证书文件到项目的ssl子目录(先创建好这个目录):
    sudo cp /etc/letsencrypt/live/domain.work/*.pem /path/to/your/node/project/ssl/
    
  • 修改文件所有权为Node.js用户:
    sudo chown nodeuser:nodeuser /path/to/your/node/project/ssl/*.pem
    
  • 最后修改代码,读取项目目录里的证书:
    try {
      var TLSoptions = {
        key: fs.readFileSync("./ssl/privkey.pem"),
        cert: fs.readFileSync("./ssl/cert.pem")
      };
      https.createServer(TLSoptions, app).listen(port, host, function() {
        console.log("TLS Website started.")
      });
    } catch(e) {
      console.log(e)
    }
    
  • 注意:如果启用了Let's Encrypt自动续期,你需要添加一个定时脚本定期同步证书到项目目录

3. (不推荐)用sudo运行Node.js

虽然这能直接绕开权限问题,但用root权限运行Node.js会带来严重安全风险——除非你完全信任代码和所有依赖,否则不建议这么做:

sudo node your-app.js

额外注意事项

  • 私钥文件privkey.pem不要设置过宽的权限,保持600(只有所有者可读可写)是最安全的
  • 如果你的Node.js需要绑定443端口(默认HTTPS端口),普通用户可能没有权限,这时候可以用setcap给Node.js添加端口绑定权限:
    sudo setcap 'cap_net_bind_service=+ep' $(which node)
    

内容的提问来源于stack exchange,提问作者kraftwerk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:01:28