Skip to content

Backup and restore

Two things make up the entire Asclepius state:

  1. vault/ directory, all documents, organized files, imaging studies, and the SQLite database
  2. config/settings.yaml, your configuration file

Back up both regularly.

Download a SQLite backup directly from the web UI:

  1. Go to Settings → Backup
  2. Click Download Backup
  3. A timestamped .sqlite file is downloaded (e.g., asclepius_backup_20250115_143022.sqlite)

This uses SQLite’s online backup API, which creates a consistent snapshot even while the application is running. The backup includes all structured data (documents, patients, lab results, etc.) but not the actual document files on disk.

Asclepius can run one configurable backup job on a schedule, write the file to a directory you choose, and prune old files automatically. No cron required.

Configure it under Settings → Backup → Scheduled backups:

SettingValuesNotes
Enabledon / offMaster switch
DirectorypathDefaults to /vault/backups (kept inside the volume so a host-level vault backup picks it up)
Include databaseyes / noAdds the SQLite snapshot to the run
Include vaultyes / noAdds the document files; gzipped tarball
Schedulehourly / daily / weeklyRuns once per interval since the last successful backup
Retentionkeep last N / keep newer than N daysOne policy at a time, applied after every successful run

The scheduler picks the artifact format from your scope flags:

  • database onlyasclepius_db_YYYYMMDD_HHMMSS.sqlite (SQLite online backup; safe while the app runs)
  • vault onlyasclepius_vault_YYYYMMDD_HHMMSS.tar.gz
  • database + vaultasclepius_full_YYYYMMDD_HHMMSS.tar.gz (a snapshot of the SQLite file is taken first, then added to the tarball alongside the vault tree)

The vault archive walks vault/ and skips three things automatically: the backup directory itself (no recursion), the live asclepius.sqlite file, and the WAL/SHM/journal sidecars. Inside a *_full_* archive the consistent SQLite snapshot is written as asclepius.sqlite at the root, with the vault tree under vault/.

The same Settings page lets you:

  • Run now, triggers the configured job immediately, no waiting for the next tick
  • List existing backups, newest first, with size and timestamp
  • Download any backup file
  • Delete any backup file (admin only, emits a backup.delete audit-log entry)

You can also drive the same actions via the API:

POST /api/settings/backup/run # admin · runs the configured job
GET /api/settings/backup/files # list, newest first
GET /api/settings/backup/files/{name} # download
DELETE /api/settings/backup/files/{name} # admin · delete one file

Retention runs after every successful backup. Two modes:

  • count (default 7), keep the N most recent files across all kinds, delete the rest
  • days (e.g. 30), keep everything newer than N days, delete the rest

Both modes operate across the whole backup directory, so mixing scopes (e.g. switching from db to full) still results in a clean directory. Pruning a file logs a single Pruned backup ... line.

If you prefer editing settings.yaml directly:

backup:
directory: /vault/backups
enabled: true
include_database: true
include_vault: true
schedule: daily # hourly | daily | weekly
retention_mode: count # count | days
retention_value: 7

Settings are live, changes are written back to YAML and the in-memory scheduler is cancelled and restarted with the new config. No container restart needed.

For a complete backup, copy the entire vault/ directory and config/settings.yaml:

Terminal window
# Stop the container for a consistent backup
docker compose stop
# Copy the vault and config
cp -r vault/ /backup/asclepius/vault/
cp config/settings.yaml /backup/asclepius/settings.yaml
# Restart
docker compose up -d

SQLite with WAL mode supports live backups. You can copy the database while the application is running:

Terminal window
# Use sqlite3 backup command for a consistent copy
sqlite3 vault/asclepius.sqlite ".backup /backup/asclepius.sqlite"
# Copy document files (rsync for incremental)
rsync -av vault/patients/ /backup/patients/
rsync -av vault/unclassified/ /backup/unclassified/
  1. Stop the application: docker compose stop
  2. Replace the database file: cp backup.sqlite vault/asclepius.sqlite
  3. Start the application: docker compose up -d
  1. Stop the application: docker compose stop
  2. Restore the vault: cp -r /backup/asclepius/vault/ vault/
  3. Restore the config: cp /backup/asclepius/settings.yaml config/settings.yaml
  4. Start the application: docker compose up -d

Set up a cron job for automated backups:

Terminal window
# Daily backup at 2 AM
0 2 * * * sqlite3 /path/to/vault/asclepius.sqlite ".backup /backup/asclepius_$(date +\%Y\%m\%d).sqlite" && rsync -av /path/to/vault/patients/ /backup/patients/

To move Asclepius to a new server:

  1. Create a full backup on the old server
  2. Install Asclepius on the new server
  3. Copy the vault/ directory and config/settings.yaml to the new server
  4. Start the application