Skip to content
中文

Backup and Recovery

On a single-machine deployment, all of FinClaw's stateful data lives in Docker named volumes (the chatkit_* family). This page gives the simplest viable backup procedure: stop → archive every volume → start.

1. What to Back Up

1.1 Configuration Files

PathWhat it holds
deploy/.envLLM credentials, JWT keys, internal tokens, concurrency settings
deploy/config/services.yaml, ai-infra.yaml, idp.yaml, etc.
deploy/docker-compose.override.yml (if any)Custom port mapping or other overrides

1.2 Docker Volumes

The chatkit_* volumes — all declared external: true in docker-compose.yml:

VolumeContents
chatkit_postgres_dataPostgreSQL data (identity / inbox / persona / skill / document / pulse)
chatkit_timescaledb_dataTimescaleDB data (conversation-store history)
chatkit_ai_infra_dataAI runtime state (audit logs, memory index, sessions, mcp-servers.yaml)
chatkit_workspacesUser workspaces (installed skills, memory files)
chatkit_skills_dataPlatform skills data (populated by skills-init)
chatkit_persona_uploadsPersona service uploads
chatkit_identity_uploadsIdentity service uploads (avatars, etc.)
chatkit_doc_toolkit_cacheDoc toolkit cache
chatkit_nats_dataNATS JetStream (event streams, short-lived)
chatkit_redis_dataRedis cache and coordination state
chatkit_restate_dataRestate timers and cron state
chatkit_tei_modelsTEI model cache

Simple rule for single-machine: archive every chatkit_* volume. Don't try to cherry-pick — one missed volume can mean data loss.

2. Backup

Step 1 — Stop the services

Backing up volumes while containers are running yields an inconsistent snapshot (especially for PostgreSQL). Stop first.

bash
cd /data/chatkit-offline-release-1.0.xx-linux-amd64/deploy
./scripts/fleet.sh basic down

down only stops the containers; it does not delete volumes.

Step 2 — Archive config + volumes

bash
# Prepare a backup directory
BACKUP_DIR=/data/backups/finclaw-$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"

# 1) Configuration files
tar -czf "$BACKUP_DIR/deploy-config.tar.gz" \
  -C /data/chatkit-offline-release-1.0.xx-linux-amd64/deploy \
  .env config docker-compose.override.yml 2>/dev/null || true

# 2) Volumes — one-shot container archives each volume's contents
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 \
    alpine \
    tar -czf "/backup/${vol}.tar.gz" -C /source .
done

# 3) Record volume list + release metadata
docker volume ls --filter "name=chatkit_" --format '{{.Name}}' > "$BACKUP_DIR/volumes.txt"
echo "release_dir=$(realpath /data/chatkit-offline-release-1.0.xx-linux-amd64)" > "$BACKUP_DIR/meta.txt"
date -u +"backup_time=%Y-%m-%dT%H:%M:%SZ" >> "$BACKUP_DIR/meta.txt"

# 4) Inspect the backup
ls -lh "$BACKUP_DIR"

Step 3 — Start the services

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

Backup Layout

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                    # list of volume names
└── meta.txt                       # release path + backup timestamp

3. Restore

Step 1 — Stop services and remove existing volumes

bash
cd /data/chatkit-offline-release-1.0.xx-linux-amd64/deploy
./scripts/fleet.sh basic down

# Remove all chatkit_* volumes (confirm you want to roll back!)
docker volume ls -q | grep '^chatkit_' | xargs -r docker volume rm

⚠️ This drops any data not in the backup. Double-check before executing.

Step 2 — Restore configuration

bash
BACKUP_DIR=/data/backups/finclaw-20260625-030000   # replace with your backup dir

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

Step 3 — Restore volumes

bash
# Restore each volume: create an empty volume, then unpack the tar into it
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 \
    alpine \
    tar -xzf "/backup/${vol}.tar.gz" -C /target
done

Step 4 — Start and verify

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

Expected: doctor.sh returns all ✅ and /health returns 200 OK. Allow 2–5 minutes for slow first starts.

Digital Ecosystem Infrastructure.