如何在Node.js应用程序中自动重新加载更新的SSL证书



我创建了nodejs应用程序,并使用Lets EncryptSSL证书。以下是我的代码

var express = require(‘express’);
var https = require(‘https’);
var fs = require(‘fs’);
var option = {
key: fs.readFileSync(‘/etc/letsencrypt/live/$DOMAIN/privkey.pem’),
cert: fs.readFileSync(‘/etc/letsencrypt/live/$DOMAIN/fullchain.pem’)
};
const app = express();
app.use((req, res) =>
{
res.end(‘Hello World’);
});
https.createServer(option, app).listen(8000);

我已经使用pm2来启动这个应用程序,使用以下命令

sudo pm2 start app.js --watch

我正在使用以下cronjob 更新SSL证书

0 8 * * * sudo certbot renew

我想在certbot续订SSL证书时自动重新加载SSL证书。我怎样才能做到这一点?

对于那些负担不起或不愿重新启动服务器以重新加载证书的人,以及那些对Dylan Landry基于SNI的方法感到不舒服的人,有一段时间以来,通过server.setSecureContext(其中服务器是标准节点https服务器实例(,有一种专门构建的方法可以在节点中实现这一点。参见以下片段:

const app = express();
function readCertsSync() {
return {
key: fs.readFileSync(sslKeyPath),
cert: fs.readFileSync(sslCertPath) + fs.readFileSync(sslFullChainPath)
}
}
let httpd = https.createServer(readCertsSync(), app).listen(port, onReady);
// Refresh httpd's certs when certs change on disk. The timeout stuff 
// "ensures" that all 3 relevant files are updated, and accounts for 
// sometimes trigger-happy fs.watch.
let waitForCertAndFullChainToGetUpdatedTooTimeout;
fs.watch(sslKeyPath, () => {
clearTimeout(waitForCertAndFullChainToGetUpdatedTooTimeout);
waitForCertAndFullChainToGetUpdatedTooTimeout = setTimeout(() => {
httpd.setSecureContext(readCertsSync());
}, 1000);
});

fs.watch和超时代码确实有点笨拙,可以使用chokidar之类的东西和一些更扩展的逻辑来监控所有3个相关文件的状态,从而进行改进。我选择保持简单的方式来关注有趣的部分:setSecureContext

有关参考,请参见https://nodejs.org/api/tls.html#tls_server_setsecurecontext_options

此外,这要归功于诺利米特德夫,他在setSecureContext出现之前就提出了大部分内容。

您可以在每次续订后使用标志--post-hook重新启动应用程序。

certbot renew --post-hook "pm2 restart app_name"
更新#1

请注意,我们正在运行的命令位于crontab中,任何全局程序都必须使用完整路径进行引用。可以使用which命令查找该命令的可执行文件路径。

您可以在不重新启动服务器的情况下重新加载新证书。

根据问题重新加载https.createServer((的证书文件而不重新启动节点服务器#15115,特别是来自mscdex:的此评论

FWIW您已经可以使用SNICallback((:

const https = require('https');
const tls = require('tls');
const fs = require('fs');
var ctx = tls.createSecureContext({
key: fs.readFileSync(config.sslKeyPath),
cert: fs.readFileSync(config.sslCrtPath)
});
https.createServer({
SNICallback: (servername, cb) => {
// here you can even change up the `SecureContext`
// based on `servername` if you want
cb(null, ctx);
}
});

这样,您所要做的就是重新分配ctx,然后它将用于未来的任何请求。

使用上面的示例,您只需要在SNICallback内的cert路径上再次执行fs.readFileSync,并将它们附加到ctx对象。但是,只有当你知道他们刚刚改变时,你才想这么做。您可以从javascript中查看文件的更改。您可以使用fs.watch()或npm中的其他内容。

最新更新