实现certbot的证书在服务器之间迁移,及Systemd Timers了解

Nginx服务迁移,需要将SSL证书也一起迁移,而CertBot是通过定时器触发续定证书。

典型生产环境中,这些路径映射为:

  • /etc/letsencrypt/live/: 包含指向最新证书的符号链接,如fullchain.pemprivkey.pem
  • /etc/letsencrypt/archive/: 存储所有历史证书版本(自动轮转)
  • /etc/letsencrypt/renewal/: 域名续期配置文件(.conf格式)

警告:live目录下的证书文件实为符号链接,直接复制可能导致备份失效,需通过配置文件获取真实路径。

在原服务器备份

# 创建迁移包(排除敏感日志)
tar -czf certbot-migration.tar.gz --exclude=logs /etc/letsencrypt/{live,archive,renewal}

# 会有两不影响压缩的提示
tar: Removing leading `/' from member names
tar: Removing leading `/' from hard link targets

在目标服务器还原

# 在目标服务器还原
tar -xzf /tmp/certbot-migration.tar.gz -C /

# 检查 renewal配置文件
vim /etc/letsencrypt/renewal/example.com.conf
# 关键参数检查:
# - authenticator(验证方式)
# - installer(服务器类型)
# - server(ACME端点URL)

# 检查权限:私钥权限必须为600,为仅root可读写
sudo find /etc/letsencrypt -type f -name "*.pem"|xargs sudo ls -l

# chmod 600 /etc/letsencrypt/live/*/privkey.pem
# chown -R root:root /etc/letsencrypt/

完成迁移后,需要执行全面检查

检查项验证命令预期结果
证书有效期sudo certbot certificates所有证书状态为”Valid”
续期验证sudo certbot renew --dry-run能续期成功
自动续期配置sudo systemctl status certbot.timer

sudo crontab -l
定时器处于active状态

0 2 5,20 * * /usr/bin/certbot renew --quiet记录
HTTPS连通性curl -I https://example.com响应码200,包含”Server: nginx”等
OCSP staplingopenssl s_client -connect example.com:443 -status包含”OCSP Response Status: successful”

Systemd 中的 certbot 定时器

$ sudo systemctl list-unit-files --type service # 查看所有 Service 单元
$ sudo systemctl list-unit-files --type timer # 查看所有 Timer 单元
  • /lib/systemd/system/:系统默认的单元文件
  • /etc/systemd/system/:用户安装的软件的单元文件
  • /usr/lib/systemd/system/:用户自己定义(机器范围)的单元文件
  • ~/.config/systemd/user/:用户自己定义(用户范围,需要对用记登录后,才会被执行)的单元文件,还有在使用systemctl时,要加上--user参数,比如:
systemctl --user daemon-reload
systemctl --user start test.timer
systemctl --user list-timers
systemctl --user stop test.timer
systemctl --user status test.service

certbot定时器的配置文件

$ sudo cat /usr/lib/systemd/system/certbot.timer
[Unit]
Description=Run certbot twice daily

[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true

[Install]
WantedBy=timers.target

$ sudo cat /usr/lib/systemd/system/certbot.service
[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://certbot.eff.org/docs
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew --no-random-sleep-on-renew
PrivateTmp=true

定时器分为两种类型:实时定时器和单调定时器,官方文档:时间写法/时间表示方法定时器单元配置描述

  • 实时定时器基于绝对时间,也就是日历事件(如每天、每周),使用 OnCalendar= 配置。
  • 单调定时器基于相对时间(如系统启动后 15 分钟),使用 OnBootSec=OnUnitActiveSec= 等等字段,更多看官方配置说明。
    • OnActiveSec:定时器生效后,多少时间开始执行任务
    • OnBootSec:系统启动后,多少时间开始执行任务
    • OnStartupSec:Systemd 进程启动后,多少时间开始执行任务
    • OnUnitActiveSec:该单元上次执行后,等多少时间再次执行
    • OnUnitInactiveSec: 定时器上次关闭后多少时间,再次执行
    • AccuracySec:如果因为各种原因,任务必须推迟执行,推迟的最大秒数,默认是60秒

certbot.timer的配置描述

  • OnCalendar=*-*-* 00,12:00:00表示每天的0点和12点。
    • =1h表示每一小时, =*-*-* 02:00:00表示每天凌晨两点, =Mon *-*-* 02:00:00表示每周一凌晨两点。更多见时间表示方法。
  • RandomizedDelaySec=43200表示可以随机延时范围在43200s,也就是6小时之间。起到避免在同一个时间里,有大量定时任务被触发;对应,有一个相反作用的参数AccuracySec或者配置“RandomizedDelaySec=0`。
  • Persistent=true表示定时器到时没有启动,也会自动执行相应的单元,仅对使用” OnCalendar= “配置的计时器有效。
  • Unit=表示当此计时器到期时激活的执行单位。如果在[Timer]里面没有Unit=时,则默认为与计时器单位名称相同的服务,可以下面查看状态中看到相关内容。
  • WantedBy=timers.target表示此定时器归属于timers.target
    • Target 指的是一组相关进程,有点像 init 进程模式下面的启动级别。启动某个Target 的时候,属于这个 Target 的所有进程都会全部启动。

certbot.timer的状态查看

$ sudo systemctl list-timers|grep -e certbot -e NEXT
NEXT                            LEFT LAST                              PASSED UNIT             ACTIVATES
Sat 2026-01-17 06:43:12 CST       6h Fri 2026-01-16 18:33:40 CST 5h 47min ago certbot.timer    certbot.service

$ sudo systemctl status certbot.timer
● certbot.timer - Run certbot twice daily
     Loaded: loaded (/usr/lib/systemd/system/certbot.timer; enabled; preset: enabled)
     Active: active (waiting) since Fri 2025-11-28 21:12:13 CST; 1 month 18 days ago
    Trigger: Sat 2026-01-17 06:43:12 CST; 6h left
   Triggers: ● certbot.service

Nov 28 21:12:13 vps-251018 systemd[1]: Started certbot.timer - Run certbot twice daily.

$ sudo systemctl status certbot.service
○ certbot.service - Certbot
     Loaded: loaded (/usr/lib/systemd/system/certbot.service; static)
     Active: inactive (dead) since Sat 2026-01-17 17:12:21 CST; 4min 29s ago
TriggeredBy: ● certbot.timer
       Docs: file:///usr/share/doc/python-certbot-doc/html/index.html
             https://certbot.eff.org/docs
    Process: 949468 ExecStart=/usr/bin/certbot -q renew --no-random-sleep-on-renew (code=exited, status=0/SUCCESS)
   Main PID: 949468 (code=exited, status=0/SUCCESS)
        CPU: 1.053s

Jan 17 17:12:19 vps-251018 systemd[1]: Starting certbot.service - Certbot...
Jan 17 17:12:21 vps-251018 systemd[1]: certbot.service: Deactivated successfully.
Jan 17 17:12:21 vps-251018 systemd[1]: Finished certbot.service - Certbot.
Jan 17 17:12:21 vps-251018 systemd[1]: certbot.service: Consumed 1.053s CPU time.

Systemd timers

Systemd timers 与传统的 crontab 相比,使用 Systemd 管理定时任务主要有以下优势:

  • 统一的日志系统:日志自动汇集到journald,方便搜索和分析
  • 资源控制能力:可以限制任务占用的CPU和内存等资源,且不会重复执行定时任务
  • 模块化管理:依赖关系清晰,易于管理复杂任务

缺点也有,就看你的使用场景。

systemd timer 入门示例

创建systemd timer定时任务时,需要同时编写两个文件:

  • 编写一个以.timer为后缀的Systemd Unit,该文件描述定时任务如何定时
  • 编写一个以.service为后缀的Systemd Service Unit,该文件描述定时任务要执行的操作

这两个文件名称通常保持一致(除了后缀部分),它们可以放在/usr/lib/systemd/system

backup.sh

在 /tmp/backup_output.log 中写入“Backup Completed!”及当前时间和日期信息。

#!/bin/bash
echo "Backup Completed! $(date)" >> /tmp/backup_output.log

配置可执行权限

chmod +x backup.sh

backup.service

如果服务以非零退出码结束,则会尝试在定义的时间间隔内重新启动至指定的次数。

[Unit]
Description=Backup Script

[Service]
ExecStart=/path/to/backup.sh
Restart=on-failure
RestartSec=10s
StartLimitInterval=60s
StartLimitBurst=5

backup.timer

周一到周五的2点启动

[Unit]
Description=Backup Timer

[Timer]
OnCalendar=Mon..Fri:02:00:00
Persistent=true

[Install]
WantedBy=timers.target

启用并启动定时器

sudo systemctl daemon-reload
# 是由 backup.timer 去启动 backup.service,所以不需要配置 backup.service
sudo systemctl enable backup.timer
sudo systemctl start backup.timer
# 查看 backup.service 的日志
sudo journalctl -u backup.service

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注