Claude Code Router 配置备份与灾难恢复完整指南:从误删、换机到密钥泄露的救援手册
【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router
周三下午,你执行了一条清理临时文件的rm命令,顺手把~/.claude-code-router目录整个删掉了——供应商列表、路由规则、API 密钥三秒钟归零,而你的 AI 工作流还挂在上面。这时候最值钱的不是情绪,是备份。本文围绕 Claude Code Router(CCR)讲透配置备份与灾难恢复:哪些数据真正值得保护、快照怎么打才完整、自动化怎么落地,以及恢复流程如何提前演练到形成肌肉记忆。
读完本文,你可以做到:
- 准确定位 CCR 的持久化数据分布,判断"哪个文件丢了才会真出事"
- 用一条 tar 命令打出带 WAL 文件的完整快照,而不是只复制一个 JSON 就以为完事
- 给快照本身加锁:加密 + 异地同步,让密钥泄露和磁盘故障都伤不到你
- 建立可重复的恢复演练,把"出事时的慌乱"换成"按清单操作"
⚠️ 先看清风险:CCR 会遭遇的四种数据灾难
谈备份之前,先承认灾难是常态而非意外。对 CCR 这类本地控制面,最常见的四类事故是:
| 事故 | 触发方式 | 损失范围 |
|---|---|---|
| 误删/误覆盖 | 清理 home 目录、脚本rm -rf打错路径 | 全部配置,秒级不可逆 |
| 磁盘故障/系统重装 | SSD 掉盘、分区表损坏、强制升级系统 | 全部数据,包括用量与日志 |
| 换机迁移 | 换笔记本、从 VM 迁到裸机 | 需要"原样搬家"而非重装 |
| 密钥泄露 | 备份文件本身被同步到公开仓库、网盘 | 供应商账单风险,且备份里全是明文凭据 |
前三种靠"有快照"解决,第四种恰恰提醒我们:备份文件是第二敏感资产,后文会专门处理。
🗂️ 资产盘点:CCR 到底把什么存到了哪里
备份的前提是知道要备份什么。当前版本的 CCR 不再依赖单个config.json,核心配置存进了 SQLite 数据库:
~/.claude-code-router/config.sqlite(以及-wal、-shm两个附属文件):Providers、Router 规则、APIKEYS、插件与 Agent 配置都在这里;- 旧版用户可能还有遗留的
config.json,应用启动时会自动读取并归档,但迁移完成前它同样是资产; ~/.claude-code-router/app-data/子目录:usage.sqlite(用量)、request-logs.sqlite(请求日志)、context-archive.sqlite(上下文归档),以及certs/下的代理 CA 私钥key.pem——这个私钥泄露同样是大事;- Windows 上对应
%APPDATA%\Claude Code Router目录,结构一致。
两个关键推论:第一,快照的最小单位是整个配置目录,单拷一个文件必丢数据;第二,SQLite 的 WAL 模式下,-wal里可能躺着最近一批未合并的写入,拷主库不拷 WAL,快照就是不完整的。
另外,官方内置了数据导出能力:在管理界面触发导出后,会在~/Downloads生成形如claude-code-router-data-<时间戳>.json的文件,内含完整配置快照和各 SQLite 文件的 base64 副本(实现见packages/core/src/web/management-server.ts)。它适合一次性导出或换机传输,但它是"手动触发的一次性动作",不能替代定期快照。
📦 第一道防线:一条命令打出完整快照
日常快照的核心原则:先停服务,再打整包。停掉服务能保证 WAL 文件归位,快照才是自洽的。
CCR_HOME="$HOME/.claude-code-router" STAMP="$(date +%Y%m%d-%H%M)" DEST="$HOME/ccr-snapshots/$STAMP" ccr stop mkdir -p "$DEST" tar -czf "$DEST/ccr-config-$STAMP.tgz" -C "$HOME" \ ".claude-code-router/config.sqlite" \ ".claude-code-router/config.sqlite-wal" \ ".claude-code-router/config.sqlite-shm" \ ".claude-code-router/config.json" \ ".claude-code-router/app-data/usage.sqlite" ccr start这一步在做什么:ccr stop让数据库完成 WAL 合并,随后用 tar 把主库、WAL/SHM 附属文件、遗留 JSON 和用量库一起打成单个压缩包,-C "$HOME"保证包内是相对路径,恢复时不会写死你的用户名。config.json在旧版目录中不存在时 tar 会报 warning,属正常现象,不影响其余文件打包。
⏰ 第二道防线:让快照按时自己跑
手动快照坚持不过两周。下面这个脚本把"停服→打包→轮转清理"固化下来,保留最近 14 份,避免磁盘被快照撑爆。
#!/usr/bin/env bash # ccr-auto-snapshot.sh —— CCR 配置定时快照(保留最近 14 份) set -euo pipefail SNAP_ROOT="$HOME/ccr-snapshots" KEEP=14 NAME="$(date +%Y%m%d-%H%M)-$(hostname)" ccr stop tar -czf "$SNAP_ROOT/ccr-$NAME.tgz" -C "$HOME" \ .claude-code-router/config.sqlite \ .claude-code-router/config.sqlite-wal \ .claude-code-router/config.sqlite-shm \ .claude-code-router/app-data/usage.sqlite ccr start || true # 只保留最新 KEEP 份,更旧的自动清理 ls -1t "$SNAP_ROOT"/ccr-*.tgz | tail -n +$((KEEP + 1)) | xargs -r rm -f echo "snapshot done: $NAME"这一步在做什么:脚本把快照流程串成原子动作,KEEP控制轮转数量,hostname进文件名是为了同一备份根目录服务多台机器时不互相覆盖。
挂到 crontab,每天凌晨 4 点 15 分执行:
15 4 * * * $HOME/bin/ccr-auto-snapshot.sh >> $HOME/ccr-snapshots/snapshot.log 2>&1这一步在做什么:注册一个每日定时任务并把输出写入日志,方便日后排查"快照到底有没有跑成"。macOS 上可改用launchd的StartCalendarInterval达到同样效果。
🔐 第三道防线:加密 + 异地,让备份自己也安全
快照里躺着全部 API 密钥,明文快照同步到网盘或推到仓库,等于给泄露事故发邀请函。出本机之前先加一层对称加密:
ENC_KEY_FILE="$HOME/.ccr-backup.key" # 只生成一次,妥善保管 [ -f "$ENC_KEY_FILE" ] || openssl rand -hex 32 > "$ENC_KEY_FILE" LATEST="$(ls -1t "$HOME"/ccr-snapshots/ccr-*.tgz | head -n1)" openssl enc -aes-256-cbc -pbkdf2 -iter 100000 \ -in "$LATEST" \ -out "$LATEST.enc" \ -pass file:"$ENC_KEY_FILE"这一步在做什么:用 AES-256 对最新快照加密,密钥从固定文件读取(避免每次手输),密钥文件本身只留在本机、由你的密码管理器之外的安全位置托管。之后把.enc文件同步到另一台机器或对象存储,key.pem、CA 证书等敏感文件同步时也应走同样的加密通道。
配套的纪律是脱敏习惯:给同事或社区求助时,贴配置前先抹掉api_key字段;一旦怀疑某份快照外流,不要纠结找回,直接去各供应商控制台轮换密钥,这是比找回更快、也更彻底的止血方式。
🎬 恢复演练:把灾难提前彩排一遍
没演练过的恢复方案只是一份愿望清单。每月花十分钟做一次"干跑":
SNAP="$(ls -1t "$HOME"/ccr-snapshots/ccr-*.tgz | head -n1)" # 1) 先验包:内容清单能否完整列出 tar -tzf "$SNAP" # 2) 解到临时目录,不碰线上目录 rm -rf /tmp/ccr-drill && mkdir -p /tmp/ccr-drill tar -xzf "$SNAP" -C /tmp/ccr-drill # 3) 验证数据库真的可读:主配置表与密钥表应都有行 sqlite3 /tmp/ccr-drill/.claude-code-router/config.sqlite \ "SELECT count(*) FROM app_config; SELECT count(*) FROM api_keys;"这一步在做什么:不解压到线上目录的前提下,用tar -tzf验完整性,再用sqlite3直接查询 CCR 的app_config和api_keys两张表,确认快照里的数据库不是"能解压但已损坏"的假象。
真出事时的恢复顺序固定为四步,建议打印贴墙:
ccr stop停掉残留服务;- 把当前(可能已损坏的)配置目录整体挪到
~/.claude-code-router.broken-<日期>留证; - 将最近一份可用快照解包回
~/.claude-code-router,确认目录权限为 700、config.sqlite为 600(CCR 自身也按此权限维护数据库,手动恢复后请保持一致); ccr start启动并发一条最小路由请求验证,最后用管理界面确认可观测数据。
🛡️ 加固:四个让灾难少发生的习惯
- 权限不将就:目录 700、数据库文件 600,CCR 写入时会自动收紧权限,你手动恢复文件后务必复查;
- 密钥尽量不进文件:CCR 配置支持环境变量插值,把高价值密钥放环境变量而非写死,快照泄露的爆炸半径立刻缩小;
- 版本控制只收"无密"部分:自定义路由脚本、
custom-router逻辑可以进 Git 获得历史与回滚,但配置数据库和密钥文件严禁入库; - 轮换是常态:换机、换人、怀疑泄露这三个节点,无条件轮换 API 密钥,成本远低于事后追账。
✅ 最佳实践清单
- 知道 CCR 数据目录里每一个 SQLite 文件的作用,并确认快照覆盖全部
- 快照包含
config.sqlite及其-wal/-shm附属文件,且打快照前先ccr stop - 自动化任务已注册,且日志证明最近 7 天每次执行成功
- 快照保留策略已设定(建议 ≥ 14 份或 30 天)
- 出本机的备份全部经过加密,密钥与备份分开放置
- 本月做过一次恢复演练,
sqlite3查询验证通过 - 配置中已用环境变量插值替代明文密钥
延伸阅读:
- 配置存储与迁移实现:packages/core/src/config/config-repository.ts
- 数据导出功能实现:packages/core/src/web/management-server.ts
- 配置文件说明:docs/src/content/docs/zh/configuration/configuration-file.md
- 项目初衷及原理:blog/zh/项目初衷及原理.md
备份的价值从不体现在那叠安静的压缩包上,而体现在灾难发生的那一刻——你的恢复动作比恐慌更快。
【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考