Backups
Composia automates backups through Rustic. Backup and restore tasks run on the agent, while the controller generates runtime configuration.
Architecture
Backups require a Rustic infrastructure service. The repository must declare exactly one service with infra.rustic:
name: rustic
nodes:
- main
infra:
rustic:
compose_service: rustic
profile: default
data_protect_dir: /data-protectThe Rustic compose service is a normal Docker container running the rustic binary. It must have a volume that maps the agent’s {StateDir}/data-protect to the path set in data_protect_dir.
Controller configuration
controller:
backup:
default_schedule: "0 2 * * *"
rustic:
main_nodes:
- "main"
maintenance:
forget_schedule: "0 1 * * Sun"
prune_schedule: "0 3 * * Sun"| Key | Description |
|---|---|
backup.default_schedule | Default cron schedule for service backups. |
rustic.main_nodes | Node IDs where Rustic operations run. Each must reference a configured node. |
rustic.maintenance.forget_schedule | Cron schedule for rustic forget. |
rustic.maintenance.prune_schedule | Cron schedule for rustic prune. |
Service data protection
Define what to back up in composia-meta.yaml under data_protect:
data_protect:
data:
- name: db
backup:
strategy: database.pgdumpall
service: postgres
restore:
strategy: database.pgimport
service: postgres
- name: uploads
backup:
strategy: files.copy_after_stop
include:
- ./uploads
restore:
strategy: files.copy
include:
- ./uploadsData strategies
| Strategy | Purpose |
|---|---|
files.copy | Bind-mount source paths into the Rustic container for read-only backup. Use for live-readable data. |
files.copy_after_stop | Stop the compose project, bind-mount source paths, back up, then restart. Use for data that must be quiesced. |
database.pgdumpall | Run pg_dumpall inside the compose service. Requires service to be set. |
database.pgimport | Restore a PostgreSQL dump via psql. Requires service to be set. |
Data action fields
| Key | Type | Required for | Description |
|---|---|---|---|
strategy | string | All | Backup or restore strategy. |
service | string | database.* | Compose service name. |
include | []string | files.* | Paths to include. Service paths (relative to service root, starts with ./ or contains /) or Docker volume names (bare name, no path separators). |
Include path types
Paths can reference:
- Service paths: files or directories inside the service directory. Bind-mounted read-only into the Rustic container via
-v. - Named volumes: Docker volume names. Bind-mounted read-only into the Rustic container via
-v(no temporary container needed).
Backup schedules
Enable scheduled backups for protected data items:
backup:
data:
- name: db
provider: rustic
enabled: true
schedule: "0 2 * * *"
- name: uploads
enabled: true
schedule: "0 3 * * Sun"| Key | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Must reference a data_protect.data[].name that has a backup action. |
provider | string | No | Backup provider name. |
enabled | bool | No | Enable or disable this backup. |
schedule | string | No | Cron expression. "none" disables scheduling while keeping the entry. |
When schedule is set, the controller schedules recurring backup tasks. The controller’s backup.default_schedule is used as a fallback if a service entry does not specify its own schedule.
How backup runs
A backup task executes these steps on the agent:
- Render: download the service bundle and the Rustic bundle from the controller. Read
.composia-backup.jsongenerated by the controller. - Backup: for each data item in the runtime config:
files.*: create an empty staging directory underdata-protect, add-vbind mounts for each include path or volume, then rundocker compose run -v ... rustic backupwith tags identifying the service and data item. No data is copied into the agent state directory.database.pgdumpall: rundocker compose exec <service> pg_dumpall, write the SQL dump to a staging file underdata-protect, then rundocker compose run rustic backupon the staging directory.- Report the result (snapshot ID) to the controller.
- The task finishes when all items are backed up.
Backup artifacts are identified by Rustic snapshot IDs. Tags include composia-service:<name> and composia-data:<name> for later restore and forget operations.
Restore
Trigger a restore through the web UI from the backups page or via CLI:
composia backup restore --wait --follow --timeout 30m main <backup-id>The first argument is the target node. Use --wait --follow to block until the restore finishes and stream task logs.
The restore process:
- Render: download the service bundle and Rustic bundle. Read
.composia-restore.json. - Restore: for each item:
files.copy/files.copy_after_stop: clean the restore targets (must exist), create an empty staging directory underdata-protect, bind-mount each target path or Docker volume into the staging tree, then rundocker compose run -v ... rustic restore <snapshot_id> <staging_dir>. Restored data is written directly to the target locations — no post-restore copy step.files.copy_after_stop: additionally stops the compose project before restore and restarts it after.database.pgimport: rundocker compose run rustic restore <snapshot_id>into a staging directory, then rundocker compose exec <service> psqlwith the restored SQL dump.
Restore targets for files.* service paths must already exist on the agent (the target file or directory is used to determine the bind-mount semantics). Docker volume targets are cleared before restore.
Rustic maintenance
Maintenance tasks use the Rustic infrastructure service:
rustic_init: runsdocker compose run rustic initto initialize the Rustic repository. Use once per Rustic setup.rustic_forget: runsdocker compose run rustic forgetwith tag filters. Scoped to a service, data item, or repo-wide.rustic_prune: runsdocker compose run rustic pruneto remove unreferenced data.
Trigger maintenance from the web UI or CLI:
composia rustic init --wait --follow main
composia rustic forget --service my-app --data uploads --yes --wait --follow main
composia rustic prune --yes --wait --follow mainUse --wait --follow when you want the CLI to wait for the maintenance task and stream logs.
See also
- Service Configuration — data protection and backup scheduling.
- Migrate — move services between nodes with data preserved through backups.