docs: record production deployment and smtp alert template
This commit is contained in:
parent
df6a0e46a6
commit
f613fc5680
30
docs/production-deployment-2026-09-10.md
Normal file
30
docs/production-deployment-2026-09-10.md
Normal file
@ -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 受理”与实际送达;本记录不把受理等同于送达。
|
||||||
28
infra/scripts/kaotings-alert.py
Normal file
28
infra/scripts/kaotings-alert.py
Normal file
@ -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())
|
||||||
6
infra/systemd/kaotings-alert.env.example
Normal file
6
infra/systemd/kaotings-alert.env.example
Normal file
@ -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
|
||||||
Loading…
Reference in New Issue
Block a user