Backup and Restore
This section covers backup and restore operations for BK-Lite's critical components, helping operations engineers develop a data protection strategy.
Backup Priority
Based on data importance, the following backup priority is recommended:
| Priority | Component | Data Type | Recommended Frequency |
|---|---|---|---|
| P0 | PostgreSQL | Core business data | Daily full + real-time archiving |
| P0 | PGVector (metis) | AI vector data | Daily full |
| P1 | FalkorDB | CMDB graph data | Daily full |
| P2 | MinIO | Files/model artifacts | Weekly full + daily incremental |
| P2 | VictoriaMetrics | Monitoring metrics | As needed (can be re-collected) |
| P2 | VictoriaLogs | Log data | As needed (can be re-collected) |
| P3 | Redis (rebuildable cache when RUM is disabled) | Cache data | Depends on actual use |
| P1 | Conductor (managed Workflow engine) | SQLite engine data | Daily and before upgrades; consistent backup |
| P1 | RUM (when enabled) | Configuration/keys, Redis state, replay, queue, Logs/Traces | Coordinated backups based on recovery objectives |
Prerequisites
Deployment Directory
BK-Lite is deployed by default in the /opt/bk-lite directory. All docker compose commands must be executed from this directory:
# Navigate to the deployment directory
cd /opt/bk-lite
# Check currently running services
docker compose ps
# Load environment variables (for obtaining passwords and other config in scripts)
source .env
All commands below assume execution from the /opt/bk-lite directory. If you use a custom deployment directory, adjust the paths accordingly.
Create Backup Directory
# Create backup root directory
mkdir -p /data/backup/bklite/{postgres,pgvector,falkordb,victorialogs,minio}
# Set permissions
chmod 750 /data/backup/bklite
PostgreSQL Backup and Restore
PostgreSQL stores the system's core business data and is the most important backup target.
Database Details
| Database | Purpose | Backup Necessity |
|---|---|---|
bklite | Main business data (users, configurations, CMDB, etc.) | Required |
mlflow | MLflow experiment tracking data | Recommended |
Full Backup
# Backup all databases
docker compose exec -T postgres pg_dumpall -U postgres > /data/backup/bklite/postgres/full_$(date +%Y%m%d_%H%M%S).sql
# Or backup individual databases (recommended)
docker compose exec -T postgres pg_dump -U postgres -d bklite > /data/backup/bklite/postgres/bklite_$(date +%Y%m%d_%H%M%S).sql
docker compose exec -T postgres pg_dump -U postgres -d mlflow > /data/backup/bklite/postgres/mlflow_$(date +%Y%m%d_%H%M%S).sql
Compressed Backup (Recommended for Production)
# Backup in custom format (supports parallel restore)
docker compose exec -T postgres pg_dump -U postgres -Fc -d bklite > /data/backup/bklite/postgres/bklite_$(date +%Y%m%d_%H%M%S).dump
docker compose exec -T postgres pg_dump -U postgres -Fc -d mlflow > /data/backup/bklite/postgres/mlflow_$(date +%Y%m%d_%H%M%S).dump
Restore Database
The restore operation will overwrite existing data. Make sure the target environment is correct!
# Restore from SQL file
docker compose exec -T postgres psql -U postgres -d bklite < /data/backup/bklite/postgres/bklite_20240101_120000.sql
# Restore from dump file (requires an empty database first)
cat /data/backup/bklite/postgres/bklite_20240101_120000.dump | docker compose exec -T postgres pg_restore -U postgres -d bklite -c
Automated Backup Script
Create a scheduled backup script at /opt/bk-lite/scripts/backup_postgres.sh:
#!/bin/bash
set -e
BACKUP_DIR="/data/backup/bklite/postgres"
KEEP_DAYS=7
DATE=$(date +%Y%m%d_%H%M%S)
BKLITE_DIR="/opt/bk-lite"
cd "${BKLITE_DIR}"
# Create backup
echo "[$(date)] Starting PostgreSQL backup..."
docker compose exec -T postgres pg_dump -U postgres -Fc -d bklite > "${BACKUP_DIR}/bklite_${DATE}.dump"
docker compose exec -T postgres pg_dump -U postgres -Fc -d mlflow > "${BACKUP_DIR}/mlflow_${DATE}.dump"
# Clean up expired backups
find "${BACKUP_DIR}" -name "*.dump" -mtime +${KEEP_DAYS} -delete
echo "[$(date)] PostgreSQL backup completed."
Add to crontab:
# Execute backup daily at 2:00 AM
0 2 * * * /opt/bk-lite/scripts/backup_postgres.sh >> /var/log/bklite_backup.log 2>&1
PGVector Backup and Restore
PGVector runs as a PostgreSQL extension, with its data stored in the metis database.
Backup Vector Data
cd /opt/bk-lite
# PGVector runs in a separate container, connected via the postgres container
# Backup the metis database (contains vector tables)
docker compose exec -T postgres pg_dump -U postgres -Fc -d metis > /data/backup/bklite/pgvector/metis_$(date +%Y%m%d_%H%M%S).dump
Restore Vector Data
cd /opt/bk-lite
# Ensure the pgvector extension is installed before restoring
docker compose exec -T postgres psql -U postgres -d metis -c "CREATE EXTENSION IF NOT EXISTS vector;"
# Restore data
cat /data/backup/bklite/pgvector/metis_20240101_120000.dump | docker compose exec -T postgres pg_restore -U postgres -d metis -c
If restoring to a new environment, you need to create the metis database first:
docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE metis;"
FalkorDB Backup and Restore
FalkorDB is based on the Redis protocol and stores CMDB asset relationship graphs.
FalkorDB maps port 6479:6379 in Docker Compose, meaning the host uses port 6479.
Backup Methods
FalkorDB supports two backup methods:
Method 1: RDB Snapshot (Recommended)
cd /opt/bk-lite
source .env
# Trigger RDB persistence
docker compose exec falkordb redis-cli -a ${FALKORDB_PASSWORD} BGSAVE
# Wait for backup to complete (check last save time)
docker compose exec falkordb redis-cli -a ${FALKORDB_PASSWORD} LASTSAVE
# Copy RDB file
docker compose cp falkordb:/var/lib/falkordb/data/dump.rdb /data/backup/bklite/falkordb/dump_$(date +%Y%m%d_%H%M%S).rdb
Method 2: Data Volume Backup
cd /opt/bk-lite
# Stop service (optional, ensures data consistency)
docker compose stop falkordb
# Get volume name
VOLUME_NAME=$(docker volume ls --filter name=falkordb -q | head -1)
# Backup data volume
docker run --rm -v ${VOLUME_NAME}:/source -v /data/backup/bklite/falkordb:/backup alpine \
tar czf /backup/falkordb_volume_$(date +%Y%m%d_%H%M%S).tar.gz -C /source .
# Restart service
docker compose start falkordb
Restore Methods
Restore from RDB File
cd /opt/bk-lite
# Stop FalkorDB
docker compose stop falkordb
# Copy RDB file to data volume
docker compose cp /data/backup/bklite/falkordb/dump_20240101_120000.rdb falkordb:/var/lib/falkordb/data/dump.rdb
# Start FalkorDB (automatically loads RDB)
docker compose start falkordb
Restore from Data Volume Backup
cd /opt/bk-lite
# Stop service
docker compose stop falkordb
# Get volume name
VOLUME_NAME=$(docker volume ls --filter name=falkordb -q | head -1)
# Clear and restore data volume
docker run --rm -v ${VOLUME_NAME}:/target -v /data/backup/bklite/falkordb:/backup alpine \
sh -c "rm -rf /target/* && tar xzf /backup/falkordb_volume_20240101_120000.tar.gz -C /target"
# Start service
docker compose start falkordb
VictoriaLogs Backup and Restore
VictoriaLogs stores log data on port 9428. Log data can typically be re-collected, but retaining historical logs may be valuable for auditing and analysis.
VictoriaLogs data is stored in the victoria-logs data volume under the /vlogs directory.
Backup Methods
Method 1: Online Snapshot (Recommended)
VictoriaLogs supports online snapshots with no downtime required:
cd /opt/bk-lite
# Create snapshot
docker compose exec victoria-logs wget -qO- 'http://localhost:9428/snapshot/create'
# List snapshots
docker compose exec victoria-logs ls -la /vlogs/snapshots/
# Copy snapshot directory
SNAPSHOT_NAME=$(docker compose exec victoria-logs ls /vlogs/snapshots/ | tail -1 | tr -d '\r')
docker compose cp victoria-logs:/vlogs/snapshots/${SNAPSHOT_NAME} /data/backup/bklite/victorialogs/snapshot_$(date +%Y%m%d_%H%M%S)
Method 2: Data Volume Backup
cd /opt/bk-lite
# Stop service (ensures data consistency)
docker compose stop victoria-logs
# Get volume name
VOLUME_NAME=$(docker volume ls --filter name=victoria-logs -q | head -1)
# Backup data volume
docker run --rm -v ${VOLUME_NAME}:/source -v /data/backup/bklite/victorialogs:/backup alpine \
tar czf /backup/victorialogs_volume_$(date +%Y%m%d_%H%M%S).tar.gz -C /source .
# Restart service
docker compose start victoria-logs
Restore Methods
Restore from Snapshot
cd /opt/bk-lite
# Stop service
docker compose stop victoria-logs
# Get volume name
VOLUME_NAME=$(docker volume ls --filter name=victoria-logs -q | head -1)
# Clear data directory and restore snapshot
docker run --rm -v ${VOLUME_NAME}:/vlogs -v /data/backup/bklite/victorialogs:/backup alpine \
sh -c "rm -rf /vlogs/* && cp -r /backup/snapshot_20240101_120000/* /vlogs/"
# Start service
docker compose start victoria-logs
Restore from Data Volume Backup
cd /opt/bk-lite
# Stop service
docker compose stop victoria-logs
# Get volume name
VOLUME_NAME=$(docker volume ls --filter name=victoria-logs -q | head -1)
# Clear and restore data volume
docker run --rm -v ${VOLUME_NAME}:/target -v /data/backup/bklite/victorialogs:/backup alpine \
sh -c "rm -rf /target/* && tar xzf /backup/victorialogs_volume_20240101_120000.tar.gz -C /target"
# Start service
docker compose start victoria-logs
RUM and Workflow Backup and Restore
The generic backup script and disaster recovery steps below do not cover all optional component data. Follow these additional steps when enabled. See the deployment guide for component selection.
Configuration and Versions
Save common.env, .env, the generated docker-compose.yaml, selected component templates, and current image references/digests from the actual deployment directory. Encrypt backups containing credentials and restrict access. Record actual volume mounts and restore the original volumes or their contents to the correct replacement volumes; starting a service with the same name does not restore its data.
Workflow / Conductor
The managed engine mounts compose_conductor at /data, containing conductor.db and its WAL/SHM files:
- Pause workflow entry points and new triggers, drain running executions or suspend them as required, stop Workflow background processes, then run
docker compose stop conductor. - With the engine stopped, back up the entire volume, preserving permissions. Copying only a live
conductor.dbis insufficient. Also back up workflow definitions/history in platform PostgreSQL, artifacts in MinIO, and connection settings. - Start the engine and verify health, then resume background processes and triggers. Schedule downtime so triggers do not keep submitting work during the backup.
- For restoration, keep writes paused, restore matching engine data, platform data, image versions, and
CONDUCTOR_BASE_URL, then start services and verify execution, approval, and artifact downloads.
Back up external engines according to their database/storage design. Changing the engine endpoint does not migrate data. Rollback requires the previous image and matching data backup. Never allow two engines to write to the same SQLite volume.
RUM
RUM spans multiple stores; platform PostgreSQL and the platform victoria-logs volume alone are insufficient:
- Configuration and keys: Preserve
RUM_IDENTITY_HMAC_CURRENT,RUM_REPLAY_SIGNING_SECRET,RUM_REPLAY_INDEX_EPOCH, dedicated NATS credentials, and thecompose_rum-secretsvolume. Restore the original identities, signing material, and actual index epoch rather than generating replacements. - Shared Redis: RUM uses DB0 for admission, DB2 for replay indexes, and DB4 for sessions. Back up according to the configured persistence and verify recovery coverage. Redis must not be treated entirely as disposable cache. Restoring the shared instance affects other modules, so coordinate recovery points.
- Replay and queue: Back up the MinIO
rum-replaybucket, including required object versions when versioning is enabled, andcompose_rum-gateway-queue. Undelivered queue events may not yet exist in backend stores. Do not directly merge two nonempty queues during recovery. - Experience and trace data: Back up
compose_rum-victoria-logsandcompose_rum-victoria-tracesvolumes separately, or use the respective storage backup procedures. These are independent of platform logs and APM stores. Historical browser visits generally cannot be collected again.
For consistent volume backups, pause browser ingestion, RUM writers, and maintenance processes, and coordinate backup times across shared Redis/MinIO and dedicated Logs/Traces. Account for other modules before stopping shared services. Restore configuration, keys, and stores while writes remain paused, then restore RUM services. After signing in, confirm controlAvailable is true at /api/v1/rum/health/, and verify historical queries, replay, and new writes. Disabling a module retains data but is not a backup.
Complete Backup Script
Create an all-in-one backup script at /opt/bk-lite/scripts/backup_all.sh:
#!/bin/bash
set -e
# Configuration
BACKUP_ROOT="/data/backup/bklite"
BKLITE_DIR="/opt/bk-lite"
KEEP_DAYS=7
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/bklite_backup.log"
# Navigate to deployment directory and load environment variables
cd "${BKLITE_DIR}"
source .env
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE}
}
log "========== Starting Backup =========="
# Ensure backup directories exist
mkdir -p "${BACKUP_ROOT}"/{postgres,pgvector,falkordb,victorialogs}
# 1. PostgreSQL
log "Backing up PostgreSQL..."
docker compose exec -T postgres pg_dump -U postgres -Fc -d bklite > "${BACKUP_ROOT}/postgres/bklite_${DATE}.dump"
docker compose exec -T postgres pg_dump -U postgres -Fc -d mlflow > "${BACKUP_ROOT}/postgres/mlflow_${DATE}.dump"
log "PostgreSQL backup completed"
# 2. PGVector (metis)
log "Backing up PGVector..."
docker compose exec -T postgres pg_dump -U postgres -Fc -d metis > "${BACKUP_ROOT}/pgvector/metis_${DATE}.dump"
log "PGVector backup completed"
# 3. FalkorDB
log "Backing up FalkorDB..."
docker compose exec falkordb redis-cli -a ${FALKORDB_PASSWORD} BGSAVE 2>/dev/null || true
sleep 5 # Wait for BGSAVE to complete
docker compose cp falkordb:/var/lib/falkordb/data/dump.rdb "${BACKUP_ROOT}/falkordb/dump_${DATE}.rdb"
log "FalkorDB backup completed"
# 4. VictoriaLogs (optional)
log "Backing up VictoriaLogs..."
docker compose exec victoria-logs wget -qO- 'http://localhost:9428/snapshot/create' || true
sleep 2
SNAPSHOT_NAME=$(docker compose exec victoria-logs ls /vlogs/snapshots/ 2>/dev/null | tail -1 | tr -d '\r')
if [ -n "${SNAPSHOT_NAME}" ]; then
docker compose cp victoria-logs:/vlogs/snapshots/${SNAPSHOT_NAME} "${BACKUP_ROOT}/victorialogs/snapshot_${DATE}"
log "VictoriaLogs backup completed"
else
log "VictoriaLogs backup skipped (no snapshot)"
fi
# 5. Clean up expired backups
log "Cleaning up backups older than ${KEEP_DAYS} days..."
find "${BACKUP_ROOT}" -type f \( -name "*.dump" -o -name "*.rdb" -o -name "*.tar.gz" \) -mtime +${KEEP_DAYS} -delete
find "${BACKUP_ROOT}" -type d -name "snapshot_*" -mtime +${KEEP_DAYS} -exec rm -rf {} + 2>/dev/null || true
log "========== Backup Completed =========="
# List backup files
log "Backup files from this run:"
find "${BACKUP_ROOT}" -type f -mmin -10 -exec ls -lh {} \;
Scheduled Task Configuration
# Add execute permission
chmod +x /opt/bk-lite/scripts/backup_all.sh
# Configure crontab
crontab -e
# Add the following (execute daily at 2:00 AM)
0 2 * * * /opt/bk-lite/scripts/backup_all.sh
Disaster Recovery Procedure
When you need to restore the entire system in a new environment, follow these steps in order:
1. Deploy Base Environment
# Install BK-Lite (without data initialization)
curl -sSL https://bklite.cn/install.run | bash -
2. Stop Services
cd /opt/bk-lite
docker compose stop server web
3. Restore Databases
cd /opt/bk-lite
# Restore PostgreSQL
docker compose exec -T postgres psql -U postgres -c "DROP DATABASE IF EXISTS bklite;"
docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE bklite;"
cat /path/to/bklite_backup.dump | docker compose exec -T postgres pg_restore -U postgres -d bklite
# Restore MLflow database
docker compose exec -T postgres psql -U postgres -c "DROP DATABASE IF EXISTS mlflow;"
docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE mlflow;"
cat /path/to/mlflow_backup.dump | docker compose exec -T postgres pg_restore -U postgres -d mlflow
# Restore PGVector (metis)
docker compose exec -T postgres psql -U postgres -c "DROP DATABASE IF EXISTS metis;"
docker compose exec -T postgres psql -U postgres -c "CREATE DATABASE metis;"
docker compose exec -T postgres psql -U postgres -d metis -c "CREATE EXTENSION IF NOT EXISTS vector;"
cat /path/to/metis_backup.dump | docker compose exec -T postgres pg_restore -U postgres -d metis
4. Restore FalkorDB
cd /opt/bk-lite
docker compose stop falkordb
docker compose cp /path/to/dump_backup.rdb falkordb:/var/lib/falkordb/data/dump.rdb
docker compose start falkordb
5. Restore VictoriaLogs (Optional)
cd /opt/bk-lite
docker compose stop victoria-logs
# Get volume name
VOLUME_NAME=$(docker volume ls --filter name=victoria-logs -q | head -1)
# Restore snapshot
docker run --rm -v ${VOLUME_NAME}:/vlogs -v /path/to/backup:/backup alpine \
sh -c "rm -rf /vlogs/* && cp -r /backup/snapshot_YYYYMMDD/* /vlogs/"
docker compose start victoria-logs
6. Start Services
cd /opt/bk-lite
docker compose start server web
# Check service status
docker compose ps
7. Verify Recovery
- Log in to the Web interface to verify user data
- Check CMDB asset data
- Verify knowledge base search functionality
- Confirm monitoring alerts are working properly
FAQ
Q: What if backup files are too large?
A: You can use compression and splitting:
# Compress backup
gzip /data/backup/bklite/postgres/bklite_20240101.sql
# Split and compress (1GB per volume)
split -b 1G /data/backup/bklite/postgres/bklite.dump bklite.dump.part_
Q: How to verify backup file integrity?
A: Use checksum verification:
# Generate checksum
sha256sum /data/backup/bklite/postgres/bklite_20240101.dump > /data/backup/bklite/postgres/bklite_20240101.dump.sha256
# Verify checksum
sha256sum -c /data/backup/bklite/postgres/bklite_20240101.dump.sha256
Q: Can backups be performed online?
A: PostgreSQL, FalkorDB, and VictoriaLogs all support online backups without stopping services. However, for data consistency, it is recommended to perform backups during off-peak hours.
Q: How to back up to remote storage?
A: You can use rsync or rclone:
# Sync to remote server using rsync
rsync -avz /data/backup/bklite/ user@backup-server:/backup/bklite/
# Sync to S3 using rclone
rclone sync /data/backup/bklite/ s3:my-bucket/bklite-backup/
Next Steps
- Component Overview - Learn more about each component