You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Node.js应用中实现Let's Encrypt SSL证书自动重载

解决Certbot更新SSL证书后自动重载Node.js应用的问题

我懂你的需求——每次Certbot自动更新SSL证书后,希望PM2管理的Node.js应用能自动加载新证书,不用手动操作对吧?下面给你两种可靠的方案,优先推荐第一种,简单又高效:

方案一:利用Certbot的部署钩子(推荐)

Certbot本身支持在成功更新证书后自动运行自定义脚本,我们可以用这个特性触发PM2重载应用,让Node.js重新读取新的证书文件。

步骤1:创建Certbot部署钩子脚本

在Certbot的钩子目录下创建一个可执行脚本,Certbot会在证书更新成功后自动执行它:

# 创建脚本文件
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-pm2.sh

写入以下内容:

#!/bin/bash
# 重载PM2中名为app.js的应用(如果你的PM2应用有自定义名称,替换成对应的名字)
pm2 reload app.js

步骤2:给脚本添加执行权限

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-pm2.sh

步骤3:测试钩子是否生效

用Certbot的模拟更新命令测试,不会真的更新证书,但会触发钩子:

sudo certbot renew --dry-run

执行后查看PM2日志(pm2 logs),应该能看到应用被重载的记录,说明钩子生效了。

为什么这个方案可行?

你的Node.js应用是启动时一次性读取证书文件到内存的,证书更新后磁盘上的文件变了,但应用内存里还是旧的证书,必须重启/重载才能加载新的。PM2的reload是零停机重载,比直接restart更友好,用户不会感受到服务中断。


方案二:修改Node.js代码自动重载证书(进阶)

如果你不想依赖PM2的重载,也可以修改代码让应用定期检查证书文件变化,自动重新加载。这种方法适合不想重启应用的场景,但需要额外的代码开发:

修改你的Express应用代码:

var express = require('express');
var https = require('https');
var fs = require('fs');

const app = express();
app.use((req, res) => {
  res.end('Hello World');
});

// 定义加载证书的函数
function loadHttpsServer() {
  const options = {
    key: fs.readFileSync('/etc/letsencrypt/live/$DOMAIN/privkey.pem'),
    cert: fs.readFileSync('/etc/letsencrypt/live/$DOMAIN/fullchain.pem')
  };
  // 如果之前有服务器实例,关闭旧的
  if (global.httpsServer) {
    global.httpsServer.close(() => {
      console.log('旧HTTPS服务器已关闭,正在启动新服务器');
      startHttpsServer(options);
    });
  } else {
    startHttpsServer(options);
  }
}

function startHttpsServer(options) {
  global.httpsServer = https.createServer(options, app);
  global.httpsServer.listen(8000, () => {
    console.log('HTTPS服务器运行在端口8000');
  });
}

// 启动初始服务器
loadHttpsServer();

// 每12小时检查一次证书文件,自动重载(可根据需要调整间隔)
setInterval(() => {
  console.log('检查证书是否需要更新...');
  loadHttpsServer();
}, 12 * 60 * 60 * 1000);

这种方法会定期重新读取证书文件,关闭旧的HTTPS服务器并启动新的,实现证书热重载。但注意:这种方法可能会有极短的服务中断(比PM2 reload长一点),而且需要确保应用有足够的权限读取证书文件。


额外注意事项

  • 权限问题:你的证书目录/etc/letsencrypt/live/$DOMAIN/默认是root可读的,如果你用sudo pm2 start启动应用(root用户),那没问题;如果是普通用户启动PM2,需要给该用户添加读取证书目录的权限,比如用setfacl命令:sudo setfacl -R -m u:your_username:r /etc/letsencrypt/live/$DOMAIN/(比直接修改所有权更安全)。
  • PM2应用名称:如果你的PM2应用有自定义名称(比如用pm2 start app.js --name my-app),钩子脚本里要改成pm2 reload my-app

内容的提问来源于stack exchange,提问作者Zain Ul Abideen

火山引擎 最新活动