Multi-repository backup automation for Kopia.
Currently Windows only, but could be adapted for Linux/macOS.
Kopia is excellent, but its CLI works with one repository at a time. These scripts solve the "multiple backup destinations" problem:
- One command, all repositories — Back up to local NAS, cloud storage, and external drive simultaneously
- Single YAML config — All your repositories, sources, and policies in one readable, versionable file
- Set-and-forget scheduling — Auto-registers with Windows Task Scheduler
- Health monitoring — Toast notifications if backups haven't run in 7 days
If you only have one backup destination, just use Kopia directly. If you follow the 3-2-1 backup rule (3 copies, 2 media types, 1 offsite), this makes your life easier.
| Script | Description |
|---|---|
kopia-start-backups.py |
Main backup script - creates snapshots, sets policies, schedules in task-scheduler |
kopia-stop-backups.py |
Unregister scheduled tasks (backups and/or health checks) |
kopia-health-check.py |
Alert if no backups in 7 days (toast notification), schedules in task-scheduler |
kopia-find-files.py |
Search for files across all snapshots |
- Install Kopia
- Copy
kopia-helpers.template.yamltokopia-helpers.yaml - Edit
kopia-helpers.yamlwith your repository paths and sources - Set your password (see below)
- Run
python kopia-start-backups.pyas Administrator - Run
python kopia-health-check.py --registerto enable backup monitoring
Your kopia-helpers.yaml is re-read each time the scheduled task runs, so config changes take effect automatically. You can also safely re-run steps 5 and 6 anytime to re-register the tasks (but not required). Uou will receive a Windows Toast Notification if there are backup failures or lack of backup activity.
Passwords can be set in multiple ways (checked in this order):
# kopia-helpers.yaml
repositories:
- name: my-backup
password: your-password-here
...# Repository-specific (recommended)
set KOPIA_PASSWORD_MY_BACKUP1=your-password
# Or global fallback (kopia default)
set KOPIA_PASSWORD=your-password# .env.local
KOPIA_PASSWORD_MY_BACKUP1=your-passwordNote: The variable name is based on the repository name in your kopia-helpers.yaml, converted to uppercase with dashes replaced by underscores.
Example: name: my-backup1 → KOPIA_PASSWORD_MY_BACKUP1
Run as Administrator to auto-register with Windows Task Scheduler:
python kopia-start-backups.py
This creates a task that runs every 15 minutes (configurable in kopia-helpers.yaml).
Register the health check to alert if backups stop:
python kopia-health-check.py --register
This checks every 3 hours and shows a toast notification if no backups for 7 days (configurable in kopia-helpers.yaml).
After Kopia creates local snapshots, you can sync them to cloud storage or other destinations using Kopia's built-in repository sync-to command. This properly handles repository structure (sharding) and supports multiple destinations per repository.
- Kopia writes snapshots to a local directory repository
- After backup completes,
kopia repository sync-tosyncs to each configured destination - Each destination can have its own sync interval
| Backend | Description | Setup Required |
|---|---|---|
rclone |
OneDrive, Dropbox, and 50+ providers | rclone installed + configured |
s3 |
Amazon S3 and S3-compatible storage | Access keys |
gcs |
Google Cloud Storage | GCP credentials |
azure |
Azure Blob Storage | Storage account + key |
b2 |
Backblaze B2 | Application key |
gdrive |
Google Drive (native) | OAuth credentials |
filesystem |
Local/network paths | None |
sftp |
SSH/SFTP servers | SSH access |
webdav |
WebDAV servers | URL + credentials |
Add a sync-to list to your repository in kopia-helpers.yaml:
repositories:
- name: my-backup
repo_destination: C:/kopia-cache/mysrc
repo_config: C:/kopia-cache/mysrc/repository.config
repo_password: your-password
sources:
- C:/Users/username/Documents
policies:
# ... retention policies ...
# Sync to one or more destinations
sync-to:
# OneDrive via rclone
- type: rclone
remote-path: onedrive:mybackups/kopia
interval: 60m
# Local NAS
- type: filesystem
path: //nas/backups/kopia
interval: 30mThese flags are always applied (you can override via extra-args):
--delete- Mirror behavior (remove files not in source)--flat- Flat directory structure for cloud backends
- Install rclone: https://rclone.org/downloads/
- Configure your remote:
rclone config # Choose 'n' for new remote, name it 'onedrive', follow auth flow - Test:
rclone lsd onedrive: - Add to config:
sync-to: - type: rclone remote-path: onedrive:mybackups/kopia interval: 60m
sync-to:
- type: s3
bucket: my-backup-bucket
interval: 120m
extra-args: ["--access-key=AKIAXXXXXXXX", "--secret-access-key=xxx"]Each backend has a few required YAML fields (the destination identifier). Everything else goes in extra-args:
| Backend | Required YAML fields | Example extra-args |
|---|---|---|
rclone |
remote-path |
--rclone-args=... |
s3 |
bucket |
--access-key=..., --region=... |
gcs |
bucket |
--credentials-file=... |
azure |
container, storage-account |
--storage-key=... |
b2 |
bucket |
--key-id=..., --key=... |
gdrive |
folder-id |
--credentials-file=... |
filesystem |
path |
|
sftp |
path, host, username |
--keyfile=..., --password=... |
webdav |
url |
--username=..., --password=... |
Common fields for all backends:
interval- how often to sync (e.g.,60m,2h)extra-args- list of additional kopia flags
sync-to:
- type: rclone
remote-path: onedrive:mybackups/kopia
interval: 60m
extra-args: ["--no-delete", "--times"]
- type: s3
bucket: my-bucket
interval: 120m
extra-args: ["--access-key=AKIA...", "--secret-access-key=...", "--region=us-west-2"]
- type: sftp
path: /backups/kopia
host: backup.example.com
username: backupuser
interval: 30m
extra-args: ["--keyfile=/path/to/key"]To see all available options for a backend:
kopia repository sync-to <type> --helpSearch for files across all snapshots using find -name style patterns:
python kopia-find-files.py "*.py" # Find all .py files (not .pyc)
python kopia-find-files.py "report*.pdf" # Files starting with 'report'
python kopia-find-files.py "config.yaml" # Exact filename match
python kopia-find-files.py "data_202[0-9].csv" # Character range: 2020-2029Pattern syntax (same as find -name):
| Pattern | Matches |
|---|---|
* |
Any characters (zero or more) |
? |
Exactly one character |
[abc] |
One of: a, b, or c |
[a-z] |
One character in range a-z |
Options:
-n 50— Search last 50 snapshots (default: 100)--all— Search all snapshots--path— Match against full path (likefind -path) instead of filename--repo name1,name2— Search specific repositories--mount— Mount repository after search for browsing
All scripts support:
--log-level DEBUG|INFO|WARNING|ERROR(default: WARNING)--dry-run(for backup script)
- Python 3.8+
- PyYAML:
pip install pyyaml - python-dotenv (optional):
pip install python-dotenv - rclone (for OneDrive/Dropbox/etc sync): https://rclone.org/downloads/
MIT License - see LICENSE for details.