auberge 0.8.5

CLI tool for managing self-hosted infrastructure with Ansible
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# Backup & Restore

## Overview

Auberge provides built-in backup and restore functionality for all self-hosted applications. Backups are stored locally and can be restored to the same host or migrated to a different host using the cross-host restore feature.

## Supported Applications

- **Baikal**: Calendar and contact data, configuration files
- **FreshRSS**: SQLite database, configuration, user data
- **Navidrome**: Database and configuration (music files excluded by default)
- **Calibre**: Book library, metadata database, user database (login credentials)
- **WebDAV**: All shared files

## Backup Storage

Backups are stored locally in `~/.local/share/auberge/backups/` with the following structure:

```
backups/
└── {hostname}/
    ├── baikal/
    │   ├── 2026-01-23_14-30-00/
    │   ├── 2026-01-23_18-45-12/
    │   └── latest -> 2026-01-23_18-45-12
    ├── freshrss/
    ├── navidrome/
    ├── calibre/
    └── webdav/
```

Each app has a `latest` symlink pointing to the most recent backup for easy access.

## Creating Backups

### Backup All Apps

```bash
auberge backup create --host my-vps
```

This creates a timestamped backup of all applications with their data and configuration.

### Backup Specific Apps

```bash
auberge backup create --host my-vps --apps baikal,freshrss
```

### Include Music Files

By default, Navidrome backups exclude the music library (`/srv/music`) to save space and time. To include music files:

```bash
auberge backup create --host my-vps --include-music
```

### Dry Run

Preview what will be backed up without making changes:

```bash
auberge backup create --host my-vps --dry-run
```

### Custom Destination

```bash
auberge backup create --host my-vps --dest /mnt/external/backups
```

## Listing Backups

### List All Backups

```bash
auberge backup list
```

Example output:

```
HOST            APP          TIMESTAMP            SIZE
-----------------------------------------------------------------
my-vps          baikal     2026-01-23_14-30-00  3.24 MB
my-vps          freshrss     2026-01-23_14-30-01  39.57 MB
my-vps          navidrome    2026-01-23_14-30-02  856.06 KB
```

### Filter by Host or App

```bash
auberge backup list --host my-vps
auberge backup list --app baikal
auberge backup list --host my-vps --app freshrss
```

### Output Formats

```bash
auberge backup list --format json
auberge backup list --format yaml
```

## Restoring Backups

### Same-Host Restore

Restore the latest backup to the same host:

```bash
auberge backup restore latest --host my-vps
```

Restore a specific backup by timestamp:

```bash
auberge backup restore 2026-01-23_14-30-00 --host my-vps
```

Restore only specific apps:

```bash
auberge backup restore latest --host my-vps --apps baikal,freshrss
```

Dry run to preview:

```bash
auberge backup restore latest --host my-vps --dry-run
```

### Cross-Host Restore (Migration)

The `--from-host` flag enables restoring backups from one host to a different host. This is useful for:

- **VPS Provider Migration**: Moving from one provider to another (e.g., IONOS → Hetzner)
- **Disaster Recovery**: Restoring to a fresh VPS after hardware failure
- **Dev/Test Environments**: Seeding staging with production-like data

```bash
auberge backup restore latest --from-host old-vps --host new-vps
```

Restore specific apps only:

```bash
auberge backup restore latest --from-host old-vps --host new-vps --apps baikal,freshrss
```

Dry run to preview cross-host restore:

```bash
auberge backup restore latest --from-host old-vps --host new-vps --dry-run
```

## Cross-Host Restore Safety Features

Cross-host restore includes comprehensive safety checks to prevent data loss and ensure successful migration:

### 1. Pre-flight Validation

Before any restore operation, Auberge validates:

- **SSH Connectivity**: Tests connection to target host with 10-second timeout
- **Service Existence**: Verifies all required systemd services are installed on target
- **Disk Space**: Ensures target has sufficient space (requires 120% of backup size)

If any validation fails, the restore is aborted with a clear error message.

### 2. Hostname Confirmation

Cross-host restores require typing the target hostname to confirm:

```
Type the target host name 'new-vps' to confirm: new-vps
```

This prevents accidental cross-host restores that could overwrite the wrong server.

### 3. Emergency Backup

Before overwriting data on the target host, Auberge automatically creates an emergency backup:

```
--- Creating Emergency Backup ---
  Backing up current state of 'new-vps' before cross-host restore
  ✓ Emergency backup created: pre-migration-2026-01-23_15-30-00
    Location: ~/.local/share/auberge/backups/new-vps/{app}/2026-01-23_15-30-00
```

If emergency backup creation fails, you'll be prompted whether to continue without it.

### 4. Escape Hatch with --yes Flag

When using `--yes` to skip confirmation prompts, cross-host restores add a 3-second delay:

```bash
auberge backup restore latest --from-host old-vps --host new-vps --yes
```

```
⚠  Cross-host restore with --yes flag
   Waiting 3 seconds (press Ctrl+C to cancel)...
```

This provides time to abort (Ctrl+C) if the command was run accidentally.

## Post-Restore Actions

After a successful cross-host restore, manual verification and configuration updates are typically required.

### Service Verification

Check that services are running:

```bash
ssh user@new-vps 'systemctl status php*-fpm freshrss navidrome'
```

Check logs for errors:

```bash
ssh user@new-vps 'journalctl -u php*-fpm --since "5 minutes ago" | grep -i error'
```

### Configuration Updates

Re-run Ansible to regenerate host-specific configurations:

```bash
auberge ansible run --host new-vps --tags baikal,freshrss,navidrome
```

### DNS Updates

If the hostname changed, update DNS records to point to the new host:

```bash
auberge dns set-all --host new-vps
```

### SSL Certificates

Verify SSL certificates are valid for the new domain. Caddy will automatically provision new certificates, but verify they're working:

```bash
curl -I https://cal.example.com
```

### App-Specific Notes

**Baikal** (CalDAV/CardDAV):

- Data lives in `/opt/baikal/Specific`; verify admin and DAV users in the Baikal web admin after restore.

**Navidrome** (Music Streaming):

- May need to rescan music library if file paths changed
- Trigger rescan from web UI or restart service

**FreshRSS** (RSS Reader):

- Database paths should work, but verify feeds update correctly
- Check feed refresh status in web UI

## Best Practices

### Regular Backups

Set up a cron job for regular backups:

```bash
0 2 * * * auberge backup create --host my-vps --apps baikal,freshrss,navidrome
```

### Retention Policy

Keep multiple timestamped backups and periodically clean old ones:

```bash
# Keep last 7 days, delete older
find ~/.local/share/auberge/backups/my-vps/*/20* -type d -mtime +7 -exec rm -rf {} \;
```

### Test Restores

Periodically test restores to verify backups are working:

```bash
auberge backup restore latest --host my-vps --apps baikal --dry-run
```

### Before Major Changes

Always create a backup before running Ansible playbooks or system updates:

```bash
auberge backup create --host my-vps
auberge ansible run --host my-vps --tags baikal
```

## Troubleshooting

### "No backups found for host"

The backup directory doesn't exist for the specified host. Create a backup first:

```bash
auberge backup create --host my-vps
```

### "SSH key not found"

See [docs/ssh.md](./ssh.md) for SSH key configuration options.

### "Required service not found on target host"

The target host is missing required systemd services. Run Ansible to install:

```bash
auberge ansible run --host new-vps
```

### "Insufficient disk space"

Target host doesn't have enough space for the restore. Free up space or use a larger VPS.

### Backup/Restore Hangs

Check network connectivity and SSH connection:

```bash
ssh -v user@host
```

If using SSH ControlMaster, clean up stale sockets:

```bash
rm /tmp/ssh-*
```

### Service Won't Start After Restore

Check service logs:

```bash
ssh user@host 'journalctl -u php*-fpm -n 50'
```

Common issues:

- File permissions (automatically fixed during restore; if still broken, re-run Ansible)
- Missing dependencies (fix: reinstall service)
- Port conflicts (fix: check `netstat -tulpn`)

## OPML Export/Import (FreshRSS)

Export and import RSS feed subscriptions independently of full backups.

### Export Feeds

```bash
auberge backup export-opml --host my-vps --output feeds.opml
```

With custom FreshRSS user:

```bash
auberge backup export-opml --host my-vps --output feeds.opml --user admin
```

### Import Feeds

```bash
auberge backup import-opml --host my-vps --input feeds.opml
```

This uploads the OPML file to the server and imports it into FreshRSS, then cleans up the temporary file.

## Technical Details

### Backup Process

1. Services are stopped via `systemctl stop {service}`
2. Data is synced from remote using `rsync` with SSH
3. Services are restarted via `systemctl start {service}`
4. `latest` symlink is updated to point to new backup

### Restore Process

1. Pre-flight validation (cross-host only)
2. Emergency backup creation (cross-host only)
3. User confirmation (hostname typing for cross-host, Y/N for same-host)
4. Services are stopped on target
5. Data is synced to remote using `rsync` with SSH
6. File ownership is set to service user (e.g., `chown -R calibre:calibre /home/calibre`)
7. Services are restarted on target
8. Post-restore guidance displayed (cross-host only)

### Excluded Files

The following patterns are excluded from backups to reduce size:

- `.git/` directories (except Baikal's VCS)
- `node_modules/`
- `venv/`, `__pycache__/`
- `*.pyc`, `*.pyo`, `*.tmp`, `*.log`
- `.DS_Store`, `.cache/`
- `.Baikal.cache/`

### SSH Connection Pooling

Backup and restore operations use SSH ControlMaster for connection reuse:

- ControlPath: `/tmp/ssh-%r@%h:%p`
- ControlPersist: 60 seconds

This significantly speeds up operations that require multiple SSH commands.