raspberry pi to PBS¶
my Z-Wave pi backs itself up to PBS every hour, as a host
backup in the Hosts namespace. this is how.
the client on arm64¶
Proxmox only publishes proxmox-backup-client for amd64. Debian does not package
it either. for a pi that leaves community builds, and the one i use is
wofferl/proxmox-backup-arm64,
which builds the Proxmox sources for arm64 and publishes Debian packages for
bookworm and trixie. i use the static client, it has no library dependencies.
check the pi is 64 bit first. armhf means a 32 bit OS and this will not run:
download, check it is the file GitHub has for that release, install:
cd /tmp
curl -fLO https://github.com/wofferl/proxmox-backup-arm64/releases/download/4.2.5-1/proxmox-backup-client-static_4.2.5-1_arm64.deb
echo "0c7f9be14286ddaeef2a2644d1515051ef94759336a980b34579105062221848 proxmox-backup-client-static_4.2.5-1_arm64.deb" | sha256sum -c
sudo apt install ./proxmox-backup-client-static_4.2.5-1_arm64.deb
proxmox-backup-client version
the checksum is the one GitHub publishes for that release asset. it proves you got
the file that was uploaded, not that the build is trustworthy. if that matters to
you, the same repo's ./build.sh client builds it from source. match the client
version to your PBS.
1. a user and token for this machine only¶
on PBS. one user and token per machine, never shared: PBS only lets a
DatastoreBackup token touch backup groups it owns, so separate tokens keep one
machine from reading another's backups, and a lost pi means deleting one token.
proxmox-backup-manager user create pi-zwave01@pbs --comment "pi-zwave01 host backups"
proxmox-backup-manager acl update /datastore/mnt-pbs/Hosts DatastoreBackup --auth-id pi-zwave01@pbs
proxmox-backup-manager user generate-token pi-zwave01@pbs backup
proxmox-backup-manager acl update /datastore/mnt-pbs/Hosts DatastoreBackup --auth-id 'pi-zwave01@pbs!backup'
- the user and the token both need the ACL, a token can never do more than its user
- the ACL is on the
Hostsnamespace only, not the whole datastore generate-tokenshows the secret once. keep it somewhere safe before you close the shell
taking over an existing backup group. if the machine backed up before under another token, its group still belongs to that token and the first run fails with
change the owner in the PBS UI: datastore, Content, namespace Hosts, the person
icon on the group. the old snapshots stay in the group.
2. the token file¶
keep it somewhere that is not backed up, so a copy of the credential does not end up inside the backups it protects:
sudo install -d -m 700 /var/lib/pbs-backup
sudo nano /var/lib/pbs-backup/token # paste the secret, save
sudo chmod 600 /var/lib/pbs-backup/token
the file holds the secret only, not the user!token part. the client reads only
the first line, so the newline nano adds is fine.
3. the script¶
/usr/local/sbin/pbs-backup, mode 700:
#!/bin/bash
set -euo pipefail
export PBS_REPOSITORY='pi-zwave01@pbs!backup@pbs1.yourdomain.com:mnt-pbs'
export PBS_PASSWORD_FILE=/var/lib/pbs-backup/token
proxmox-backup-client backup \
docker-data.pxar:/docker-data \
etc.pxar:/etc \
usr-local.pxar:/usr/local \
root.pxar:/root \
home.pxar:/home \
--ns Hosts --backup-id pi-zwave01
what the archives are for:
| archive | why |
|---|---|
docker-data.pxar |
everything the containers keep. this is the one you restore |
etc.pxar, usr-local.pxar, root.pxar, home.pxar |
reference copies of config, for pulling out a single file. not for restoring over a fresh install |
the whole filesystem is not backed up on purpose. restoring /usr or package
state file by file over a running system does not work well, docker's images come
back from their registries, and the stacks come back from git. the plan is to
rebuild the pi from a script and restore docker-data.pxar.
typing this at an interactive bash prompt, run set +H first, or the ! in
pi-zwave01@pbs!backup gets treated as history expansion.
4. an hourly timer¶
/etc/systemd/system/pbs-backup.service:
[Unit]
Description=Back up pi-zwave01 to PBS
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/pbs-backup
/etc/systemd/system/pbs-backup.timer:
run it once by hand before turning the timer on:
sudo systemctl daemon-reload
sudo systemctl start pbs-backup.service
journalctl -u pbs-backup -n 30 --no-pager
sudo systemctl enable --now pbs-backup.timer
a timer rather than cron because the output lands in the journal, and
Persistent=true runs a missed backup when the pi comes back up.
5. prove it restores¶
a clean exit only proves the upload finished. this proves the backup is usable.
set +H
export PBS_REPOSITORY='pi-zwave01@pbs!backup@pbs1.yourdomain.com:mnt-pbs'
export PBS_PASSWORD_FILE=/var/lib/pbs-backup/token
SNAP='host/pi-zwave01/<snapshot time>'
du -sh --apparent-size /docker-data
proxmox-backup-client catalog dump "$SNAP" --ns Hosts 2>&1 | grep -E 'configuration.yaml|ser2net.yaml'
proxmox-backup-client restore "$SNAP" docker-data.pxar /tmp/restore-test --ns Hosts
diff -rq /docker-data /tmp/restore-test | wc -l
rm -rf /tmp/restore-test
- the size should match what the backup log reported
catalog dumpwrites to stderr, hence the2>&1, or the grep sees nothing- a handful of differences is normal, files the apps wrote since the backup. on mine it was six, all Z-Wave's network cache and today's logs
mine: 20 MB of /docker-data, 6 MB compressed, under two seconds to back up, half
a second to restore.