www_site/docs/OPERATIONS.md
flym 99976ef77f docs: record configured offsite NAS backup (rsync over SSH)
Offsite backup to the Synology NAS (103.40.14.100:52200) is now configured:
pg_dump of business+CMS DBs (keep 7 per series) plus rsync of the audio dir,
encrypted over SSH with key auth, on a daily 03:00 systemd timer. Document the
destination, transport, script, timer, and restore-from-NAS procedure; mark the
backup-location item resolved (retention/threshold/owner still pending).
2026-09-10 15:24:04 +08:00

5.8 KiB
Raw Blame History

运维方案OPERATIONS

日期2026-09-10 · 版本 8657f44 范围:音频容量/保留/清理/备份/恢复、数据库备份/恢复、Worker 与额度对账、告警。本轮不擅自删除任何既有音频。

1. 音频存储现状

  • 位置:/home/flym/kaotings-audio,布局 {user_id}/{task_id}.wav(私有本地目录,非对象存储)。
  • 元数据:audio_filesstorage_keymime_typesize_byteschecksumstatusexpires_at)。
  • 写入:成功结算时先写文件、再登记 audio_files(含 SHA256
  • 读取:回放/下载按 storage_key 取文件;文件缺失返回 404优雅降级

2. 备份(已配置异地备份)

  • 本机暂存:/home/flym/backups/(仅存放 .dump)。
  • 异地备份目标:Synology NAS 103.40.14.100Synology DSM账号 kts_bak,落盘 /var/services/homes/kts_bak/backup/kaotings/db/ + audio/),可用容量约 92 GiB。
  • 传输方式:rsync over SSH(端口 52200加密),密钥认证(/root/.ssh/id_ed25519_ktsbak,公钥已加入 NAS kts_bakauthorized_keys)。不使用 公网明文 rsync 守护端口 50873
  • 脚本:/usr/local/sbin/kaotings-backup.shroot 运行):
    1. pg_dump --format=custom 业务库(/etc/kaotings/api.envDATABASE_URL)与 CMS 库(/etc/kaotings/cms.envDATABASE_URI)。
    2. 每库保留最近 7 份(按序列独立轮转)。
    3. rsync -a --delete 增量镜像 db/audio/AUDIO_STORAGE_DIR)到 NAS。
  • 定时systemd kaotings-backup.timer,每日 03:00Persistent=trueRandomizedDelaySec=30min)触发 kaotings-backup.service
  • 验证:首份备份已落盘(业务库 54K、CMS 48K、音频 22 文件 4.8Mpg_restore --list 确认归档可恢复。
对象 工具 本机 异地NAS
业务库 kaotings pg_dump --format=custom /home/flym/backups/kaotings_<ts>.dump …/backup/kaotings/db/
CMS 库 kaotings_cms pg_dump --format=custom /home/flym/backups/kaotings_cms_<ts>.dump …/backup/kaotings/db/
音频目录 rsync -a --delete /home/flym/kaotings-audio/ …/backup/kaotings/audio/

仍待用户确认:音频保留期、磁盘告警阈值、是否启用按 expires_at 的定时清理(见 §5。备份保留份数当前=7可按需调整脚本 KEEP

3. 容量 / 保留 / 清理(需用户决定的参数集中列出)

参数 当前值 需用户决定
音频保留期 AUDIO_RETENTION_SECONDS 7 天(默认) 是(产品/隐私/存储预算)
磁盘容量上限 / 告警阈值 根盘约 48 GiB 可用,无上限告警 是(阈值 + 通知方式)
保留期清理策略 未启用定时清理(仅启动时清孤儿) 是(是否按 expires_at 定时删除)
原始文本保留期 存于 tts_tasks.text 是(产品/隐私)
备份保留份数 / 周期 已配置:每库 7 份 · 每日 03:00 · 异地 NAS 否(可调脚本 KEEP 与 timer
  • 清理安全边界:
    • 启动时 cleanup_orphan_audio 仅删除“ available 记录且 mtime>1h”的孤儿文件。
    • 保留期清理在参数确认并实现后启用;在此之前不删除任何既有音频
  • 告警:磁盘使用率超阈值、audio_files 与磁盘文件数量长期不一致、Worker 长期无 queued 消化。

4. 恢复(含隔离演练结果)

4.1 流程

  1. 停止写入(可选,视 RPOsystemctl stop kaotings-api
  2. 建空库 → pg_restore --clean --if-exists 业务库 / CMS 库。
  3. 音频:从 NAS 异地备份 rsync/scp/home/flym/kaotings-audio(源:…/backup/kaotings/audio/)。
  4. 校验:行数、音频文件↔audio_files 关联、checksum、额度↔流水一致(见 §4.2 校验 SQL
  5. systemctl start kaotings-api/healthz 复核。

4.2 校验(隔离演练已执行)

  • 业务库行数源=恢复users 35 / quota 34 / tasks 28 / audio 26 / usage 61 / grants 10。
  • 额度↔流水:usedconsumereservedreserve-consume-release 均 0 不符。
  • 音频:磁盘 22 文件全部被 available 引用(无孤儿)。
  • 发现4 条 status=available 且任务 succeededaudio_files 行在磁盘无文件(既有不一致,回放 404 降级)。待调查根因(见 §6

4.3 Worker 重启 / 额度对账

  • 单 Workersystemd 单进程),原子领取(FOR UPDATE SKIP LOCKED+ 5 分钟租约 + 过期 running 回收(WORKER_LEASE_EXPIRED,释放冻结)。
  • 对账:GET /admin/usage/summary 汇总 quota_accountsusage_records 口径;GET /admin/tts/tasks 查结算状态consumed/released/pending
  • 不变式(每账户恒成立):limit_snapshot + adjustment - used - reserved >= 0(由 Phase 5 异常矩阵 S3/S4 保证)。

5. 待用户确认清单(集中)

  1. 音频保留期(AUDIO_RETENTION_SECONDS)。
  2. 磁盘容量上限与告警阈值、通知方式。
  3. 是否启用按 expires_at 的定时保留期清理。
  4. 原始文本保留期。
  5. 备份:异地 NAS 已配置(103.40.14.100,每日 03:00每库 7 份);剩余待确认:保留份数/周期是否调整、备份责任人。
  6. 上游 HTTPS/加密端点、允许来源网段、凭据轮换(见 DEPLOYMENT.md §4

6. 待调查 / 未闭环项(不标为完成)

  • 4 条 available 音频行无对应文件:既有 DB/文件系统不一致,待定位根因(文件被外部删除 or 写入路径异常);恢复流程本身通过。
  • 上游公网 HTTP:上线阻断,待加密 + 来源限制 + 外部复测(DEPLOYMENT.md §4
  • 音频容量/保留/清理参数待用户确认§5