Compare commits

...
2 Commits
Author SHA256 Message Date
spacefreak 2fdf065017 document encryption key handling in README.md 2026-08-27 23:14:49 +02:00
spacefreak 6239fe5ca6 add support for encryption keys 2026-08-27 23:14:18 +02:00
3 changed files with 67 additions and 22 deletions
+48 -16
View File
@@ -3,10 +3,10 @@
A Bash wrapper around Proxmox's `proxmox-backup-client` for Proxmox Backup Server (PBS).
It keeps the repository, credentials and the list of paths to back up in a single config
file, injects the configured namespace (`--ns`) into every command that needs it, and lets
you pick a snapshot group, snapshot and archive from an interactive menu instead of typing
them out. Any command it does not implement itself is passed straight through to
`proxmox-backup-client`.
file, injects the configured namespace (`--ns`) and encryption key (`--keyfile`) into every
command that needs them, and lets you pick a snapshot group, snapshot and archive from an
interactive menu instead of typing them out. Any command it does not implement itself is
passed straight through to `proxmox-backup-client`.
## Requirements
@@ -50,24 +50,15 @@ sudo chmod 640 /etc/pbc/config
sudo editor /etc/pbc/config
```
```bash
PBS_SERVER='pbs.domain.tld:8007'
PBS_USER='backup@pam:token-name'
PBS_PASSWORD='XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
PBS_DATASTORE='backup'
PBS_NAMESPACE='MyBackups'
BACKUP=('root.pxar:/' 'data.pxar:/mnt/data')
```
| Key | Description |
|---|---|
| `PBS_SERVER` | PBS host and port |
| `PBS_USER` | User and API token name, `user@realm:token-name` |
| `PBS_PASSWORD` | The API token secret |
| `PBS_DATASTORE` | Datastore to back up to |
| `PBS_NAMESPACE` | Namespace inside the datastore |
| `PBS_NAMESPACE` | Optional, namespace inside the datastore |
| `BACKUP` | Array of `archive-name.pxar:/path` entries to back up |
| `ENCRYPTION_KEYFILE` | Optional, path to the client encryption key — see [Encryption](#encryption) |
| `PBC` | Optional, path to `proxmox-backup-client` (default `/usr/local/bin/proxmox-backup-client`) |
`pbc` never creates the config for you — copy the example and edit it yourself. The file
@@ -93,6 +84,45 @@ Use a different config with `-c`:
pbc -c ./myconfig list
```
## Encryption
Backups can be encrypted client-side, so PBS only ever sees ciphertext. Create a key and
point `ENCRYPTION_KEYFILE` at it:
```bash
sudo proxmox-backup-client key create /etc/pbc/backup.key --kdf none
sudo chmod 600 /etc/pbc/backup.key
```
`pbc` errors out if the key is missing or unreadable, and warns if it is readable by
others. As with the config, the file has to be readable for the user that runs `pbc`
`sudo chown youruser /etc/pbc/backup.key` if that is not root.
**Back the key up somewhere else.** Without it the backups are unrecoverable, and a key
stored only on the machine you are backing up is gone exactly when you need it. Print a
recovery sheet and keep it off-host:
```bash
sudo proxmox-backup-client key paperkey /etc/pbc/backup.key
```
`--kdf none` leaves the key unprotected on disk, which is what makes unattended backups
possible. With a passphrase-protected key (`--kdf scrypt`) the client prompts on every run
and `backup-cron` hangs; export `PBS_ENCRYPTION_PASSWORD` in that case.
The key is passed to `backup`, `backup-cron`, `mount` and `catalog-shell`. It is *not*
passed to commands that fall through to `proxmox-backup-client``pbc restore` needs both
flags spelled out:
```bash
pbc restore --ns MyBackups --keyfile /etc/pbc/backup.key \
host/myhost/2026-08-24T01:00:00Z root.pxar /mnt/restore
```
Setting `ENCRYPTION_KEYFILE` only affects snapshots made from then on. Older unencrypted
snapshots stay readable, and listing works without the key either way — only reading
archive contents needs it.
## Usage
Run `pbc --help` for the synopsis and the list of options, or `pbc -H` to additionally
@@ -150,7 +180,8 @@ pbc mount host/myhost/2026-08-24T01:00:00Z root.pxar /mnt/restore
```
The target directory is not created for you — create it beforehand and make sure it is
writable for the user that runs `pbc`. Unmount when done:
writable for the user that runs `pbc`. Encrypted archives are decrypted transparently when
`ENCRYPTION_KEYFILE` is configured. Unmount when done:
```bash
umount /mnt/restore
@@ -159,6 +190,7 @@ umount /mnt/restore
### catalog-shell
Open an interactive shell to browse an archive and restore selected files — see below.
Encrypted archives are decrypted transparently when `ENCRYPTION_KEYFILE` is configured.
```bash
pbc catalog-shell
+1
View File
@@ -3,5 +3,6 @@ PBS_USER='backup@pam:token-name'
PBS_PASSWORD='XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
PBS_DATASTORE='backup'
PBS_NAMESPACE='MyBackups'
#ENCRYPTION_KEYFILE='/etc/pbc/backup.key'
BACKUP=('root.pxar:/' 'data.pxar:/mnt/data')
+18 -6
View File
@@ -53,17 +53,17 @@ function pbc-version() {
return $rc
}
function pbc-backup() { "$PBC" backup --ns "$PBS_NAMESPACE" "${BACKUP[@]}" "$@"; }
function pbc-backup() { "$PBC" backup "${PBC_ARGS[@]}" "${KEY_ARGS[@]}" "${BACKUP[@]}" "$@"; }
function pbc-list() { "$PBC" list --ns "$PBS_NAMESPACE" "$@"; }
function pbc-list() { "$PBC" list "${PBC_ARGS[@]}" "$@"; }
function pbc-snapshot-list() { "$PBC" snapshot list --ns "$PBS_NAMESPACE" "$@"; }
function pbc-snapshot-list() { "$PBC" snapshot list "${PBC_ARGS[@]}" "$@"; }
function pbc-files() { "$PBC" files --ns "$PBS_NAMESPACE" "$@"; }
function pbc-files() { "$PBC" files "${PBC_ARGS[@]}" "$@"; }
function pbc-catalog-shell() { "$PBC" catalog shell --ns "$PBS_NAMESPACE" "$@"; }
function pbc-catalog-shell() { "$PBC" catalog shell "${PBC_ARGS[@]}" "${KEY_ARGS[@]}" "$@"; }
function pbc-mount() { "$PBC" mount --ns "$PBS_NAMESPACE" "$@"; }
function pbc-mount() { "$PBC" mount "${PBC_ARGS[@]}" "${KEY_ARGS[@]}" "$@"; }
function get_group_names() {
pbc-list --output-format json | jq -r '.[] | "\(.["backup-type"])/\(.["backup-id"])"'
@@ -307,7 +307,19 @@ else
[ ! -f "$PBC" ] && echo "Error: $PBC: no such file" >&2 && exit 200
[ ! -x "$PBC" ] && echo "Error: $PBC: not executable" >&2 && exit 200
! command -v jq >/dev/null && echo "Error: jq executable not found!" >&2 && exit 200
if [ -n "$ENCRYPTION_KEYFILE" ]; then
[ ! -f "$ENCRYPTION_KEYFILE" ] && echo "Error: $ENCRYPTION_KEYFILE: no such file" >&2 && exit 203
[ ! -r "$ENCRYPTION_KEYFILE" ] && echo "Error: $ENCRYPTION_KEYFILE: not readable" >&2 && exit 203
perms=$(stat -c '%a' "$ENCRYPTION_KEYFILE")
(( 8#$perms & 0007 )) && echo "Warning: $ENCRYPTION_KEYFILE is readable by others!" >&2
fi
fi
PBC_ARGS=()
KEY_ARGS=()
[ -n "$PBS_NAMESPACE" ] && PBC_ARGS+=('--ns' "$PBS_NAMESPACE")
[ -n "$ENCRYPTION_KEYFILE" ] && KEY_ARGS+=('--keyfile' "$ENCRYPTION_KEYFILE")
export PBS_REPOSITORY="$PBS_USER@$PBS_SERVER:$PBS_DATASTORE"
export PBS_PASSWORD="$PBS_PASSWORD"