Backing up
Win 11 made me make the move to finally start using Linux on my daily driver computer after almost 3 decades of using Windows. Six months ago, I’ve ditched Windows for Bluefin (Fedora Silverblue). Linux desktop experience is much different from when I remember it 10-15 years ago. Bluefin is an immutable distro, which essentially ends the fight with the package manager by making critical system files read-only. Obviously this has some tradeoffs as you’re essentially working with homebrew and Flatpak whenever you need to install command line or GUI application that’s not included in the base image.
This is a conscious and opinionated decision by the developers of Bluefin. Silverblue works on OCI images booted as a readonly file system, ensuring reproducibility and stability. Even though it is possible to “layer” your changes, you’re suggested to not do it. Development environments are again based on container technologies and you never install them on your actual system. It’s a fascinating way to work, but that’s for another day.
One of the biggest challenges of moving to a new OS was finding a solution for backing up my files. I was a faithful user of CrashPlan for many years to do incremental, off-site backups. After quite some research I’ve decided to use restic without a GUI. I’ve attempted to set it up via systemd but it was too fiddly. After working on it for a few days, I now had to understand how permissions worked with a unit and I finally decided that was already too much work.
It was a matter of making sure a piece of software is running and considering my distro, next obvious solution was indeed using Docker. Conveniently, resticprofile has a docker image. It is a pretty capable restic manager and it’d be incredibly reproducible once I set it up! This is roughly the config file I use:
version: '1'
global:
scheduler: crond
main:
password-file: /run/secrets/restic_password
repository: 'rclone:drive:restic'
initialize: false
force-inactive-lock: true
backup:
source: .
source-base: <path-to-be-backed-up-files>
source-relative: true
exclude-caches: true
one-file-system: true
tag: 'main'
schedule: 'hourly'
schedule-permission: system
skip-if-unchanged: true
check-before: true
dry-run: false
verbose: true
As the backup server, I’m using Google Drive on a Workspace account via rclone, which is a supported backend for restic and is very cheap in my location. From memory, it let’s you setup an oauth app and manages tokens internally. Obviously, the backup (as well as the rclone config) is encrypted and another problem was keeping those passwords safe. This is important to minimize risk of ransomware attacks (which might access the backup as well if you’re not careful). I use secret-tool to keep them:
secret-tool store --label="Restic Backup" service rclone:drive:restic
Unfortunately docker only supports secrets in swarm mode, so I also need to make it a swarm manager as a one time setup, and deploy to it:
docker swarm init
# Feed passwords to docker
secret-tool lookup service rclone:drive:restic | docker secret create restic_password -
secret-tool lookup service rclone | docker secret create rclone_password -
docker stack deploy --compose-file=./docker-compose.yml restic
And finally this is the compose file:
services:
restic:
image: creativeprojects/resticprofile:0.30.1
volumes:
# Config locations
- ./:/resticprofile
- $HOME/.config/rclone:/root/.config/rclone
# Backup sources, mapped to same path for consistency in the backup
- <path-to-be-backed-up-files>:<path-to-be-backed-up-files>:ro
# Cache locations
- /tmp
- /root/.cache/restic
restart: unless-stopped
hostname: $HOSTNAME
secrets:
- restic_password
- rclone_password
entrypoint: "/bin/sh"
command:
- "-c"
- "resticprofile schedule --all && crond -f"
environment:
- RCLONE_PASSWORD_COMMAND=cat /run/secrets/rclone_password
- TZ=Europe/Istanbul
- GOMAXPROCS=2
secrets:
restic_password:
external: true
rclone_password:
external: true
All the secrets are mapped to files in /run/secrets, which I configure things to use them. I also mount cache locations to make sure they persist and use my local rclone config file, which is also encrypted. Resticprofile have these send-after-fail and send-after configurations (redacted above) which I use for setting up heartbeats & alerts when things go wrong or things are not backed up on time to let me know via a Telegram bot.
Even though it is capable of supporting all my use cases, it has its flaws. One nuiscance is b/c the container is running as root, rclone keeps changing permissions of my local configuration file. OTOH, I want to share them b/c I sometimes use it on the host machine as well. Other things I want to experiment with are; append only backups, so that it is not possible to delete them and BTRFS snapshots, which would probably not be feasible via docker.
Reach me out for any comments or questions on Twitter.