Skip to content
English

备份和恢复 ​

单机部署模式下,FinClaw 的所有有状态数据都在 Docker 命名卷里(chatkit_* 前缀)。本节给出一种最简单可行的备份方案:停服 → 整卷打包 → 启服。生产环境如需 RPO/RTO 更严格的方案,可再叠加 pg_dump 逻辑备份或卷快照。

一、需要备份的内容 ​

1. 配置文件 ​

路径说明
deploy/.envLLM 凭证、JWT 密钥、内部 token、并发参数
deploy/config/services.yaml、ai-infra.yaml、idp.yaml 等 yaml 配置
deploy/docker-compose.override.yml(如有)自定义端口等覆写

2. Docker 数据卷 ​

chatkit_* 系列卷,全部由 docker-compose.yml 声明为 external: true:

卷名内容
chatkit_postgres_dataPostgreSQL 业务数据(用户/租户/画像/技能/收件箱/文档元数据,及飞书、钉钉、企微 connector 数据)
chatkit_timescaledb_dataTimescaleDB 数据(conversation-store 会话历史与审计数据)
chatkit_ai_infra_dataAI 运行时持久化数据(审计日志、记忆索引、会话状态、MCP servers 配置、fleet 运行时状态)
chatkit_workspaces用户工作区(文件、记忆文件、已安装技能)
chatkit_skills_data平台技能数据(builtin + catalog)
chatkit_persona_uploads画像服务上传文件
chatkit_identity_uploadsIdentity 服务上传文件(头像等)
chatkit_doc_toolkit_cache文档工具缓存(纯缓存,理论上可不备份;按「全打包」原则一并备份最稳妥)
chatkit_nats_dataNATS JetStream(事件流,短期消息)
chatkit_redis_dataRedis 缓存与协调状态
chatkit_restate_dataRestate 定时任务 / cron 状态
chatkit_tei_modelsTEI 向量模型文件(离线环境无法重新下载模型,必须备份)

单机部署的简单原则:chatkit_* 全打包 —— 不要试图人工筛选,漏掉一个就可能丢数据。

二、备份操作 ​

步骤 1:停服 ​

数据卷在容器运行期备份会得到不一致快照(特别是 PostgreSQL)。先停服再备份。

bash
cd /data/chatkit-offline-release-1.1.20-linux-amd64/deploy   # 按实际版本替换
./scripts/fleet.sh down

down 会停止全部容器(含 per-tenant 租户 Claw 容器),但不会删除任何数据卷。

步骤 2:打包配置 + 数据卷 ​

⚠️ 离线环境注意:打包/解包用的一次性容器必须使用离线包自带的镜像(见 manifests/basic-images.list),不要写 alpine、busybox 等需要联网拉取的外部镜像。本文统一使用 postgres:16-alpine——部署过本套服务的机器上必定存在。

bash
# 准备备份目录
BACKUP_DIR=/data/backups/finclaw-$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"

# 1) 配置:直接 tar 打包 deploy 目录里的关键文件
tar -czf "$BACKUP_DIR/deploy-config.tar.gz" -C /data/chatkit-offline-release-1.1.20-linux-amd64/deploy .env config docker-compose.override.yml 2>/dev/null || true

# 2) 确认 helper 镜像存在(部署过本套服务则必定存在,正常无输出即为 OK)
docker image inspect postgres:16-alpine >/dev/null && echo "helper image OK"

# 3) 数据卷:用一次性容器把每个卷的内容打包(tar 保留文件属主)
for vol in $(docker volume ls -q | grep '^chatkit_'); do
  echo ">> backing up volume: $vol"
  docker run --rm \
    -v "$vol":/source:ro \
    -v "$BACKUP_DIR":/backup \
    postgres:16-alpine \
    tar -czf "/backup/${vol}.tar.gz" -C /source .
done

# 4) 记录卷清单 + 版本信息
docker volume ls --filter "name=chatkit_" --format '{{.Name}}' > "$BACKUP_DIR/volumes.txt"
echo "release_dir=$(realpath /data/chatkit-offline-release-1.1.20-linux-amd64)" > "$BACKUP_DIR/meta.txt"
date -u +"backup_time=%Y-%m-%dT%H:%M:%SZ" >> "$BACKUP_DIR/meta.txt"

# 5) 校验并查看备份目录(备份数应与卷清单行数一致)
ls "$BACKUP_DIR"/chatkit_*.tar.gz | wc -l
cat "$BACKUP_DIR/volumes.txt" | wc -l
ls -lh "$BACKUP_DIR"
du -sh "$BACKUP_DIR"

全新部署为 12 个卷;从旧版本升级上来的机器可能残留少量已退役的历史卷(无容器挂载),一并打包无害。

备选方案(不起容器):在宿主机以 root 直接打包卷目录也可,无需任何镜像。先用 docker volume inspect 取卷的真实路径(与 Docker 数据目录配置无关),再对卷目录打 tar 包:

bash
# 备份:解析卷路径并打包
tar -czf <包路径> -C $(docker volume inspect -f '{{.Mountpoint}}' <卷名>) .

# 恢复(对称):先建卷再解包
docker volume create <卷名>
tar -xzf <包路径> -C $(docker volume inspect -f '{{.Mountpoint}}' <卷名>)

缺点是需要宿主机 root 权限(/var/lib/docker 目录仅 root 可读)。

步骤 3:启服 ​

bash
./scripts/fleet.sh up -d
./scripts/doctor.sh

备份产物示例 ​

text
/data/backups/finclaw-20260625-030000/
├── deploy-config.tar.gz           # .env + config/ + override
├── chatkit_postgres_data.tar.gz
├── chatkit_timescaledb_data.tar.gz
├── chatkit_ai_infra_data.tar.gz
├── chatkit_workspaces.tar.gz
├── chatkit_skills_data.tar.gz
├── chatkit_persona_uploads.tar.gz
├── chatkit_identity_uploads.tar.gz
├── chatkit_doc_toolkit_cache.tar.gz
├── chatkit_nats_data.tar.gz
├── chatkit_redis_data.tar.gz
├── chatkit_restate_data.tar.gz
├── chatkit_tei_models.tar.gz
├── volumes.txt                    # 卷名清单
└── meta.txt                       # 版本与备份时间戳

三、恢复操作 ​

步骤 1:停服并清空旧卷 ​

bash
cd /data/chatkit-offline-release-1.1.20-linux-amd64/deploy   # 按实际版本替换
./scripts/fleet.sh down

# 删除所有 chatkit_* 卷(确认要回滚到备份状态再执行!)
docker volume ls -q | grep '^chatkit_' | xargs -r docker volume rm

⚠️ 这步会丢失当前未备份的数据,确认无误再执行。

步骤 2:恢复配置 ​

bash
BACKUP_DIR=/data/backups/finclaw-20260625-030000   # 替换为你的备份目录

tar -xzf "$BACKUP_DIR/deploy-config.tar.gz" -C /data/chatkit-offline-release-1.1.20-linux-amd64/deploy

⚠️ .env 与数据卷必须配套恢复:USER_SECRETS_KEK(用户密钥加密密钥)与加密的用户数据绑定,ADMIN_EMAILS 决定哪些账号保有管理员身份。始终使用与数据卷同时备份的那份 .env;用重新 init-env.sh 初始化的 .env 搭配旧数据卷,加密的用户数据将无法解密。

步骤 3:恢复数据卷 ​

bash
# 逐个还原卷:先创建空卷,再把 tar.gz 解到卷里
# (一次性容器用 postgres:16-alpine,离线环境无需联网)
for tarball in "$BACKUP_DIR"/chatkit_*.tar.gz; do
  vol=$(basename "$tarball" .tar.gz)
  echo "<< restoring volume: $vol"
  docker volume create "$vol" >/dev/null
  docker run --rm \
    -v "$vol":/target \
    -v "$BACKUP_DIR":/backup:ro \
    postgres:16-alpine \
    tar -xzf "/backup/${vol}.tar.gz" -C /target
done

# 检查:卷数量应与备份清单一致
docker volume ls --filter "name=chatkit_" --format '{{.Name}}' | wc -l

步骤 4:启服 + 验证 ​

bash
./scripts/fleet.sh up -d
./scripts/doctor.sh
curl http://127.0.0.1:26100/health

预期 doctor.sh 全 ✅、/health 返回 200 OK。若个别服务首次启动较慢,等 2–5 分钟再跑一次。up -d 会在平台启动后自动重建租户 Claw 容器;若未重建,手动执行 ./scripts/reconcile-claw-deployments.sh --force。

Digital Ecosystem Infrastructure.