用了一下午时间做,之前的证书同步方案还行,但是后来 cloudflare dcv 记录占据了 _acme-challenge 位置,导致签发失败,Google Trust Service 支持 _validation-persist 虽然 lego 客户端已经支持了这个验证方式,但是 nixos 自带的 acme 模块并不支持直接配置这个选项并且考虑到以后可能加更多证书 / 域名,还是图形化管理更好用,所以把主签发机 us.or.dls.2 上的签发器从 acme 模块换成了 certwarden 这个 docker 里的 webui 证书管理器
换完后发现直接把证书同步模块叫作 acme 不合适,于是又对证书同步模块大改了下,换了单元名字和证书存放路径,并且把它从机器配置里抽出来,成为了独立模块,还加了证书更新时 reload 相关单元的功能
然后又发现 cert-sync 每天拉一次遇到紧急情况需要立刻同步证书时需要逐个 ssh 上去重启单元,非常麻烦所以又给 us.or.dls.2 部署了 ntfy 服务器,在上传后 certwarden 会向 ntfy 服务器发送消息,其他机器则用 cert-notify 单元和 ntfy 服务器保持 wss 长连接,在收到更新消息 cert-notify 会自动拉起 cert-sync 从存储桶拉取证书
后续会详细写篇博客说是如何实现的(先让我咕咕咕一会)
具体流程如下
--- config: theme: redux-color themeVariables: edgeLabelBackground: "#ffffff" --- flowchart BT %% 公网下游 · 6 台 VPS subgraph EU["eu.de.0"] direction TB EU_N["cert-notify"] EU_S["cert-sync<br/>cert-sync.timer"] end subgraph HK2["hk.2"] direction TB HK2_N["cert-notify"] HK2_S["cert-sync<br/>cert-sync.timer"] end subgraph HK3["hk.3.cnix"] direction TB HK3_N["cert-notify"] HK3_S["cert-sync<br/>cert-sync.timer"] end subgraph SG["sg.0"] direction TB SG_N["cert-notify"] SG_S["cert-sync<br/>cert-sync.timer"] end subgraph PHX["us.az.phx.0"] direction TB PHX_N["cert-notify"] PHX_S["cert-sync<br/>cert-sync.timer"] end subgraph LAX["us.ca.lax.0"] direction TB LAX_N["cert-notify"] LAX_S["cert-sync<br/>cert-sync.timer"] end %% 证书与通知汇聚节点 NB(("更新消息推送")) DB(("证书下载")) subgraph CF["Cloudflare Global Network"] direction LR EDGE["https://ntfy.nahida.im"] R2[("Cloudflare R2<br/>r2:tls")] end subgraph GCP["GCP 集群 · 同一 VPC"] direction LR subgraph G0["us.or.dls.0"] direction TB T0["cloudflared"] N0["cert-notify"] S0["cert-sync<br/>cert-sync.timer"] end subgraph G1["us.or.dls.1"] direction TB T1["cloudflared"] N1["cert-notify"] S1["cert-sync<br/>cert-sync.timer"] end subgraph G2["us.or.dls.2 · 签发主节点"] direction TB CW["Cert Warden<br/>GTS / DNS-PERSIST-01"] NTFY["ntfy-sh Server<br/>10.138.0.5:8000"] T2["cloudflared"] end end %% 紫色:systemd trigger (0-7) EU_N -->|"trigger"| EU_S HK2_N -->|"trigger"| HK2_S HK3_N -->|"trigger"| HK3_S SG_N -->|"trigger"| SG_S PHX_N -->|"trigger"| PHX_S LAX_N -->|"trigger"| LAX_S N0 -->|"trigger"| S0 N1 -->|"trigger"| S1 %% 绿色:ntfy publish (8) CW -->|"R2 上传完成后 publish: sync"| NTFY %% 绿色:ntfy Tunnel / Origin (9-14) NTFY ---|"VPC Origin"| T0 NTFY ---|"VPC Origin"| T1 NTFY ---|"本机 Origin"| T2 T0 ---|"Tunnel · 路径 0"| EDGE T1 ---|"Tunnel · 路径 1"| EDGE T2 ---|"Tunnel · 路径 2"| EDGE %% 绿色:ntfy JSON Streaming (15-23) NTFY -.->|"HTTP · VPC"| N0 NTFY -.->|"HTTP · VPC"| N1 EDGE -.- NB NB -.-> EU_N NB -.-> HK2_N NB -.-> HK3_N NB -.-> SG_N NB -.-> PHX_N NB -.-> LAX_N %% 蓝色:R2 证书上传、下载 (24-33) CW ==>|"上传 PEM"| R2 R2 === DB DB ==> EU_S DB ==> HK2_S DB ==> HK3_S DB ==> SG_S DB ==> PHX_S DB ==> LAX_S DB ==> S0 DB ==> S1 %% 连线颜色与线宽 linkStyle 0,1,2,3,4,5,6,7 stroke:#9333ea,color:#9333ea,stroke-width:1.2px; linkStyle 8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 stroke:#059669,color:#059669,stroke-width:1.3px; linkStyle 24,25,26,27,28,29,30,31,32,33 stroke:#2563eb,color:#2563eb,stroke-width:1.6px; %% 应用节点配色 classDef issuer fill:#dbeafe,stroke:#2563eb,color:#1e40af; classDef cloudflare fill:#ffedd5,stroke:#ea580c,color:#9a3412; classDef notify fill:#dcfce7,stroke:#16a34a,color:#166534; class CW issuer class EDGE,R2,T0,T1,T2 cloudflare class NTFY,EU_N,HK2_N,HK3_N,SG_N,PHX_N,LAX_N,N0,N1 notify %% 汇聚节点:白色背景、彩色边框与文字 classDef notifyBus fill:#ffffff,stroke:#16a34a,color:#16a34a; classDef dataBus fill:#ffffff,stroke:#2563eb,color:#2563eb; class NB notifyBus class DB dataBus %% Sky Blue:所有机器的独立容器 classDef machine fill:#f0f9ff,stroke:#38bdf8,color:#0369a1,stroke-width:1px; class EU,HK2,HK3,SG,PHX,LAX,G0,G1,G2 machine %% Cloudflare:橙色 style CF fill:#fff7ed,stroke:#f97316,color:#9a3412,stroke-width:1.5px %% GCP 集群:黄色 style GCP fill:#fefce8,stroke:#eab308,color:#854d0e,stroke-width:1.5px收藏 1支持反对打赏
支持技术贴
个性签名生于安乐,死于忧患。
支持 收藏
支持一下
好奇为什么不直接用 caddy @grok
个性签名楼上楼下都是大水比,没说我不是
grok:不是单机自动上 HTTPS 的问题,Caddy 替换不了这套流程。
楼主卡在签发方式:Cloudflare 的 DCV 占了
_acme-challenge,只能走 Google Trust Services 的_validation-persist。lego 支持,NixOS 自带的 acme 模块不能直接配,所以签发端改成了 Cert Warden,并且要在一个 Web UI 里管以后更多证书。证书还要分到 eu、hk、sg、phx、lax 和 GCP 上那几台。这些机器会离线,服务也不都是 Caddy,更新后要 reload 各自的单元。所以是签发机上传 PEM 到 R2,其余机器用定时器兜底,紧急时靠 ntfy 叫醒
cert-sync来拉。第 3 楼那种 SSH 上去复制,楼主也是因为离线才没用。每台自己跑 Caddy 去签,DNS 凭据得铺开,挑战记录还是会和 DCV 抢,离线的签不了,也覆盖不了非 Caddy 的服务。
纳西妲楼主:ai 差不多把我的想法解释完了,我不用 caddy 的原因主要是这几个:
- 我使用的是 Google Trust Service,需要注册 EAB 账号,如果用 caddy 的话需要每台机器一个账号,麻烦
- 我的 _acme-challenge 被 cloudflare dcv 占用了,必须用 DNS-PERSIST-01 或者 DNS-ACCOUNT-01 签
- 我的大多数服务都是 haproxy、nginx,不想迁 caddy
- 部分使用 tls 证书的服务并不是在 caddy 后面的,比如 singbox
- 我不希望续期时有多少 vps 就续多少张证书
共 5 条回复bdbd
个性签名无敌大水比
(发出倒地的声音)