Initial LisgloSIPS V2 implementation

This commit is contained in:
hectorzhao
2026-06-22 10:56:38 +08:00
commit 5fa1bd35e9
303 changed files with 35644 additions and 0 deletions
+234
View File
@@ -0,0 +1,234 @@
# Server B MySQL 与 Redis Runbook
> 对应任务:S04
> 完成日期:2026-06-20
> 环境:本地开发 Server B
## 1. 版本与状态
| 服务 | 固定版本 | 监听 |
| --- | --- | --- |
| MySQL | 8.0.46-0ubuntu0.24.04.2 | 127.0.0.1:3306、127.0.0.1:33060 |
| Redis | 7.0.15-1ubuntu0.24.04.4 | 127.0.0.1:6379、100.90.90.91:6379 |
固定包:
```bash
apt-mark showhold | grep -E 'mysql|redis'
```
更新前必须先阅读安全公告、备份并执行恢复演练,然后显式 `apt-mark unhold`。不要长期忽略安全更新。
版本清单位于:
- B`/etc/lisglosips/versions.env`
- 仓库:`infra/server-b/s04/versions.env`
## 2. 数据目录
开发服务器没有独立数据盘。实际数据写入:
- `/data/mysql`
- `/data/redis`
为兼容 Ubuntu 包、AppArmor 和 systemd,使用 bind mount 保留标准服务路径:
```fstab
/data/mysql /var/lib/mysql none bind 0 0
/data/redis /var/lib/redis none bind 0 0
```
服务分别依赖 `var-lib-mysql.mount``var-lib-redis.mount`。迁移阿里云时必须改用独立数据盘,不能直接复制本地根盘布局。
## 3. MySQL 基线
配置:`/etc/mysql/mysql.conf.d/99-lisglosips.cnf`
- 仅绑定回环地址;
- 业务库:`lisglosips`utf8mb4
- binlog 已启用,格式 ROW,保留 7 天;
- `sync_binlog=1`
- `innodb_flush_log_at_trx_commit=1`
- 数据库默认时区 UTC
- 禁止 `local_infile` 和 DNS 主机名解析;
- 慢查询阈值 1 秒;
- InnoDB buffer pool 1 GiB,最大连接数 200。
账号:
| 账号 | 来源 | 权限 |
| --- | --- | --- |
| lisglosips_app | 127.0.0.1 | SELECT/INSERT/UPDATE/DELETE/EXECUTE |
| lisglosips_migrate | 127.0.0.1 | `lisglosips.*` 全权限,用于迁移 |
应用账号不能 DDL;S04 已用实际 ALTER 拒绝测试验证。
## 4. Redis 基线
配置:
- `/etc/redis/redis-lisglosips.conf`
- `/etc/redis/users.acl`
关键策略:
- protected mode 开启;
- AOF everysec 与 RDB 快照同时启用;
- 最大内存 1536 MiB
- `maxmemory-policy=noeviction`,业务热数据和 Stream 不静默淘汰;
- 默认用户关闭;
- `lisglosips` 允许业务命令但移除 dangerous 类命令;
- `lisglo-backup` 仅允许 PING、INFO、BGSAVE、LASTSAVE。
Redis 绑定 Tailscale 地址。`lisglosips-tailscale-ready.service` 会先等待 100.90.90.91/32 出现,避免 Redis 开机首次启动竞态。
## 5. 凭据
本地 DPAPI 加密文件:
`.codex-private/SERVICE_CREDENTIALS.clixml`
包含:
- MYSQL_APP
- MYSQL_MIGRATE
- REDIS_APP
- REDIS_BACKUP
B 机:
| 文件 | 权限 |
| --- | --- |
| `/etc/lisglosips/secrets/mysql-app.env` | root:lisglosips 0640 |
| `/etc/lisglosips/secrets/mysql-migrate.env` | root:root 0600 |
| `/etc/lisglosips/secrets/redis.env` | root:lisglosips 0640 |
| `/etc/lisglosips/secrets/redis-backup.env` | root:root 0600 |
| `/etc/redis/users.acl` | root:redis 0640 |
禁止在聊天、日志、状态文件、仓库或命令参数中输出密码。
## 6. 网络安全
- MySQL 不允许远程连接。
- Redis 仅允许 A 的 Tailscale IP 100.90.90.90 通过 B 的 nftables 访问。
- T 对 3306/6379 的连接已验证为超时拒绝。
- A 第一次访问 B 时可能需要先建立 Tailscale direct 路径:
```bash
tailscale ping --c 1 100.90.90.91
```
稳态 direct 后 Redis 认证连接正常。
## 7. 自动备份
脚本:
- `/usr/local/sbin/lisglosips-mysql-backup`
- `/usr/local/sbin/lisglosips-redis-backup`
systemd
- `lisglosips-backup.service`
- `lisglosips-backup.timer`
每天 03:15 执行,随机延迟最多 15 分钟,保留 14 天。
备份目录:
```text
/data/backups/mysql/YYYYMMDDTHHMMSSZ/
all-databases.sql.gz
lisglosips.sql.gz
metadata.tsv
SHA256SUMS
/data/backups/redis/YYYYMMDDTHHMMSSZ/
dump.rdb
redis-check-rdb.txt
metadata.txt
SHA256SUMS
```
首次有效备份:`20260620T120955Z`
检查:
```bash
sudo systemctl start lisglosips-backup.service
sudo systemctl show -p Result lisglosips-backup.service
sudo systemctl list-timers lisglosips-backup.timer
cd /data/backups/mysql/LATEST_DIRECTORY && sudo sha256sum -c SHA256SUMS
cd /data/backups/redis/LATEST_DIRECTORY && sudo sha256sum -c SHA256SUMS
```
MySQL 全库备份包含账号密码哈希,只允许 root 读取。Redis ACL 明文密码不进入自动备份,灾难恢复时从 DPAPI 凭据重新生成。
## 8. 恢复
### MySQL 业务库
先创建空的临时数据库进行验证:
```bash
sudo mysql -e 'CREATE DATABASE lisglosips_restore_test CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;'
gzip -dc /data/backups/mysql/TIMESTAMP/lisglosips.sql.gz | sudo mysql lisglosips_restore_test
sudo mysql -e 'SHOW TABLES FROM lisglosips_restore_test;'
```
确认数据后再安排正式恢复窗口。禁止直接将 `all-databases.sql.gz` 覆盖到运行中的生产实例。
### Redis RDB
将备份 `dump.rdb` 复制到独立临时目录,用 `port 0` 和独立 Unix socket 启动临时 Redis,验证关键 key 后关闭。不要替换运行中实例的 RDB/AOF。
S04 已完成:
- MySQL 备份后删除源表,恢复到临时库并验证 token;
- Redis 备份后删除源 key,恢复到独立实例并验证 token;
- 两类探针和临时实例均已清理。
## 9. 健康检查
```bash
systemctl is-active mysql redis-server lisglosips-backup.timer
mysqladmin --protocol=socket ping
sudo mysql -e 'SELECT @@version, @@log_bin, @@binlog_format, @@time_zone;'
sudo findmnt /var/lib/mysql
sudo findmnt /var/lib/redis
sudo systemctl show redis-server -p Result -p NRestarts
sudo journalctl -b -u mysql -u redis-server -p err
```
验收状态:
- 重启后 MySQL/Redis active
- Redis 首次启动 `NRestarts=0`
- 没有 failed systemd unit
- AOF 写入和 RDB BGSAVE 均正常;
- 重启持久化探针通过并已清理。
## 10. 回滚
S04 前备份:
`/var/backups/lisglosips-s04/20260620195847`
包含配置基线、迁移前 MySQL/Redis 数据目录压缩包、变更后配置、失败演练样本和 SHA-256 清单。
回滚数据目录必须在维护窗口执行:
1. 停止 `lisglosips-backup.timer`、MySQL 和 Redis。
2. 卸载 `/var/lib/mysql``/var/lib/redis`
3. 恢复 S04 前 fstab。
4. 将当前数据目录另行归档,不直接覆盖。
5. 解压 `mysql.pre-s04.tar.gz``redis.pre-s04.tar.gz``/var/lib`
6. 恢复配置后执行语法检查,再逐个启动服务。
不要在没有完整备份与控制台访问的情况下卸载、覆盖或降级数据库包。
## 11. 已知事项
- 早期一次备份使用绝对校验路径,已移至 S04 备份目录下的 `failed-backups` 留档,不参与恢复。
- 本地根盘适合开发,不满足生产数据库与录音故障隔离要求。
- 软件包处于 hold;上线前需建立定期安全更新和预生产验证流程。