I’ve been using Restic for a while, and it’s backing up to a Hetzner storage box (1TB).
Restic supports encryption, compression, deduplication, and can forget old backups in a spread out timeline (configurable; e.g. save one yearly, three monthly and 7 daily).
On top of this I also use healthchecks.io to make sure all backups are working.
I’m in the process of migrating my servers to NixOS. It takes a lot of time and the learning curve is steep, but I have one config shared for all the servers and PCs. I have setup the servers to automatically pull the latest configuration everyday and even restart if there’s a kernel update.
This means I just need to update my laptop and push the changes to the repository, and all the servers will also update.
I haven’t had this setup long enough to know if things will break unexpectedly with updates tho. NixOS has a great feature where you can rollback to a previous configuration (generation) with a single command. You can always keep using containers to isolate updates, if you want (Nix allows you to declare those in the config as well).
As an example, you can take a look at my config.
EDIT: Systemd timers have an option to randomize the time a service runs, I use it all the time. The option for Nix’s config pulling is using systemd timers, so you can use that.