feat: 优化证书申请逻辑,同一路由的多个域名合并到一个证书

- 按路由处理域名,而不是按域名处理
- 同一路由中的多个域名合并到一个证书申请(使用 SAN)
- 减少证书数量,简化管理
- 符合最佳实践:一个证书包含多个相关域名

优势:
- 减少证书数量(从 N 个减少到 1 个)
- 减少续期次数
- 降低 Let's Encrypt API 调用频率
- 简化证书管理

示例:
- 路由包含 jingrowtools.cn 和 www.jingrowtools.cn
- 现在会申请一个包含两个域名的证书(SAN)
- 而不是分别申请两个独立证书
This commit is contained in:
jingrow 2026-01-01 19:38:34 +00:00
parent cac12f50bd
commit cd346ec94b

View File

@ -154,20 +154,28 @@ class RouteWatcher:
def process_new_domains(self):
"""处理新域名"""
routes = self.get_all_routes()
new_domains = set()
# 从路由中提取所有域名
# 按路由处理,同一路由的多个域名合并到一个证书
for route in routes:
route_value = route.get('value', {})
# 跳过禁用的路由status=0 表示禁用)
if route_value.get('status') == 0:
continue
# 从路由中提取所有域名
domains = self.extract_domains_from_route(route)
new_domains.update(domains)
# 处理需要申请证书的域名
for domain in new_domains:
if self.should_request_cert(domain):
if not domains:
continue
# 过滤出需要申请证书的域名
domains_to_request = [d for d in domains if self.should_request_cert(d)]
if not domains_to_request:
continue
# 如果只有一个域名,单独申请
if len(domains_to_request) == 1:
domain = domains_to_request[0]
logger.info(f"发现新域名,准备申请证书: {domain}")
try:
if self.ssl_manager.request_certificate(domain):
@ -176,6 +184,18 @@ class RouteWatcher:
logger.error(f"证书申请失败: {domain}")
except Exception as e:
logger.error(f"处理域名异常 {domain}: {e}")
else:
# 多个域名,合并到一个证书申请(使用 SAN
primary_domain = domains_to_request[0]
additional_domains = domains_to_request[1:]
logger.info(f"发现同一路由中的多个域名,合并申请证书: {primary_domain} + {additional_domains}")
try:
if self.ssl_manager.request_certificate(primary_domain, additional_domains):
logger.info(f"证书申请成功: {primary_domain} (包含 {len(additional_domains)} + 1} 个域名)")
else:
logger.error(f"证书申请失败: {primary_domain} + {additional_domains}")
except Exception as e:
logger.error(f"处理域名异常 {primary_domain} + {additional_domains}: {e}")
def run(self, interval: int = 60):
"""运行监听服务"""