Leaving Airtable? Bring your bases to Artavolo, checked record by record. See how

Backups and restore

Every Artavolo instance can produce one encrypted archive that holds everything needed to rebuild it: the application database, the data database (one table per sheet) and the uploaded files. The Enterprise edition runs this on a schedule and can copy the archive to an S3-compatible bucket.

The encryption key

Set BACKUP_ENCRYPTION_KEY before the first backup:

  • Docker: ARTAVOLO_BACKUP_ENCRYPTION_KEY in .env (openssl rand -hex 32), then docker compose up -d.
  • LAMP: define('BACKUP_ENCRYPTION_KEY', '...'); in includes/config.php.

Store a copy of the key outside the server (password manager, printed in a safe). An archive cannot be opened without it, and there is no recovery path. Rotating the key only affects new archives; keep old keys as long as you keep old archives.

Archives are artavolo-backup-YYYYMMDD-HHMMSS.abk: AES-256-CTR with a random IV, authenticated with HMAC-SHA256 over the whole file. The integrity tag is checked before anything is decrypted, so a wrong key or a damaged file is refused up front.

Running a backup

From the shell (any edition):

# Docker
docker compose exec -u www-data app php utilities/backup.php
# LAMP
php utilities/backup.php

Options: --no-uploads (databases only), --path=/mnt/backups, --keep=30 (retention in days), --no-s3, --plain (unencrypted zip, only for moving data by hand). The archive lands in data/backups/ (Docker: the app_backups volume) unless a path is configured.

From the administration (Enterprise): Settings → Backups → "Run a backup now". The same page configures the daily schedule (hour, server time), the local folder, retention, whether uploads are included, and the S3-compatible target. The cron job that ships with the instance starts the run within five minutes of the chosen hour. A failed run e-mails all administrators; every run appears in the audit log as backup.run or backup.failed.

Copy archives off the host. With Docker: docker compose cp app:/var/www/html/data/backups ./backups. With an S3 target the copy happens automatically after each run; retention applies there too.

Checking an archive

php utilities/restore.php artavolo-backup-20260911-030001.abk --dry-run

This verifies the tag, decrypts to a temporary folder, prints the manifest (version, instance, creation time) and the size of each part, and removes the temporary files. Do this monthly, and once on a scratch machine to prove the full restore below works.

Restoring

Restoring replaces the two databases named in includes/config.php and copies the uploads over the current ones. Stop the web server (or scale the app container down) first.

# Docker: a fresh stack with the same .env (same ARTAVOLO_BACKUP_ENCRYPTION_KEY)
docker compose up -d db
docker compose run --rm -u www-data app php utilities/restore.php /var/www/html/data/backups/artavolo-backup-20260911-030001.abk --yes
docker compose up -d

# LAMP
php utilities/restore.php /path/to/artavolo-backup-20260911-030001.abk --yes
php utilities/clear-cache.php

--no-uploads restores only the databases, --no-database only the uploads, --extract=/tmp/out unpacks without touching the instance, --key=... supplies the key when config.php does not exist yet. The restore records backup.restored in the audit log.

Restoring into an instance that runs a newer application version is supported: run php utilities/migrate.php afterwards so the schema catches up.

What is not in the archive

includes/config.php (contains database credentials and secrets; keep it with the key), the language packs under lang/ if you edited them, and the licence key (also in the database, so it is restored with it).

A question these pages do not answer? Write to us and we answer by e-mail, usually within one business day. Contact us