I've just updated the backup strategy for my NixOS home server, switching from a simple daily script to an hourly one. It's not quite as elegant as the Mastodon instance my friend manages—where we have ZFS snapshots every 20 minutes—but I'm happy with this solution. And I have to say, I'm liking NixOS more and more. Without AI, it would be far too complicated for me to understand, but by now I can at least read the finished Nix files. I once considered switching the server to a standard Linux distribution, but as long as it works this well...

  1. /etc/nixos: The entire NixOS configuration (all .nix files).

  2. /opt/minecraft: All worlds and data for the Minecraft server.

  3. /opt/satisfactory: Save games and configuration for the Satisfactory server.

  4. /opt/Blog: The source code and content of the blog.

  5. /opt/ui: The Mastodon UI files.

  6. /opt/audiobookshelf: The audiobooks and the associated database.

Everything ends up on S3 storage mounted via RClone.

The NixOS Configuration


{ config, pkgs, ... }:

{
  # BorgBackup configuration
  services.borgbackup.jobs.hourly = {
    # Path to the repository in the S3 mount
    repo = "/opt/S3/Backup/NixOSHomeServer_Borg";

    # No password required
    encryption.mode = "none";

    # Compression for even more space savings
    compression = "auto,zstd";

    # The paths to be backed up
    paths = [
      "/etc/nixos"
      "/opt/minecraft"
      "/opt/satisfactory"
      "/opt/Blog"
      "/opt/ui"
      "/opt/audiobookshelf"
    ];

    # Hourly execution
    startAt = "hourly";

    # Automatically initialize repository if it's missing
    doInit = true;

    # Retention rules (Pruning)
    prune.keep = {
      within = "1d"; # All snapshots from the last 24h
      daily = 7;
      weekly = 4;
      monthly = 12;
    };
  };

  # Ensure the S3 mount is ready before Borg starts
  systemd.services.borgbackup-job-hourly = {
    requires = [ "rclone-s3-mount.service" ];
    after = [ "rclone-s3-mount.service" ];
  };
}