99 lines
2.7 KiB
Markdown
99 lines
2.7 KiB
Markdown
# Encrypted Hermes Backup Pipeline
|
|
|
|
Issue: `timmy-home#693`
|
|
|
|
This pipeline creates a nightly encrypted archive of `~/.hermes`, stores a local encrypted copy, uploads it to remote storage, and supports restore verification.
|
|
|
|
## What gets backed up
|
|
|
|
By default the pipeline archives:
|
|
|
|
- `~/.hermes/config.yaml`
|
|
- `~/.hermes/state.db`
|
|
- `~/.hermes/sessions/`
|
|
- `~/.hermes/cron/`
|
|
- any other files under `~/.hermes`
|
|
|
|
Override the source with `BACKUP_SOURCE_DIR=/path/to/.hermes`.
|
|
|
|
## Backup command
|
|
|
|
```bash
|
|
BACKUP_PASSPHRASE_FILE=~/.config/timmy/backup.passphrase \
|
|
BACKUP_NAS_TARGET=/Volumes/timmy-nas/hermes-backups \
|
|
bash scripts/backup_pipeline.sh
|
|
```
|
|
|
|
The script writes:
|
|
|
|
- local encrypted copy: `~/.timmy-backups/hermes/<timestamp>/hermes-backup-<timestamp>.tar.gz.enc`
|
|
- local manifest: `~/.timmy-backups/hermes/<timestamp>/hermes-backup-<timestamp>.json`
|
|
- log file: `~/.timmy-backups/hermes/logs/backup_pipeline.log`
|
|
|
|
## Nightly schedule
|
|
|
|
Run every night at 03:00:
|
|
|
|
```cron
|
|
0 3 * * * cd /Users/apayne/.timmy/timmy-home && BACKUP_PASSPHRASE_FILE=/Users/apayne/.config/timmy/backup.passphrase BACKUP_NAS_TARGET=/Volumes/timmy-nas/hermes-backups bash scripts/backup_pipeline.sh >> /Users/apayne/.timmy-backups/hermes/logs/cron.log 2>&1
|
|
```
|
|
|
|
## Remote targets
|
|
|
|
At least one remote target must be configured.
|
|
|
|
### Local NAS
|
|
|
|
Use a mounted path:
|
|
|
|
```bash
|
|
BACKUP_NAS_TARGET=/Volumes/timmy-nas/hermes-backups
|
|
```
|
|
|
|
The pipeline copies the encrypted archive and manifest into `<BACKUP_NAS_TARGET>/<timestamp>/`.
|
|
|
|
### S3-compatible storage
|
|
|
|
```bash
|
|
BACKUP_PASSPHRASE_FILE=~/.config/timmy/backup.passphrase \
|
|
BACKUP_S3_URI=s3://timmy-backups/hermes \
|
|
AWS_ENDPOINT_URL=https://minio.example.com \
|
|
bash scripts/backup_pipeline.sh
|
|
```
|
|
|
|
Notes:
|
|
|
|
- `aws` CLI must be installed if `BACKUP_S3_URI` is set.
|
|
- `AWS_ENDPOINT_URL` is optional and is used for MinIO, R2, and other S3-compatible endpoints.
|
|
|
|
## Restore playbook
|
|
|
|
Restore an encrypted archive into a clean target root:
|
|
|
|
```bash
|
|
BACKUP_PASSPHRASE_FILE=~/.config/timmy/backup.passphrase \
|
|
bash scripts/restore_backup.sh \
|
|
/Volumes/timmy-nas/hermes-backups/20260415-030000/hermes-backup-20260415-030000.tar.gz.enc \
|
|
/tmp/hermes-restore
|
|
```
|
|
|
|
Result:
|
|
|
|
- restored tree lands at `/tmp/hermes-restore/.hermes`
|
|
- if a sibling manifest exists, the restore script verifies the archive SHA256 before decrypting
|
|
|
|
## End-to-end verification
|
|
|
|
Run the regression suite:
|
|
|
|
```bash
|
|
python3 -m unittest discover -s tests -p 'test_backup_pipeline.py' -v
|
|
```
|
|
|
|
This proves:
|
|
|
|
1. the backup output is encrypted
|
|
2. plaintext archives do not leak into the backup destinations
|
|
3. the restore script recreates the original `.hermes` tree end-to-end
|
|
4. the pipeline refuses to run without a remote target
|