Skip to main content

NixOS: Backing Up with Restic

NixOS - This article is part of a series.
Part 8: This Article

Backing up user files to Google Drive
#

Using a combination of Rclone and Restic we can create scheduled, deduplicated backups of user files. This requires a a valid client ID, client secret and access token set up through the google developer console.

Configuring Rclone
#

Rclone can be set up using a sops-nix template as such:

{
  inputs,
  ...
}:
{
  flake.modules.homeManager.rclone =
    {
      pkgs,
      lib,
      config,
      ...
    }:
    {
      options = {
        rclone.enable = lib.mkEnableOption "rclone google drive remote";
        secrets.rclone.enable = lib.mkEnableOption "rclone google drive secrets";
      };

      config = lib.mkMerge [
        (lib.mkIf config.rclone.enable {
          programs.rclone.enable = true;
        })

        (lib.mkIf (config.rclone.enable && config.secrets.enable && config.secrets.rclone.enable) {
          sops = {
            secrets = {
              "restic/repository" = { };
              "restic/password" = { };
              "rclone/client_id" = { };
              "rclone/client_secret" = { };
              "rclone/access_token" = { };
            };
            templates."rclone.conf".content = ''
              [gdrive]
              scope = drive.file
              type = drive
              client_id = ${config.sops.placeholder."rclone/client_id"}
              client_secret = ${config.sops.placeholder."rclone/client_secret"}
              token = ${config.sops.placeholder."rclone/access_token"}
            '';
          };
          home.activation."rclone.conf" = ''
            mkdir -p ~/.config/rclone
            ln -sf ${config.sops.templates."rclone.conf".path} ~/.config/rclone/rclone.conf
          '';
        })
      ];
    };
}

Configuring Restic
#

Restic can be configured using the services.restic config option as follows:

{
  inputs,
  ...
}:
{
  flake.modules.homeManager.restic =
    {
      pkgs,
      lib,
      config,
      ...
    }:
    {
      options = {
        restic.enable = lib.mkEnableOption "restic backups";
        secrets.restic.enable = lib.mkEnableOption "restic repository secrets";
      };

      config = lib.mkMerge [
        (lib.mkIf config.restic.enable {
          home.packages = with pkgs; [
            restic
            restic-browser
          ];
        })

        (lib.mkIf (config.restic.enable && config.secrets.enable && config.secrets.restic.enable) {
          sops.secrets = {
            "restic/repository" = { };
            "restic/password" = { };
          };
          services.restic = {
            enable = true;
            backups.daily = {
              repositoryFile = config.sops.secrets."restic/repository".path;
              passwordFile = config.sops.secrets."restic/password".path;
              paths = [
                "${config.home.homeDirectory}/Documents"
                "${config.home.homeDirectory}/Pictures"
                "${config.home.homeDirectory}/Books"
              ];
              pruneOpts = [
                "--keep-daily 3"
                "--keep-weekly 7"
                "--keep-monthly 15"
                "--keep-yearly 30"
              ];
              timerConfig = {
                OnCalendar = "00:00";
                RandomizedDelaySec = "45m";
                Persistent = true;
              };
            };
          };
        })
      ];
    };
}

NixOS - This article is part of a series.
Part 8: This Article