Backups
What gets backed up on each environment, the retention schedule, and how to restore files via the Hub or the command line.
Every StoreFrame environment has automated, encrypted, off-site backups. Backups run daily and retain snapshots for up to 12 months. You can restore from the Hub UI or directly over SSH.
How backups work
A daily cron job on each environment backs up the entire project directory. After each backup, old snapshots are pruned according to the retention policy below. Everything is encrypted before leaving the server. Encryption keys are managed by StoreFrame — you do not need to configure or rotate them.
Schedule: Daily
What gets backed up
The backup covers the entire project directory at /var/www/<subdomain>.<domain>/, which includes:
| Path | Contents |
|---|---|
application/app/etc/env.php | Database credentials, Redis config |
application/app/etc/config.php | Module configuration |
application/pub/media/catalog/ | Product images |
application/var/log/ | Application logs |
backups/mysql/ | Scheduled daily MariaDB SQL dumps |
docker-compose.yml | Container composition |
Exclusions
The live MariaDB data files are not included, because copying a running database produces an inconsistent snapshot. Your database is protected by the daily SQL dumps in backups/mysql/, which are part of every backup.
Retention policy
| Policy | Value |
|---|---|
| Keep every snapshot from the last | 14 days |
| Keep monthly snapshots | 12 (one per month) |
| Keep yearly snapshots | 1 |
In practice: you have every daily snapshot from the last 14 days, then one snapshot per month going back a year, plus one yearly snapshot. For most restore scenarios the 14-day window covers you; monthly snapshots provide a longer safety net.
Manual backups you start from the Hub are kept separately: the 10 most recent are retained.
Database backups
MariaDB dumps are handled separately from the file backup. A MySQL backup script runs daily and writes compressed SQL dumps to /var/www/<subdomain>.<domain>/backups/mysql/, named backup_DD-MM-YYYY_HHMM.sql.gz (for example backup_08-01-2026_2211.sql.gz). These dump files are then captured by the next daily backup.
Dump retention: the 7 most recent dumps stay on disk locally; older dumps survive inside backup snapshots per the retention policy above.
To take an extra dump right now, run backup-db on the VM.
Restoring via the Hub
For most restore operations, the Hub backup tab is the fastest path.
Go to your environment's Settings → Backup, select a snapshot, choose what to restore (files, database, or both), and confirm. The Hub puts the store in maintenance mode, runs the restore in the background and reports the result.
The same restore is available over SSH:
sudo backup-restore --scope db --snapshot <snapshot_id> # database only
sudo backup-restore --scope files --snapshot <snapshot_id> # application files only
sudo backup-restore --scope both --snapshot <snapshot_id>Restoring via SSH
For cases where you need more control — restoring to a specific target path, doing a dry run first, or scripting a restore — use the restic-restore helper directly.
List available snapshots
sudo restic-restore listThis shows a human-readable list of snapshots with short IDs (8 characters) and timestamps.
Restore a specific file
sudo restic-restore file application/app/etc/env.php -s <snapshot_id>Paths are relative to the backup root (/var/www/<subdomain>.<domain>/). The restored file lands in a timestamped directory under /var/www/restore/YYYYMMDD-HHMMSS/, which keeps the full original path. Copy it to the production location once you've verified it. Use --target <dir> to restore somewhere else.
# Example: copy restored env.php back into place
cp /var/www/restore/20260109-143022/var/www/<subdomain>.<domain>/application/app/etc/env.php \
/var/www/<subdomain>.<domain>/application/app/etc/env.phpRestore a directory
sudo restic-restore directory application/pub/media/catalog/ -s <snapshot_id>Restore a database from a SQL dump
To restore one of the 7 dumps still on the VM, use restore-db:
restore-db --list # show the dumps on disk
restore-db --latest # restore the newest dump
restore-db backup_08-01-2026_2211.sql.gz # restore a specific dumpFor an older dump, restore it from a snapshot first, then import it:
# 1. Restore the MySQL backups directory from a snapshot
sudo restic-restore directory backups/mysql/ -s <snapshot_id>
# 2. Import the dump you want
gunzip -c /var/www/restore/*/var/www/*/backups/mysql/backup_08-01-2026_2211.sql.gz \
| mysql magentosudo backup-restore --scope db --snapshot <snapshot_id> does both steps for the newest dump in that snapshot, with maintenance mode on.
Preview a restore without making changes
sudo restic-restore full --dry-run -s <snapshot_id>Full restore
sudo restic-restore full -s <snapshot_id>This restores the entire project directory to the default target path. Use with care — it overwrites what's there.
Common path shortcuts
| What to restore | Path argument |
|---|---|
| Magento env.php | application/app/etc/env.php |
| All MySQL dumps | backups/mysql/ |
| Product images | application/pub/media/catalog/product/ |
| Application logs | application/var/log/ |
Manual backup trigger
To run a backup immediately outside the scheduled window, trigger one from the Hub's Settings → Backup tab, or run sudo backup-now on the VM (add --label "<name>" to name it). A manual backup takes a fresh database dump first.
Backup logs
Backup output is written to /var/log/restic.log. Check it to confirm the last run completed cleanly:
sudo tail -50 /var/log/restic.logA successful run ends with a snapshot <id> saved line followed by a forget prune summary.
Encryption and key management
Backups are encrypted before uploading off-site. Keys are generated during provisioning and managed by StoreFrame — you do not need to configure, rotate, or back them up. If you suspect a backup issue, file a support ticket.
Related
- Settings → Backup — restore snapshots from the Hub UI
- Users and SSH — how to connect to your environment