Backup and Restore
Self-hosted Scheduler0 can snapshot its embedded SQLite database while the cluster is running, upload the snapshot to S3, and later restore from a snapshot. Both operations are asynchronous: the request returns 202 with a requestId, and you follow progress with GET /async-tasks/{requestId}.
Both endpoints require either a credential with the admin scope or Basic Auth with the operator username/password plus X-Peer: cmd.
Endpoints
| Method | Path | Body | Response |
|---|---|---|---|
POST | /cluster/backup | — | 202 {"status": "backup initiated", "requestId": "..."} |
POST | /cluster/restore | {"filePath": "..."} | 202 {"status": "restore initiated", "requestId": "..."} |
Backup
curl -X POST "https://node1.example.com/api/v1/cluster/backup" \
-u "$SCHEDULER0_USER:$SCHEDULER0_PASSWORD" -H "X-Peer: cmd"
What happens on the node that receives the request:
- The database is copied with SQLite's online backup API to
<db-dir>/backups/<db-name>-YYYYMMDD-HHMMSS.db(for examplesqlite_data/backups/db-20260113-143015.db). The connection lock is held for the duration, so writes pause briefly; reads and the API stay available. - The file is uploaded to the bucket configured by
S3Bucket/SCHEDULER0_S3_BUCKET(inAWSRegion), under the key<nodeId>-<ksuid>-<file-name>. - The async task is marked successful with the local path and S3 key in its
output.
An S3 bucket is required for the task to complete: if S3Bucket is empty, the local file is still written but the upload step fails and the async task ends in state 3 (failed) with S3Bucket is not defined.
Poll the task. Backup and restore tasks are recorded under account 1, and GET /async-tasks/{id} needs API-key authentication, so use a credential belonging to account 1:
curl "https://node1.example.com/api/v1/async-tasks/<requestId>" \
-H "X-API-Key: ACCOUNT_1_API_KEY" -H "X-Secret-Key: ACCOUNT_1_SECRET_KEY" -H "X-Account-ID: 1"
# → data.state 2 = success; data.output = "Backup completed, path: ..., s3Key: ..."
Restore
curl -X POST "https://node1.example.com/api/v1/cluster/restore" \
-u "$SCHEDULER0_USER:$SCHEDULER0_PASSWORD" -H "X-Peer: cmd" \
-H "Content-Type: application/json" \
-d '{"filePath": "1-2ZxYw...-db-20260113-143015.db"}'
filePath is required. When S3Bucket is configured it is the S3 object key and the file is downloaded to a temporary location first; otherwise it is a local path on the node.
Before overwriting, the node copies the current database to <db-file>.pre-restore-backup. It then closes the live connection, replaces every table from the backup, and reopens the database. The async task records progress (Restore started, Downloading backup from S3) and the final result.
CLI
scheduler0 backup start
scheduler0 backup restore <file-name-or-s3-key>
scheduler0 async-tasks get <request-id>
Notes
- The operations run on the node that receives the request; there is no leader check on these endpoints, so send them to the node whose database you intend to snapshot or replace.
- Restore replaces the receiving node's local database. In a multi-node cluster, Raft state on other nodes is not rewritten by this call; treat restore as a recovery step to be combined with cluster recovery rather than a routine operation.
- Restoring an in-memory (test) database is rejected.
Related
- Cluster Management
- Jobs → Check the result — async task states