Automated backup helper for Actual Budget deployments. The service exports native Actual backup archives (.zip) on a schedule, stores them locally (optional), and can replicate the archives to common cloud providers (Google Drive, Amazon S3–compatible storage, Dropbox, WebDAV).
Backups created by this service can be restored directly through the Actual web interface (Settings → Manage Data → Restore) without any conversion.
- Native ZIP exports – Uses
@actual-app/apito generate the same archive produced by Actual's “Download backup” button. - Configurable schedule – Cron expression (default weekly: Mondays at 00:00 UTC) controls when exports run; on-demand runs available via
npm run backup. - Local retention – Keep the most recent N archives plus optional week/month snapshots to manage disk usage.
- Multiple budgets – Provide a comma-separated list of sync targets and the service backs up each one in sequence (archives are named after the budget display name, with the sync ID appended when needed). Targets can include an optional budget identifier in the form
budgetId:syncIdwhen a single sync contains multiple budgets. - Cloud replication – Independently toggle uploads for Google Drive, S3/B2-compatible storage, Dropbox, or WebDAV shares.
- Health monitoring – Structured logging via
pinoand a/bin/healthcheck.shscript compatible with Docker health checks (reports healthy until the first backup completes, then enforces freshness thresholds).
cp env/actual-auto-backup.env.example env/actual-auto-backup.env
cp docker-compose.yml.example docker-compose.ymlIf you want a self-contained deployment with password protection, copy
docker-compose.with-auth.yml.example instead – it bundles Traefik and
actual-auto-auth so the web UI
is fronted by the familiar login screen.
Fill in env/actual-auto-backup.env with your Actual credentials and any cloud
provider settings, then launch via Docker Compose or run locally:
npm install
npm run backup # Run one export immediately
npm start # Start the cron schedulerAll configuration is sourced from env/actual-auto-backup.env when running inside the stack, or from process environment variables directly. Key options:
| Variable | Description | Default |
|---|---|---|
ACTUAL_SERVER_URL |
Base URL of your Actual self-hosted instance | required |
ACTUAL_PASSWORD |
Actual server password | required |
ACTUAL_SYNC_ID |
Primary budget sync ID (used if BACKUP_SYNC_ID unset) |
required |
BACKUP_SYNC_ID |
Comma-separated list of budgets to export. Each entry must be BudgetID:SyncID (as shown in Actual’s Advanced settings); overrides ACTUAL_SYNC_ID |
unset |
ACTUAL_BUDGET_ENCRYPTION_PASSWORD |
Budget encryption password (if enabled) | unset |
BACKUP_CRON |
Cron schedule (UTC) | 0 0 * * 1 |
ENABLE_LOCAL |
Write archives to local disk | true |
LOCAL_RETENTION_COUNT |
Keep the most recent N archives | 4 |
LOCAL_RETENTION_WEEKS |
Keep one archive per week for N weeks | 0 |
ENABLE_GDRIVE, ENABLE_S3, ENABLE_DROPBOX, ENABLE_WEBDAV |
Toggle cloud uploads | false |
See env/actual-auto-backup.env.example for a full list of supported options and comments covering each provider.
npm run lint– ESLint (flat config).npm run format:check– Prettier validation.npm test– Jest test suite (mocks Actual API calls).
The repository ships with GitHub Actions workflows mirroring the existing automation projects: lint/test CI, Docker image builds, release automation, and Dependabot integration.
The service exposes a tiny web UI (default port 4010) for:
- Triggering ad-hoc backups
- Linking / unlinking Google Drive and Dropbox via OAuth
- Viewing the status of each destination
Set BACKUP_PUBLIC_URL to the externally reachable base URL (for OAuth
callbacks) and switch Google Drive to OAuth mode by setting GDRIVE_MODE=oauth
alongside your OAuth Client ID/Secret. For Dropbox, provide
DROPBOX_APP_KEY and DROPBOX_APP_SECRET. Linked tokens are stored under
/app/data/tokens.
When using the bundled Traefik/auth compose file, the login cookie name defaults
to backup-auth – update AUTH_COOKIE_NAME in the compose file (and set the
same value in env/actual-auto-backup.env) if you want to run multiple
services side-by-side.
- Add
BACKUP_SYNC_IDwith a comma-separated list of targets. Each target must be specified asBudgetID:SyncID, matching the labels shown in Actual’s Settings → Advanced → Sync panel. You can copy those values directly from the UI; the Backup overview page also echoes the pairs currently in use. - Archives are named after the budget’s display name. If two targets resolve to the same name the sync ID (or budget ID) is appended to keep filenames unique.
- Enable with
ENABLE_LOCAL=true(default). Archives live under/app/data/backups/<budget-id>/. LOCAL_RETENTION_COUNTkeeps the newest N archives;LOCAL_RETENTION_WEEKSpreserves one archive per ISO week for the last N weeks. Any backup that satisfies either rule is retained while older ones are pruned.
- Service account (default)
- Create a Google Cloud service account and share your Drive folder with it.
- Mount the JSON credentials (
GDRIVE_SERVICE_ACCOUNT_JSON) and setENABLE_GDRIVE=true. - Optional: set
GDRIVE_FOLDER_ID; otherwise a folder named “Actual Budget Backups” is created.
- OAuth (user account)
- In Google Cloud Console, create an OAuth client via APIs & Services → Credentials → Create Credentials → OAuth client ID (configure the consent screen first if prompted, and choose Desktop app or Web application for the type).
- Copy the generated Client ID and Client Secret into
GDRIVE_OAUTH_CLIENT_ID/GDRIVE_OAUTH_CLIENT_SECRET, setGDRIVE_MODE=oauth. - If you create a Web application client, add
<BACKUP_PUBLIC_URL>/oauth/google/callbackas an authorised redirect URI. - Ensure
BACKUP_PUBLIC_URLpoints to your externally reachable base (e.g.https://stack.example.com/backup). - Visit the web UI and click Link under Google Drive to authorize. Tokens persist in
/app/data/tokens/google.json.
- Set
ENABLE_S3=true,S3_BUCKET, and optionallyS3_PREFIX. - Provide credentials via
S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY, or rely on the runtime’s IAM role. - Custom endpoints (MinIO, B2, DigitalOcean) require
S3_ENDPOINT; setS3_FORCE_PATH_STYLE=trueif needed.
- Static token
- Generate a long-lived token in Dropbox App Console.
- Set
DROPBOX_ACCESS_TOKENandENABLE_DROPBOX=true.
- OAuth workflow
- In the Dropbox App Console, create an app (Scoped access) with Full Dropbox or App folder permissions as desired.
- Note the generated App key / App secret and place them in
DROPBOX_APP_KEY/DROPBOX_APP_SECRET; leaveDROPBOX_ACCESS_TOKENunset. - Set the app redirect URI to
<BACKUP_PUBLIC_URL>/oauth/dropbox/callback. - Use the web UI Link button; tokens are stored in
/app/data/tokens/dropbox.json.
- Set
ENABLE_WEBDAV=true, supplyWEBDAV_URL(e.g.https://nextcloud.example.com/remote.php/dav/files/user/),WEBDAV_USERNAME, andWEBDAV_PASSWORD. - Adjust
WEBDAV_BASE_PATH(default/actual-backups) to control the destination folder.
All enabled destinations are attempted in parallel; if any upload fails the backup run is considered unsuccessful (and the health marker is not updated).
MIT