Ballast

Let Ballast read your backup

Ballast needs an account that can read your backups. It doesn't need one that can change them.

You run these on your server. Ballast doesn't run them and can't: it only reads.

The idea

Sign in with a separate account that belongs to a group with read access. Whoever makes the backups keeps writing as before. These steps use an account called ballast and a group called backupread; the sudo steps are yours to run.

sudo groupadd backupread
sudo usermod -aG backupread ballast

Worth knowing first

To list snapshots, the account has to read the backup's password. That means anyone holding this phone's key can decrypt those backups, even though they can't change them. If that's too much, sign in from a device you trust as much as the server.

restic

Put the repository and its password file in the group. New files follow the repository's permissions, so this keeps working after the next backup.

sudo chgrp -R backupread /srv/backups/restic
sudo chmod -R g+rX,g-w /srv/backups/restic
sudo find /srv/backups/restic -type d -exec chmod g+s {} +
sudo chgrp backupread /etc/restic/password
sudo chmod 640 /etc/restic/password

Works over SFTP too, as long as that account can sign in to the SFTP server. Cloud storage has its own credentials: Ballast's environment file setting is where those go.

Borg

Borg makes new files private by default, which breaks read access after your next backup. Add --umask 0027 to the Borg commands that write: init, create, prune and compact.

sudo chgrp -R backupread /srv/backups/borg
sudo chmod -R g+rX,g-w /srv/backups/borg
sudo find /srv/backups/borg -type d -exec chmod g+s {} +
borg --umask 0027 create /srv/backups/borg::{now} /srv/data

An unencrypted repository needs one answer the first time this account reads it. Run this once, signed in as that account:

BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes borg list /srv/backups/borg

borgmatic: reads through borgmatic always take Borg's lock, so they need write access to the repository. They're the one case where Ballast's read changes the repository. To stay truly read-only, add the same repository to Ballast as plain Borg instead. Its check history also belongs to the account that runs the checks, so Ballast only sees it if it signs in as that account.

Kopia

Each account connects to the repository once, and the connection is saved in its own home folder. For a new filesystem repository, set the file modes when you create it:

kopia repository create filesystem --path /srv/backups/kopia --file-mode 0640 --dir-mode 2750
sudo chgrp -R backupread /srv/backups/kopia
# then, signed in as the ballast account:
kopia repository connect filesystem --path /srv/backups/kopia --persist-credentials

An existing repository without those modes will lose read access at its next snapshot, because new files aren't group-readable. Ballast lists with --all, so snapshots made by other accounts appear too.

ZFS

Ballast reads with zfs list and zpool status, and on most systems any account can run those. This one isn't tested in our lab, which has no ZFS. If it's refused, check the permissions on /dev/zfs and read man zfs-allow.

Folders and logs

Give the group read access to the backup folder and its log file. Ballast only runs find and tail on them.

"Ballast can't find my tool"

Commands over SSH get a shorter PATH than a login: ~/.local/bin isn't in it on most systems. Ballast adds /usr/sbin and /sbin for ZFS. For anything else, link the tool into a folder on that path:

sudo ln -s ~/.local/bin/borgmatic /usr/local/bin/borgmatic

"Ballast can't find my backup"

It looks for restic in your account's crontab, /etc/crontab, /etc/cron.d and systemd units in /etc/systemd/system, for lines that name both a repository and a password file. Root's own crontab can't be read without sudo, so a schedule there won't appear. Add that backup by hand with the same paths.