<div class="docs-content" data-render>
# Backups
> Audience: administrators. This page is hidden from members and guests in the sidebar, the search
> index, and the documentation export. It describes the backup service, where archives live, and how
> to schedule and rotate them.
DevPlace ships an enterprise-grade backup service that captures point-in-time copies of platform
data as compressed `tar.gz` archives. Every backup runs as an asynchronous job in a subprocess off
the request path, so creating a backup never blocks the server or slows requests.
## Targets
A backup captures one of four targets:
- **Database** - a consistent SQLite snapshot of the main database plus the Devii task and lesson
databases. The snapshot uses SQLite's online backup API, so it is consistent even while the server
is writing under WAL.
- **Uploads** - every attachment and project file under the uploads directory. This is normally the
largest target.
- **Keys and config** - the VAPID notification keys and other small config artifacts.
- **Full data directory** - the database snapshot, uploads, and keys in one archive. Regenerable and
volatile data (job staging, locks, zip archives, container workspaces, search caches) is excluded
because it can be rebuilt and would only bloat the archive.
## Where backups live
Archives are written under the runtime data directory at `data/backups/`, sharded into a two-level
`xx/yy` tree taken from the random tail of each backup's identifier so no single directory grows
without bound. Each archive is named `target-YYYYMMDD-HHMMSS-id.tar.gz` and recorded with its size,
file count, and a SHA-256 checksum for integrity verification. Staging happens under
`data/backup_staging/` and is removed as soon as the archive is built.
Because everything lives under the single data directory, pointing `DEVPLACE_DATA_DIR` at a mounted
volume in production places backups on that volume automatically.
## Creating a backup
Open **Admin -> Backups**, choose a target, and select **Create backup**. The dashboard shows the
job moving from pending to running to done; when it completes a download link appears. Backups can
also be created from the command line with `devplace backups run <target>` (the running server
processes the enqueued job), or by asking Devii to back up a target.
**Downloading is restricted to the primary administrator** - the earliest-created Admin, resolved by
`database.get_primary_admin_uid` / `utils.is_primary_admin`. `GET /admin/backups/{uid}/download`
returns `403` for every other administrator, and the `download_url` is withheld from them at every
endpoint (their Download control renders disabled). Any admin may still create, schedule, and delete
backups.
## Scheduling and rotation
A backup schedule fires backups automatically. Each schedule has:
- a **target** (database, uploads, keys, or full),
- a **trigger** - either an interval in seconds or a 5-field cron expression
(`minute hour dom month dow`),
- a **keep_last** retention count - after each scheduled backup completes, older backups created by
the same schedule beyond this count are deleted to reclaim space (0 keeps them all).
Schedules are evaluated by the backup service, which runs only on the worker holding the service
lock, so each scheduled backup fires exactly once. Create, edit, enable, disable, run, and delete
schedules from the dashboard.
## Storage visibility
The dashboard reports the size and file count of every major data area (database, uploads,
attachments, project files, keys, zip archives, search data, container workspaces, and the backups
themselves), the total data-directory footprint, the total size and count of stored backups, and the
underlying disk usage (total, used, free, and percent). The scan runs in a worker thread and is
cached briefly so it never blocks page rendering.
## Retention and deletion
Backup archives are permanent operational artifacts: unlike the async job rows that track them, an
archive is never swept away by job retention. It is removed only when an administrator deletes it,
when a schedule rotates it out via keep_last, or by the `devplace backups clear` command. Deleting a
backup is a hard delete that unlinks the archive file and reclaims its disk space immediately, and is
recorded in the audit log.
## Restore
This service creates and stores backups; it does not restore them into a live server, because
overwriting the database or uploads while the application is running risks corruption. To restore,
stop the server, unpack the relevant archive over the data directory (each archive is rooted at
`database/`, `uploads/`, or `keys/`), verify the SHA-256 checksum recorded for the backup, and start
the server again.
## Command line
- `devplace backups list` - list recorded backups with target, status, size, and filename.
- `devplace backups run <database|uploads|keys|full>` - enqueue a backup for the running server.
- `devplace backups prune` - remove backup records whose archive file is missing.
- `devplace backups clear` - delete every backup archive and record.
</div>