153 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ config, pkgs, lib, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
  cfg = config.services.snapper;
 | 
						|
in
 | 
						|
 | 
						|
{
 | 
						|
  options.services.snapper = {
 | 
						|
 | 
						|
    snapshotInterval = mkOption {
 | 
						|
      type = types.str;
 | 
						|
      default = "hourly";
 | 
						|
      description = ''
 | 
						|
        Snapshot interval.
 | 
						|
 | 
						|
        The format is described in
 | 
						|
        <citerefentry><refentrytitle>systemd.time</refentrytitle>
 | 
						|
        <manvolnum>7</manvolnum></citerefentry>.
 | 
						|
      '';
 | 
						|
    };
 | 
						|
 | 
						|
    cleanupInterval = mkOption {
 | 
						|
      type = types.str;
 | 
						|
      default = "1d";
 | 
						|
      description = ''
 | 
						|
        Cleanup interval.
 | 
						|
 | 
						|
        The format is described in
 | 
						|
        <citerefentry><refentrytitle>systemd.time</refentrytitle>
 | 
						|
        <manvolnum>7</manvolnum></citerefentry>.
 | 
						|
      '';
 | 
						|
    };
 | 
						|
 | 
						|
    filters = mkOption {
 | 
						|
      type = types.nullOr types.lines;
 | 
						|
      default = null;
 | 
						|
      description = ''
 | 
						|
        Global display difference filter. See man:snapper(8) for more details.
 | 
						|
      '';
 | 
						|
    };
 | 
						|
 | 
						|
    configs = mkOption {
 | 
						|
      default = { };
 | 
						|
      example = literalExample {
 | 
						|
        home = {
 | 
						|
          subvolume = "/home";
 | 
						|
          extraConfig = ''
 | 
						|
            ALLOW_USERS="alice"
 | 
						|
          '';
 | 
						|
        };
 | 
						|
      };
 | 
						|
 | 
						|
      description = ''
 | 
						|
        Subvolume configuration
 | 
						|
      '';
 | 
						|
 | 
						|
      type = types.attrsOf (types.submodule {
 | 
						|
        options = {
 | 
						|
          subvolume = mkOption {
 | 
						|
            type = types.path;
 | 
						|
            description = ''
 | 
						|
              Path of the subvolume or mount point.
 | 
						|
              This path is a subvolume and has to contain a subvolume named
 | 
						|
              .snapshots.
 | 
						|
              See also man:snapper(8) section PERMISSIONS.
 | 
						|
            '';
 | 
						|
          };
 | 
						|
 | 
						|
          fstype = mkOption {
 | 
						|
            type = types.enum [ "btrfs" ];
 | 
						|
            default = "btrfs";
 | 
						|
            description = ''
 | 
						|
              Filesystem type. Only btrfs is stable and tested.
 | 
						|
            '';
 | 
						|
          };
 | 
						|
 | 
						|
          extraConfig = mkOption {
 | 
						|
            type = types.lines;
 | 
						|
            default = "";
 | 
						|
            description = ''
 | 
						|
              Additional configuration next to SUBVOLUME and FSTYPE.
 | 
						|
              See man:snapper-configs(5).
 | 
						|
            '';
 | 
						|
          };
 | 
						|
        };
 | 
						|
      });
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  config = mkIf (cfg.configs != {}) (let
 | 
						|
    documentation = [ "man:snapper(8)" "man:snapper-configs(5)" ];
 | 
						|
  in {
 | 
						|
 | 
						|
    environment = {
 | 
						|
 | 
						|
      systemPackages = [ pkgs.snapper ];
 | 
						|
 | 
						|
      # Note: snapper/config-templates/default is only needed for create-config
 | 
						|
      #       which is not the NixOS way to configure.
 | 
						|
      etc = {
 | 
						|
 | 
						|
        "sysconfig/snapper".text = ''
 | 
						|
          SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
 | 
						|
        '';
 | 
						|
 | 
						|
      }
 | 
						|
      // (mapAttrs' (name: subvolume: nameValuePair "snapper/configs/${name}" ({
 | 
						|
        text = ''
 | 
						|
          ${subvolume.extraConfig}
 | 
						|
          FSTYPE="${subvolume.fstype}"
 | 
						|
          SUBVOLUME="${subvolume.subvolume}"
 | 
						|
        '';
 | 
						|
      })) cfg.configs)
 | 
						|
      // (lib.optionalAttrs (cfg.filters != null) {
 | 
						|
        "snapper/filters/default.txt".text = cfg.filters;
 | 
						|
      });
 | 
						|
 | 
						|
    };
 | 
						|
 | 
						|
    services.dbus.packages = [ pkgs.snapper ];
 | 
						|
 | 
						|
    systemd.services.snapper-timeline = {
 | 
						|
      description = "Timeline of Snapper Snapshots";
 | 
						|
      inherit documentation;
 | 
						|
      serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
 | 
						|
    };
 | 
						|
 | 
						|
    systemd.timers.snapper-timeline = {
 | 
						|
      description = "Timeline of Snapper Snapshots";
 | 
						|
      inherit documentation;
 | 
						|
      wantedBy = [ "basic.target" ];
 | 
						|
      timerConfig.OnCalendar = cfg.snapshotInterval;
 | 
						|
    };
 | 
						|
 | 
						|
    systemd.services.snapper-cleanup = {
 | 
						|
      description = "Cleanup of Snapper Snapshots";
 | 
						|
      inherit documentation;
 | 
						|
      serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
 | 
						|
    };
 | 
						|
 | 
						|
    systemd.timers.snapper-cleanup = {
 | 
						|
      description = "Cleanup of Snapper Snapshots";
 | 
						|
      inherit documentation;
 | 
						|
      wantedBy = [ "basic.target" ];
 | 
						|
      timerConfig.OnBootSec = "10m";
 | 
						|
      timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
 | 
						|
    };
 | 
						|
  });
 | 
						|
}
 | 
						|
 |