From f613fc56805bf6b2e6c8eea199c5e96ae086ca5c Mon Sep 17 00:00:00 2001 From: flym Date: Thu, 10 Sep 2026 19:48:25 +0800 Subject: [PATCH] docs: record production deployment and smtp alert template --- docs/production-deployment-2026-09-10.md | 30 ++++++++++++++++++++++++ infra/scripts/kaotings-alert.py | 28 ++++++++++++++++++++++ infra/systemd/kaotings-alert.env.example | 6 +++++ 3 files changed, 64 insertions(+) create mode 100644 docs/production-deployment-2026-09-10.md create mode 100644 infra/scripts/kaotings-alert.py create mode 100644 infra/systemd/kaotings-alert.env.example diff --git a/docs/production-deployment-2026-09-10.md b/docs/production-deployment-2026-09-10.md new file mode 100644 index 0000000..e4a832e --- /dev/null +++ b/docs/production-deployment-2026-09-10.md @@ -0,0 +1,30 @@ +# 生产部署记录(2026-09-10) + +## 已完成 + +- 发布提交:`df6a0e4`,发布目录 `/home/flym/releases/df6a0e4`。 +- 生产业务库 `kaotings` 与 CMS 库 `kaotings_cms` 均为空库新建;未迁移测试用户、额度、任务或音频。 +- API 四个迁移已应用;CMS 初始迁移已应用。 +- API、CMS、Web 均由 systemd 管理,分别监听回环 `8000`、`3001`、`3000`;Worker 随 API 进程运行。 +- `www.kaotings.com` / `kaotings.com` 已由 Caddy 反代到新服务,HTTPS 首页和 `/healthz` 已验证。 +- 生产管理员使用独立随机密码初始化为 `tech@kaotings.com`;密码仅保存在 root-only 引导文件中,不进入仓库或日志。 +- 生产 TTS 上游未配置,生成能力保持关闭。 + +## 回退与旧站 + +- 原 Caddy 配置保留为 `/opt/halo/caddy/Caddyfile.pre-kaotings-20260910`。 +- 原 Caddy 容器保留为 `caddy-old-20260910` 且已停止。 +- `wordpress-web-1`、`wordpress-db-1`、`halo` 保留且未删除;未执行全局清理。 + +## 验收 + +- `GET https://www.kaotings.com/`:200。 +- `GET https://www.kaotings.com/healthz`:API/数据库均为 ok。 +- `GET https://www.kaotings.com/api/v1/auth/me`:401,认证门禁生效。 +- CMS API:200;Web:200。 + +## 剩余阻断 + +1. TTS 上游仍为公网 HTTP/未完成来源限制,正式启用 TTS 前必须提供 HTTPS 或受控加密通道并复测。 +2. 音频保留期、清理、磁盘阈值和备份保留参数仍需确认。 +3. SMTP 告警需发送明确标记的验证邮件并记录“SMTP 受理”与实际送达;本记录不把受理等同于送达。 diff --git a/infra/scripts/kaotings-alert.py b/infra/scripts/kaotings-alert.py new file mode 100644 index 0000000..0c34bc7 --- /dev/null +++ b/infra/scripts/kaotings-alert.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +import os +import smtplib +import ssl +import sys +from email.message import EmailMessage + + +def main() -> int: + subject = sys.argv[1] if len(sys.argv) > 1 else "Kaotings production alert" + body = sys.stdin.read() or "No details provided." + recipients = [item.strip() for item in os.environ.get("ALERT_RECIPIENTS", "").split(",") if item.strip()] + if not recipients: + raise SystemExit("ALERT_RECIPIENTS is required") + message = EmailMessage() + message["From"] = os.environ["SMTP_FROM"] + message["To"] = ", ".join(recipients) + message["Subject"] = subject + message.set_content(body) + context = ssl.create_default_context() + with smtplib.SMTP_SSL(os.environ["SMTP_HOST"], int(os.environ.get("SMTP_PORT", "465")), context=context, timeout=20) as smtp: + smtp.login(os.environ["SMTP_USER"], os.environ["SMTP_PASSWORD"]) + smtp.send_message(message) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/infra/systemd/kaotings-alert.env.example b/infra/systemd/kaotings-alert.env.example new file mode 100644 index 0000000..b457397 --- /dev/null +++ b/infra/systemd/kaotings-alert.env.example @@ -0,0 +1,6 @@ +SMTP_HOST=smtp.exmail.qq.com +SMTP_PORT=465 +SMTP_USER=tech@kaotings.com +SMTP_FROM=tech@kaotings.com +ALERT_RECIPIENTS=38179056@qq.com,mu.blank@gmail.com +SMTP_PASSWORD=replace-with-secret