Persistence & Backup
Every piece of durable collector state lives in SQLite. That covers the onboarded device registry, inventory, alerts, problems, correlation state, and the metric buffers. There is no PostgreSQL and no Keycloak on the collector by design, so persistence is a plain matter of files on disk. This guide covers where those files live, why they sit on a host bind mount, and how to back them up, migrate them, and restore them.
Where the state lives
All services mount one host directory at /data. The host path is AIOPS_DATA_DIR, which defaults to /opt/aiops/data and is set in deploy/docker-compose/.env. Each engine owns its own file, so a store can be inspected or restored in isolation.
| Store | File | Owner service |
|---|---|---|
| Device registry (onboarding) | collector.db | universal-collector |
| Inventory | inventory.db | inventory-engine |
| Alerts | alerts.db | alerting-engine |
| Problems | problems.db | problem-engine |
| Correlation | correlation.db | correlation-engine |
| SNMP buffer | snmp_buffer.db | universal-collector |
| eBPF buffer | ebpf_buffer.db | ebpf-collector |
| Synthetic checks | synthetic.db | synthetic-prober |
| Security posture | security.db | security-posture |
| Business impact | business.db | business-impact |
| SLO | slo.db | slo-engine |
| Capacity | capacity.db | capacity-forecast |
| Auto-discovery | discovery.db | auto-discovery |
| Netshot bridge | netshot.db | netshot-sync |
| SaaS sync cursor | saas_sync.json | saas-sync |
| HA passive inventory | passive/inventory-passive.db | inventory-engine-passive |
Why a bind mount, not a named volume
Onboarded devices used to vanish because the stack kept its state in a Docker named volume, and a named volume is destroyed by docker compose down -v, docker volume prune, and docker system prune --volumes. A host bind mount avoids all of that:
- It survives image rebuilds,
--force-recreate, and everypruneordown -v. - It sits at a known, inspectable path that you can snapshot or copy off-box.
- It turns backups into a plain file operation.
A docker compose up -d --build <svc> never touches this data. Only an explicit removal of the host directory does.
First-time setup and migration
Run this once on the host. If you are moving from the old named volume, migrate the existing data before recreating the stack so nothing is lost.
cd deploy/docker-compose
cp .env.example .env # sets AIOPS_DATA_DIR=/opt/aiops/data
sudo mkdir -p /opt/aiops/data/passive
# Copy any existing data out of the old named volume (skip if starting fresh):
docker run --rm \
-v aiops_sqlite-data:/from -v /opt/aiops/data:/to \
alpine sh -c 'cp -a /from/. /to/ 2>/dev/null || true'
# The old volume may be named "docker-compose_sqlite-data" instead of
# "aiops_sqlite-data" depending on the compose project name. Check with:
# docker volume ls | grep sqlite-data
docker compose up -d # recreates services on the bind mount
Verify the device registry survived the move: open the collector WebUI and confirm your devices are still listed. If you prefer the shell, check that the collector came back up cleanly:
cd /opt/techforcz/collector/deploy/docker-compose
docker compose ps
docker compose logs --tail 20 universal-collector
Backups
scripts/aiops-backup.sh writes a consistent, timestamped .tar.gz of every *.db. It uses the SQLite online .backup when sqlite3 is present, and it keeps the newest RETENTION archives, which defaults to 14.
# manual
AIOPS_DATA_DIR=/opt/aiops/data BACKUP_DIR=/opt/aiops/backups \
./scripts/aiops-backup.sh
# nightly at 02:30 via cron (crontab -e)
30 2 * * * AIOPS_DATA_DIR=/opt/aiops/data BACKUP_DIR=/opt/aiops/backups \
/path/to/repo/scripts/aiops-backup.sh >> /var/log/aiops-backup.log 2>&1
For durability beyond the box itself, point BACKUP_DIR at an NFS mount or sync /opt/aiops/backups to object storage.
Restore
docker compose stop # quiesce writers
./scripts/aiops-restore.sh # newest backup, or pass a specific .tar.gz
docker compose up -d
aiops-restore.sh defaults to the newest backup. Pass a specific .tar.gz path to roll back to an earlier point.
Operational rules
- Never run
docker compose down -von a live appliance. That flag is only for a deliberate wipe. To halt the stack, usedocker compose stopordocker compose downwithout-v. - Rebuild a single service with
docker compose up -d --build <svc>. This leaves the data untouched. - The WebUI Export on the Device Inventory page is a convenient point-in-time export of the device list. Treat it as a complement to the DB backups, not a replacement.
Related
- Data Collector overview for how the appliance fits together.
- Collector Installation for host sizing and first boot.