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:

PathContents
application/app/etc/env.phpDatabase credentials, Redis config
application/app/etc/config.phpModule configuration
application/pub/media/catalog/Product images
application/var/log/Application logs
backups/mysql/Scheduled daily MariaDB SQL dumps
docker-compose.ymlContainer 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

PolicyValue
Keep every snapshot from the last14 days
Keep monthly snapshots12 (one per month)
Keep yearly snapshots1

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 list

This 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.php

Restore 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 dump

For 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 magento

sudo 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 restorePath argument
Magento env.phpapplication/app/etc/env.php
All MySQL dumpsbackups/mysql/
Product imagesapplication/pub/media/catalog/product/
Application logsapplication/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.log

A 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.

On this page