Skip to content

Commit 82a67fb

Browse files
committed
now uses kopia sync-to for remote repo copies (instead of rclone directly).
1 parent efffcb9 commit 82a67fb

File tree

10 files changed

+558
-368
lines changed

10 files changed

+558
-368
lines changed

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
.env
33
.env.local
44

5-
# User config that might store with passwords
6-
kopia-configs.yaml
5+
# User config that might contain passwords
6+
kopia-helpers.yaml
77

88
# Python
99
__pycache__/

README.md

Lines changed: 126 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,21 @@ If you only have one backup destination, just use Kopia directly. If you follow
3030
## Setup
3131

3232
1. Install [Kopia](https://kopia.io/docs/installation/)
33-
2. Copy `kopia-configs.template.yaml` to `kopia-configs.yaml`
34-
3. Edit `kopia-configs.yaml` with your repository paths and sources
33+
2. Copy `kopia-helpers.template.yaml` to `kopia-helpers.yaml`
34+
3. Edit `kopia-helpers.yaml` with your repository paths and sources
3535
4. Set your password (see below)
3636
5. Run `python kopia-start-backups.py` as Administrator
3737
6. Run `python kopia-health-check.py --register` to enable backup monitoring
3838

39-
Your `kopia-configs.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.
39+
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.
4040

4141
## Password Configuration
4242

4343
Passwords can be set in multiple ways (checked in this order):
4444

4545
### Option 1: In config file (simplest)
4646
```yaml
47-
# kopia-configs.yaml
47+
# kopia-helpers.yaml
4848
repositories:
4949
- name: my-backup
5050
password: your-password-here
@@ -65,7 +65,7 @@ set KOPIA_PASSWORD=your-password
6565
# .env.local
6666
KOPIA_PASSWORD_MY_BACKUP1=your-password
6767
```
68-
**Note:** The variable name is based on the repository `name` in your `kopia-configs.yaml`, converted to uppercase with dashes replaced by underscores.
68+
**Note:** The variable name is based on the repository `name` in your `kopia-helpers.yaml`, converted to uppercase with dashes replaced by underscores.
6969
Example: `name: my-backup1``KOPIA_PASSWORD_MY_BACKUP1`
7070

7171
## Scheduled Backups
@@ -75,7 +75,7 @@ Run as Administrator to auto-register with Windows Task Scheduler:
7575
python kopia-start-backups.py
7676
```
7777

78-
This creates a task that runs every 15 minutes (configurable in kopia-configs.yaml).
78+
This creates a task that runs every 15 minutes (configurable in kopia-helpers.yaml).
7979

8080
## Health Check
8181

@@ -84,58 +84,141 @@ Register the health check to alert if backups stop:
8484
python kopia-health-check.py --register
8585
```
8686

87-
This checks every 3 hours and shows a toast notification if no backups for 7 days (configurable in kopia-configs.yaml).
87+
This checks every 3 hours and shows a toast notification if no backups for 7 days (configurable in kopia-helpers.yaml).
8888

89-
## Cloud Backup (OneDrive, Google Drive, etc.)
89+
## Syncing to Cloud / Remote Storage
9090

91-
For cloud destinations, these scripts use [rclone](https://rclone.org/) to sync your local Kopia repository to the cloud. This is more reliable than the OneDrive desktop client for automated backups (which warns about bulk deletes, has character encoding issues, etc.).
91+
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.
9292

9393
### How it works
9494

95-
1. Kopia writes snapshots to a local directory repo as per normal
96-
2. After backup completes, rclone syncs the kopia repo to your cloud destination
97-
3. The cloud provider's desktop client can sync back for fast local restores
95+
1. Kopia writes snapshots to a local directory repository
96+
2. After backup completes, `kopia repository sync-to` syncs to each configured destination
97+
3. Each destination can have its own sync interval
9898

99-
### Setup
99+
### Supported backends
100+
101+
| Backend | Description | Setup Required |
102+
|---------|-------------|----------------|
103+
| `rclone` | OneDrive, Dropbox, and [50+ providers](https://rclone.org/overview/) | [rclone](https://rclone.org/downloads/) installed + configured |
104+
| `s3` | Amazon S3 and S3-compatible storage | Access keys |
105+
| `gcs` | Google Cloud Storage | GCP credentials |
106+
| `azure` | Azure Blob Storage | Storage account + key |
107+
| `b2` | Backblaze B2 | Application key |
108+
| `gdrive` | Google Drive (native) | OAuth credentials |
109+
| `filesystem` | Local/network paths | None |
110+
| `sftp` | SSH/SFTP servers | SSH access |
111+
| `webdav` | WebDAV servers | URL + credentials |
112+
113+
### Configuration
114+
115+
Add a `sync-to` list to your repository in `kopia-helpers.yaml`:
116+
117+
```yaml
118+
repositories:
119+
- name: my-backup
120+
repo_destination: C:/kopia-cache/mysrc
121+
repo_config: C:/kopia-cache/mysrc/repository.config
122+
repo_password: your-password
123+
124+
sources:
125+
- C:/Users/username/Documents
126+
127+
policies:
128+
# ... retention policies ...
129+
130+
# Sync to one or more destinations
131+
sync-to:
132+
# OneDrive via rclone
133+
- type: rclone
134+
remote-path: onedrive:mybackups/kopia
135+
interval: 60m
136+
137+
# Local NAS
138+
- type: filesystem
139+
path: //nas/backups/kopia
140+
interval: 30m
141+
```
142+
143+
### Default flags
144+
145+
These flags are always applied (you can override via `extra-args`):
146+
- `--delete` - Mirror behavior (remove files not in source)
147+
- `--flat` - Flat directory structure for cloud backends
148+
149+
### Using rclone backend (OneDrive, Dropbox, etc.)
100150

101151
1. Install rclone: https://rclone.org/downloads/
102-
2. Configure your cloud remote:
152+
2. Configure your remote:
103153
```bash
104154
rclone config
105-
# Choose 'n' for new remote
106-
# Name it: onedrive (or gdrive, dropbox, etc.)
107-
# Follow the browser auth flow
108-
```
109-
3. Test connectivity:
110-
```bash
111-
rclone lsd onedrive:
155+
# Choose 'n' for new remote, name it 'onedrive', follow auth flow
112156
```
113-
4. Add a cloud repository to `kopia-configs.yaml`:
157+
3. Test: `rclone lsd onedrive:`
158+
4. Add to config:
114159
```yaml
115-
repositories:
116-
- name: cloud-backup
117-
local_destination_repo: C:/kopia-cache/mysrc # Where Kopia writes locally
118-
remote_destination_repo: onedrive:mybackups/kopia # rclone sync destination
119-
local_config_file_path: C:/kopia-cache/mysrc/repository.config
120-
password: your-password
121-
sources:
122-
- C:/Users/username/Documents
123-
- ...
124-
policies:
125-
# ... same as local repos
160+
sync-to:
161+
- type: rclone
162+
remote-path: onedrive:mybackups/kopia
163+
interval: 60m
126164
```
127165

128-
Kopia writes to `local_destination_repo`, then rclone syncs to `remote_destination_repo` (e.g., `onedrive:`, `gdrive:`, `dropbox:`).
166+
### Using S3 backend
129167

130-
### Supported cloud providers
168+
```yaml
169+
sync-to:
170+
- type: s3
171+
bucket: my-backup-bucket
172+
interval: 120m
173+
extra-args: ["--access-key=AKIAXXXXXXXX", "--secret-access-key=xxx"]
174+
```
175+
176+
### YAML parameters vs extra-args
177+
178+
Each backend has a few **required YAML fields** (the destination identifier). Everything else goes in `extra-args`:
179+
180+
| Backend | Required YAML fields | Example extra-args |
181+
|---------|---------------------|-------------------|
182+
| `rclone` | `remote-path` | `--rclone-args=...` |
183+
| `s3` | `bucket` | `--access-key=...`, `--region=...` |
184+
| `gcs` | `bucket` | `--credentials-file=...` |
185+
| `azure` | `container`, `storage-account` | `--storage-key=...` |
186+
| `b2` | `bucket` | `--key-id=...`, `--key=...` |
187+
| `gdrive` | `folder-id` | `--credentials-file=...` |
188+
| `filesystem` | `path` | |
189+
| `sftp` | `path`, `host`, `username` | `--keyfile=...`, `--password=...` |
190+
| `webdav` | `url` | `--username=...`, `--password=...` |
191+
192+
**Common fields for all backends:**
193+
- `interval` - how often to sync (e.g., `60m`, `2h`)
194+
- `extra-args` - list of additional kopia flags
131195

132-
Any [rclone-supported backend](https://rclone.org/overview/) works:
133-
- OneDrive / OneDrive for Business
134-
- Google Drive
135-
- Dropbox
136-
- Amazon S3
137-
- Backblaze B2
138-
- And many more...
196+
### Using extra-args
197+
198+
```yaml
199+
sync-to:
200+
- type: rclone
201+
remote-path: onedrive:mybackups/kopia
202+
interval: 60m
203+
extra-args: ["--no-delete", "--times"]
204+
205+
- type: s3
206+
bucket: my-bucket
207+
interval: 120m
208+
extra-args: ["--access-key=AKIA...", "--secret-access-key=...", "--region=us-west-2"]
209+
210+
- type: sftp
211+
path: /backups/kopia
212+
host: backup.example.com
213+
username: backupuser
214+
interval: 30m
215+
extra-args: ["--keyfile=/path/to/key"]
216+
```
217+
218+
To see all available options for a backend:
219+
```bash
220+
kopia repository sync-to <type> --help
221+
```
139222

140223
## Finding Files
141224

@@ -174,7 +257,7 @@ All scripts support:
174257
- Python 3.8+
175258
- PyYAML: `pip install pyyaml`
176259
- python-dotenv (optional): `pip install python-dotenv`
177-
- rclone (optional, for cloud backup): https://rclone.org/downloads/
260+
- rclone (for OneDrive/Dropbox/etc sync): https://rclone.org/downloads/
178261

179262
## License
180263

kopia-find-files.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
python kopia-find-files.py --mount Z: --repo myrepo # Mount for browsing
3131
3232
Requires:
33-
- kopia-configs.yaml with repository definitions
33+
- kopia-helpers.yaml with repository definitions
3434
- Password configured via yaml, environment variable, or .env file
3535
- kopia CLI installed and in PATH
3636
- WinFsp for mount functionality (Windows)
@@ -100,7 +100,7 @@ def parse_ls_line(line: str) -> Optional[Tuple[int, str, str]]:
100100
def find_in_repo(runner: utils.KopiaRunner, repo_config: Dict[str, Any], filename_pattern: str, max_snapshots: Optional[int] = None, match_path: bool = False, verbose: bool = False) -> List[Dict[str, Any]]:
101101
"""Search for files using kopia ls -l -r (gets file details directly, no mounting)."""
102102
name = repo_config['name']
103-
config_file = repo_config['local_config_file_path']
103+
config_file = repo_config['repo_config']
104104

105105
print(f" Searching in {name}...")
106106

@@ -193,7 +193,7 @@ def find_in_repo(runner: utils.KopiaRunner, repo_config: Dict[str, Any], filenam
193193

194194
def mount_repository(runner: utils.KopiaRunner, repo_config: Dict[str, Any], drive_letter: str, verbose: bool = False):
195195
name = repo_config['name']
196-
config_file = repo_config['local_config_file_path']
196+
config_file = repo_config['repo_config']
197197

198198
print(f"\nPreparing to mount '{name}' to {drive_letter}...")
199199

@@ -278,7 +278,7 @@ def find_free_drive_letter() -> Optional[str]:
278278
def list_repositories(config: Dict[str, Any]) -> List[Dict[str, Any]]:
279279
print("\nAvailable Repositories:")
280280
for i, repo in enumerate(config['repositories']):
281-
print(f"[{i}] {repo['name']} ({repo['local_destination_repo']})")
281+
print(f"[{i}] {repo['name']} ({repo['repo_destination']})")
282282
return config['repositories']
283283

284284

0 commit comments

Comments
 (0)