简介
cert-ctrl 是一个开源证书管理平台,可简化 SSL/TLS 证书在多台机器和环境中的部署。
👉 Jump straight to the 安装指南.
cert-ctrl 解决什么问题?
当您需要以下操作时,管理 SSL/TLS 证书会变得复杂:
- 自动将证书部署到多台服务器
- 在开发环境中信任自签名证书
- 在 WSL、远程 SSH 主机和本地机器之间保持证书同步
- 自动化证书续期和分发
cert-ctrl 通过中央管理服务器和安装在目标机器上的轻量级代理来解决这些挑战。
使用场景 1:本地开发环境的自签名证书
问题描述
在本地开发 HTTPS 应用时,您需要:
- 一个自签名证书颁发机构(CA)来颁发证书
- 浏览器、命令行工具和各种环境都信任该 CA
- 在混合环境(Windows、WSL、远程 SSH、Docker 容器)之间分发证书
传统方式很痛苦:
# 在每台机器上手动操作:
# 1. 手动复制 CA 证书文件
# 2. 安装到系统信任存储(不同操作系统命令不同)
# 3. 分别配置各个应用程序
# 4. CA 更改时重复以上步骤
cert-ctrl 解决方案
一次性设置:
- 安装 cert-ctrl 服务器(生成并管理您的自签名 CA)
- 在每台需要 HTTPS 访问的机器上安装轻量级代理
- 代理自动获取并信任 CA 证书
架构:
┌─────────────────────────────────────────────────────────────┐
│ cert-ctrl 服务器 │
│ • 自签名 CA 生成器 │
│ • *.localhost.dev 证书颁发 │
│ • 中央管理面板 │
└─────────────┬───────────────────────────────────────────────┘
│
│ (代理拉取 CA 和证书)
│
┌─────────┼─────────┬──────────────┬─────────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌─────────┐
│ 宿主机 │ │ WSL │ │ 远程 │ │ Docker │ │ macOS │
│Windows │ │ Ubuntu │ │ SSH │ │ │ │ Dev │
└────────┘ └────────┘ └────────┘ └────────┘ └─────────┘
代理 代理 代理 代理 代理
实际案例
场景: 您在 Windows 上开发 Web 应用,后端在 WSL 中,并从远程 SSH 机器进行测试。
# 1. 安装 cert-ctrl 服务器(一次性)
docker run -d -p 443:443 certctrl/server
# 2. 在 Windows 宿主机上安装代理
certctrl-agent install --server https://certctrl.local
# 3. 在 WSL 中安装代理
certctrl-agent install --server https://certctrl.local
# 4. 在远程 SSH 机器上安装代理
ssh dev-server
certctrl-agent install --server https://certctrl.local
结果: 所有机器现在都信任您的自签名 CA!
# 从 Windows 浏览器访问
https://myapp.localhost.dev ✅ 受信任
# 从 WSL 命令行访问
curl https://myapp.localhost.dev ✅ 正常工作
# 从远程 SSH 访问
ssh dev-server
curl https://myapp.localhost.dev ✅ 正常工作
优势
✅ 一次性设置 每台机器(代理自动安装 CA)
✅ 全平台支持:浏览器、curl、wget、Docker、Python requests、Node.js
✅ 自动更新:当 CA 轮换时,代理获取新版本
✅ 混合环境:Windows ↔ WSL ↔ Linux ↔ macOS
✅ 无需手动复制证书
使用场景 2:Let's Encrypt / ZeroSSL 的生产证书
问题描述
在生产环境使用公共 SSL 证书时:
- 证书每 90 天过期一次(Let's Encrypt)
- 必须续期并部署到所有服务器
- 每台服务器都需要私钥和证书链
- 手动部署容易出错并导致停机
传统方式:
# 每 90 天,在每台服务器上:
ssh server1.example.com
sudo certbot renew
sudo systemctl reload nginx
ssh server2.example.com
sudo certbot renew
sudo systemctl reload nginx
# ... 对几十台服务器重复操作 😫
cert-ctrl 解决方案
架构:
┌──────────────────────────────────────────────────────────┐
│ cert-ctrl 管理服务器 │
│ • ACME 客户端(与 Let's Encrypt/ZeroSSL 通信) │
│ • 自动 DNS-01 挑战(Cloudflare、阿里云 DNS) │
│ • 证书存储和加密 │
│ • 自动续期调度器 │
└────────────┬─────────────────────────────────────────────┘
│
│ (代理安全地拉取证书)
│
┌────────┼────────┬─────────┬─────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐
│ Web │ │ API │ │ 负载 │ │ 边缘 │ │ CDN │
│ 服务器 │ │ 服务器 │ │ 均衡器 │ │ 节点 │ │ 源站 │
│ Nginx │ │ Node.js│ │ HAProxy│ │ │ │ │
└────────┘ └────────┘ └────────┘ └────────┘ └────────┘
代理 代理 代理 代理 代理
分步流程
1. 初始设置(每个域名一次性)
# 在 cert-ctrl 服务器面板中:
1. 添加域名:example.com
2. 获取您的唯一 public-id(例如:abc123def)
3. 在您的 DNS 中添加 CNAME 记录:
名称: _acme-challenge.example.com
类型: CNAME
目标: abc123def.acme.cjj365.cc
4. 选择 CA:Let's Encrypt(或 ZeroSSL)
5. 点击"颁发证书"
服务器自动:
- 生成私钥
- 向 Let's Encrypt 创建 ACME 订单
- 自动解决 DNS-01 挑战:
- 在 cert-ctrl 的域名上创建 TXT 记录:
abc123def.acme.cjj365.cc - Let's Encrypt 跟随您的 CNAME 并验证 TXT 记录
- 验证完成后自动删除 TXT 记录
- 在 cert-ctrl 的域名上创建 TXT 记录:
- 接收签名证书
- 加密私钥进行安全存储
您永远不需要提供 DNS API 密钥! CNAME 委托允许 cert-ctrl 在其自己的域名上管理挑战。
2. 在服务器上安装代理
在每台需要证书的服务器上安装代理:
# Web 服务器 1
ssh web1.example.com
certctrl-agent install \
--server https://cjj365.cc \
--device-name web1 \
--service nginx
# Web 服务器 2
ssh web2.example.com
certctrl-agent install \
--server https://cjj365.cc \
--device-name web2 \
--service nginx
# API 服务器
ssh api.example.com
certctrl-agent install \
--server https://cjj365.cc \
--device-name api1 \
--service node
3. 将证书分配给设备
从 Web 面板:
证书 → example.com → 分配给设备
☑ web1
☑ web2
☑ api1
[保存]
代理自动:
- 检测到新的证书分配
- 拉取加密的证书和私钥
- 使用设备特定的密钥解密
- 安装到适当位置(
/etc/nginx/ssl/、/etc/pki/tls/等) - 重新加载 Web 服务器(nginx、apache、node.js)
4. 自动续期(后台进程)
第 0 天: 证书颁发(有效期 90 天)
第 60 天: cert-ctrl 检查到期 → 自动续期
代理检测到新版本 → 自动部署
Web 服务器重新加载 → 零停机 ✅
第 90 天: 旧证书过期(但已经被替换!)
实际案例
公司: 拥有 10 台 Web 服务器负载均衡的电商网站
使用 cert-ctrl 之前:
- 运维工程师每 90 天花费 2 小时
- 证书续期导致 15 分钟停机
- 错过续期 → 网站停机 6 小时(紧急修复)
使用 cert-ctrl 之后:
- 一次性设置:30 分钟
- 自动续期:0 工程师时间
- 部署:即时,零停机
- 错过续期:不可能(已配置警报)
优势
✅ 自动续期:到期前 30 天(可配置)
✅ 零停机:跨服务器滚动部署
✅ 安全分发:加密私钥,设备特定解密
✅ 集中管理:一个面板管理所有证书
✅ 多云支持:适用于 AWS、GCP、Azure、本地部署
✅ DNS 提供商无关:Cloudflare、阿里云、Route53 等
✅ 多 CA 支持:Let's Encrypt、ZeroSSL 或自带 CA
核心功能
🔐 安全优先
- 私钥端到端加密
- 设备特定密钥包装(X25519)
- 主密钥加密备用方案
- OAuth 2.0 / Passkey 身份验证
🤖 自动化
- ACME 协议(RFC 8555)客户端
- DNS-01 挑战自动化
- 计划证书续期
- 基于代理的部署
🌍 多环境
- 开发(自签名 CA)
- 预发布(Let's Encrypt 预发布环境)
- 生产(Let's Encrypt、ZeroSSL)
📊 可观测性
- 证书到期监控
- 部署状态跟踪
- 所有操作的审计日志
- Webhook 通知
🔌 集成
- Web 服务器:Nginx、Apache、Caddy、HAProxy
- DNS 提供商:Cloudflare、阿里云 DNS、AWS Route53
- 证书颁发机构:Let's Encrypt、ZeroSSL
- 身份验证:GitHub OAuth、微信、Passkey
快速开始
本地开发(使用场景 1)
# 1. 启动 cert-ctrl 服务器
docker-compose up -d
# 2. 在您的机器上安装代理
curl -fsSL https://get.certctrl.dev | sh
certctrl-agent register --server https://localhost:8443
# 3. 您的自签名 CA 现在受信任了!
curl https://myapp.localhost.dev
生产环境(使用场景 2)
# 1. 部署 cert-ctrl 服务器
# (参见部署指南)
# 2. 通过面板颁发证书
# 面板 → 证书 → 新证书
# 域名:example.com
# DNS:Cloudflare(输入 API 令牌)
# CA:Let's Encrypt
# 3. 在服务器上安装代理
certctrl-agent install --server https://cjj365.cc
# 4. 将证书分配给设备
# 面板 → 分配给设备
架构概览
┌─────────────────────────────────────────────────────────────┐
│ cert-ctrl 服务器 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ ACME 客户端 │ │ 证书存储 │ │ Web 面板 │ │
│ │ (RFC 8555) │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ DNS 提供商 │ │ 加密 │ │ API │ │
│ │ 适配器 │ │ (libsodium) │ │ (REST/WS) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
▲
│ HTTPS / WebSocket
▼
┌──────────────────┐
│ cert-ctrl 代理 │
│ (轻量级) │
│ │
│ • 长轮询 │
│ • 自动更新 │
│ • 服务重载 │
└──────────────────┘
下一步
社区与支持
- 💬 GitHub 讨论区:提问、分享技巧
- 🐛 问题跟踪器:报告错误、请求功能
- 📖 文档:全面的指南和 API 参考
- 🎓 示例:示例配置和使用场景
准备好开始了吗? → 安装指南