优雅地管理 SSL 证书及其关联服务

我的服务器上开着一堆服务,其中有一些需要用到 SSL 证书,例如 Nginx 及前面刚刚部署的邮件服务。我的 SSL 证书是通过 certbot 向 Let’s Encrypt 申请的,证书有效期为 90 天,也就是说每隔 80 多天就得更新一下证书。

动机

在证书更新后,自然需要将所有用到证书的服务 reload 一下,以加载新的证书,通常我会写一条 crontab 作业来干这件事。之前我只有一台服务器 A 跑 Nginx 服务的时候,这样感觉还比较舒服,而现在情况变得更加复杂了:

这两年我都在维护我们实验室主办的学术会议的官网(规模不大,因此把官网部署在我的服务器上完全没问题),所以需要同时维护两个域名的证书。另外,我现在还同时维护着另一台 B 服务器 —— 两台服务器上的服务共享着同一个域名证书,所以需要在 A 服务器上的证书更新时同步到 B 服务器上,并在 B 服务器上 reload 所有用到证书的服务。

于是原先的方法感觉就不太优雅了。正巧这两天 iBug 大佬发布了一篇文章,介绍了一种通过 systemd 来 reload 一些服务的方法:

看上去非常优雅,于是我学习了一下,也给整了起来。

服务器 A 上的操作

首先我将申请证书的脚本从 certbot 换成了更轻量的 acme.sh,安装完成后直接支持通过接入 cloudflare 以及 godaddy 的 dns api 来更新泛域名证书(而 certbot 则需要分别安装两者的插件,感觉稍显笨重)

我将 A 服务器作为更新证书的机器,更新证书后自动同步给 B,在 A 服务器上只有 Nginx 服务需要 reload,因此先创建 /etc/systemd/system/ssl-certificate.target

bash

# /etc/systemd/system/ssl-certificate.target
[Unit]
Description=SSL certificates reload helper
PropagatesReloadTo=nginx.service

然后创建一个 path 文件 /etc/systemd/system/ssl-certificate.path 来监听证书文件的变更事件:

bash

# /etc/systemd/system/ssl-certificate.path
[Unit]
Description=SSL certificate reload helper
Wants=%N.target

[Path]
PathChanged=/path/to/cert1/fullchain.cer
PathChanged=/path/to/cert2/fullchain.cer

[Install]
WantedBy=multi-user.target

我有两个证书,所以这里加了两条 PathChanged 字段分别监听证书 1 和证书 2 的变更事件。

最后由于 path 单元只能激活服务而没办法重载服务,所以需要创建一个 “一次性” 的(oneshot)service,每次激活时来 reload 服务:

/etc/systemd/system/ssl-certificate.service

bash

# /etc/systemd/system/ssl-certificate.service
[Unit]
Description=SSL certificate reload helper
StartLimitIntervalSec=5s
StartLimitBurst=2

[Service]
Type=oneshot
ExecStart=/bin/sh -c '/bin/systemctl reload %N.target; /usr/local/bin/rsync_cert.sh'

这里我需要额外执行的工作还有向 B 服务器同步证书 1,因此采用了将两条命令写在一起的方式。同步证书则使用了 rsync 命令。

/usr/local/bin/rsync_cert.sh

bash

#!/bin/bash

rsync -avzL -e 'ssh -i /path/to/priv_key' /path/to/cert1/ user@serverB:/path/to/cert1/

需要先手动执行一下这个脚本将服务器 B 的公钥写入到 ~/.ssh/known_hosts,后面就能自动化了。

最后启动创建的 path 单元:

bash

systemctl daemon-reload
systemctl enable --now ssl-certificate.path

服务器 B 上的操作

在服务器 B 上,同样可以创建与前面相似的 targetpath 及 service 单元,这样当新的证书同步过去后,也会触发 reload。

由于我的 mailserver 是部署在 docker 里的,好像不太好通过 systemd 来维护,因此同样采用了这种更愚蠢的办法,只是因为命令比较多,就干脆专门写了一个文件:

/etc/systemd/system/ssl-certificate.service

bash

# /etc/systemd/system/ssl-certificate.service
[Unit]
Description=SSL certificate reload helper
StartLimitIntervalSec=5s
StartLimitBurst=2

[Service]
Type=oneshot
ExecStart=/usr/local/bin/reload-services.sh

/usr/local/bin/reload-services.sh

bash

#!/bin/bash

set +e

/bin/systemctl reload ssl-certificate.target

/bin/docker exec mailserver postfix reload
/bin/docker exec mailserver dovecot reload

如此配置,当 SSL 证书更新时,两台服务器上的所有相关服务都可以顺利自动重新加载证书了!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇