This commit is contained in:
parent
5f62762d97
commit
e05d1ff571
@ -106,7 +106,7 @@ func loadValidatedRuntimeCertificate(cfg *Config) (tls.Certificate, error) {
|
||||
AdminRecovery: cfg.AdminRecoveryDomain,
|
||||
}}}
|
||||
runtime.SSL.TLS = cfg.SSL
|
||||
if cfg.SSLType == SSLTypeAutoDNS {
|
||||
if cfg.EffectiveSSLType() == SSLTypeAutoDNS {
|
||||
runtime.SSL.TLS.Management = SSLManagementProject
|
||||
runtime.SSL.TLS.Challenge = SSLChallengeDNS
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
package config
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSSLPolicyFollowsManagement(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
@ -34,3 +37,25 @@ func TestSSLPolicyFollowsManagement(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalCertificateReloadIgnoresLegacyDNSMode(t *testing.T) {
|
||||
previousRoot := ROOT_PATH
|
||||
ROOT_PATH = t.TempDir()
|
||||
t.Cleanup(func() { ROOT_PATH = previousRoot })
|
||||
key, cert := testManagedCertificate(t, "mail.example.com", time.Now().Add(-time.Hour), time.Now().Add(24*time.Hour), 2048)
|
||||
reference, err := ImportManagedSSL(ManagedSSLModeUpload, key, cert, nil, []string{"mail.example.com"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer ReleaseStagedSSL(reference)
|
||||
for _, management := range []string{SSLManagementCustom, SSLManagementWebServer} {
|
||||
cfg := &Config{
|
||||
Domain: "mail.example.com", WebDomain: "mail.example.com", SSLType: SSLTypeAutoDNS,
|
||||
SSL: SSLConfig{Management: management, Mode: reference.Mode,
|
||||
CertificateRef: reference.CertificateRef, PrivateKeyRef: reference.PrivateKeyRef},
|
||||
}
|
||||
if _, err := loadValidatedRuntimeCertificate(cfg); err != nil {
|
||||
t.Fatalf("外部证书被旧 DNS 类型错误拒绝:management=%s err=%v", management, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
# Nginx 反代与证书部署说明
|
||||
|
||||
> 当前状态(2026-09-18):按用户要求,服务器外部 Python/lego 续期程序及 timer 已移除。项目自身托管使用内置续期;手动与代理托管不由 Smail 自动续期。下文的外部脚本与定时任务是历史记录,不再作为部署步骤。最新实现和验收边界见《证书托管续期策略验收》。
|
||||
|
||||
## 最新整改状态
|
||||
|
||||
远程主机 2026-09-18 00:22 已将 Nginx 证书路径迁移为 `/opt/smail/ssl/custom.crt`、`custom.key`,不再直接使用签发目录。只对 Smail 站点执行路径迁移和平滑重载,正式证书、应用程序、其他站点配置未改动。58 次双站 HTTPS 探测和预先建立的下载连接通过,七个 TLS/STARTTLS 入口再次通过。
|
||||
|
||||
35
docs/证书托管续期策略验收.md
Normal file
35
docs/证书托管续期策略验收.md
Normal file
@ -0,0 +1,35 @@
|
||||
# 证书托管续期策略验收
|
||||
|
||||
## 确认的需求
|
||||
|
||||
- 项目自身托管:使用项目内置 ACME 申请及自动续期。
|
||||
- 手动配置:不自动申请或续期,保留证书文件校验和热加载。
|
||||
- 代理服务器托管:Smail 不自动申请或续期,邮件协议仍要求有效证书。
|
||||
- 不新增外部部署或续期脚本依赖。
|
||||
|
||||
## 实现
|
||||
|
||||
`Config.EffectiveSSLType` 统一计算有效策略,明确的证书管理方式优先于旧 `SSLType` 字段。只有没有管理方式及存储模式的旧配置才使用原类型;未知管理方式禁止自动申请。网页 HTTPS 配置为反代模式时仍禁止项目申请。
|
||||
|
||||
初始化展示、域名范围、HTTP/DNS 挑战选择、定时续期及运行证书校验使用统一策略。自托管每 24 小时检查一次,剩余时间不足 30 天、证书无效或域名不匹配时尝试更新;手动及代理托管只检测本地证书变化。DNS 验证目前仍需要完成 TXT 记录设置,启用内置检查不等于 DNS 已实现无人值守。
|
||||
|
||||
前端三项选择明确显示自动续期状态。线上当前为 `custom`,不得因这次修改自动切换为 `project`。
|
||||
|
||||
## 验证状态
|
||||
|
||||
- [✓] Linux 服务器隔离执行 15 组策略组合及旧配置兼容测试。
|
||||
- [✓] 手动与代理托管残留 HTTP/DNS 自动字段时,申请、续期均被拒绝,无 ACME 网络请求或配置改写。
|
||||
- [✓] 定时任务在项目、手动、代理托管之间切换后读取最新策略。
|
||||
- [✓] 前端相关 23 项回归通过,包括三种选项、初始化反代限制和 Vue 模板渲染。
|
||||
- [✓] 前端生产构建及 Linux 主程序构建通过。
|
||||
- [✓] 第一份候选在服务器空库、独立网络及挂载目录中完成初始化、Nginx HTTPS 上游、SMTP/IMAP/POP3、中文正文及附件收信、过载恢复验收。
|
||||
- [~] 补充热加载校验后,重新构建及执行最终候选验收。
|
||||
- [ ] 正式部署和浏览器业务验收。
|
||||
|
||||
第一份候选 SHA-256 为 `ec6b89a10eef5e7359e057c69d1afa3ff6ad8517ffe84b8e4c5dde9151943e21`,运行测试用时 39.91 秒,Smail 内存峰值 77,729,792 字节,Nginx 3,604,480 字节,交换空间为零。两个测试数据库完整性检查均为 `ok`,四个正式服务进程未变化,无新增 OOM,测试邮件未写入生产库。
|
||||
|
||||
## 服务器清理后的边界
|
||||
|
||||
2026-09-18 已停止并移除外部 `smail-certificate-renew` 服务与定时器、独立 Python 续期程序和 lego 工具。原数据与清理证据位于受保护目录 `/var/backups/smail-cleanup-20260918-bwQalZ`。这部分是此前清理结果,不代表本次真实 CA 续期验收。
|
||||
|
||||
仓库旧续期文档中的脚本与 timer 描述属于历史过程,不再是当前部署要求。当前手动证书保持不自动续期;尚未以真实 CA 完成项目自托管的生产续期,不将策略测试等同于真实换证成功。
|
||||
Loading…
Reference in New Issue
Block a user