ssl 证书

关于

每一个终止 TLS 的服务都需要 cert.crt / cert.key 这一对证书。有两种获取方式:

命令

证书

适用场景

make openssl

自签名,有效期 365 天

首次启动和试验。浏览器会提示证书不受信任

make cert

Let's Encrypt(ACME)免费证书

生产环境。有效期 3 个月,请按第 4 节配置自动续期

1. 生成自签名证书

cd bind-docker/office

make openssl
脚本会写入 nginx/certs/cert.crt 和 nginx/certs/cert.key,CN=$DOMAIN,有效期 365 天
两个文件都存在时脚本不做任何事,需要重新生成就先删除它们
make 也会执行这个目标,所以首次 make 时会自动补齐这一对证书

注意这种方式只有 nginx 拿到证书。bindsmtp 和 bindimap 读取的是 smtp/certs 和 imap/certs,没有证书时 bindimap 无法启动。这两个目录由第 2 节填充,所以自签名证书只适合跑 HTTPS,或者按下一节安装免费证书。

2. 申请免费的 Let's Encrypt 证书

make cert
办公套件内置了 ACME(Let's Encrypt)客户端,make cert 等价于 make generate copy
make generate 通过 HTTP 调用 /acme/create 接口,签发的证书对写入 bindinbox 的 BIND_CERT_DIR,该目录由 bindinbox/certs 挂载进来
make copy 会把证书对安装到每个终止 TLS 的服务,见第 3 节
证书有效期 3 个月,请保持第 4 节的自动续期开启

前提条件:

  • DOMAIN 解析到服务器公网 IP,且 80 端口能被公网访问,HTTP-01 验证依赖这一点

  • 容器正在运行,因为该命令是通过 nginx 的 80 端口访问应用的

3. 各服务使用哪份证书

make copy``(``sh bin/cert-distribute.sh)把证书对从 bindinbox/certs``(独立部署的会议是 ``bindmeet/certs)复制到终止 TLS 的服务:

目录

服务

nginx/certs

nginx:443 的 HTTPS 和 MQTT 的 TLS 端口

smtp/certs

bindsmtp:SMTP 提交的 STARTTLS

imap/certs

bindimap:IMAPS

手动替换证书后可以单独执行它:

make copy

4. 定时自动续期

make cron      # install the renewal job, replaces an existing one

make uncron    # remove it

sh bin/cert-cron.sh show   # print the installed job
定时任务每天执行一次 make renew,输出追加写入 logs/cert-renew.log
make renew``(``sh bin/cert-renew.sh)是幂等的:它用 openssl x509 -checkend 检查 nginx 当前正在使用的证书,剩余有效期大于 CERT_RENEW_DAYS 天时直接退出
只有在证书临近过期时才会调用 /acme/renew 接口、安装新的证书对并重新加载相关服务
只在需要时续期,才能避开 Let's Encrypt 的重复证书限制:同一组域名每周 5 张

续期之后各服务这样拿到新证书:

服务

行为

nginx

nginx -s reload:证书被重新加载且不中断连接,nginx 是**重新加载而不是重启**。nginx 没在运行时脚本会打印 nginx is not running; it will use the new certificate on next start,新证书在下次启动时生效

bindsmtp、bindimap

docker compose restart:这两个服务只在启动时读取证书,因此会被重启

需要在证书仍然有效时强制续期(例如修改了 DOMAIN):

CERT_FORCE_RENEW=1 sh bin/cert-renew.sh
crontab 归属执行 make cron 的用户,该用户必须能免 sudo 使用 Docker(在 docker 组内,或用 root 执行 make cron),否则定时任务无法操作容器
不想用 crontab 的话,可以用 systemd timer 或其他调度器定时执行 cd <部署目录> && make renew

变量

默认值

说明

CERT_RENEW_DAYS

30

剩余天数少于该值时续期

CERT_CRON_SCHEDULE

0 3 * * *

make cron 写入 crontab 的计划

CERT_FORCE_RENEW

未设置

设置后忽略剩余天数直接续期;在命令行传入,不从 .env 读取