1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.services.autotierfs;
9 ini = pkgs.formats.ini { };
10 format = lib.types.attrsOf ini.type;
11 stateDir = "/var/lib/autotier";
12
13 generateConfigName =
14 name: builtins.replaceStrings [ "/" ] [ "-" ] (lib.strings.removePrefix "/" name);
15 configFiles = builtins.mapAttrs (
16 name: val: ini.generate "${generateConfigName name}.conf" val
17 ) cfg.settings;
18
19 getMountDeps =
20 settings: builtins.concatStringsSep " " (builtins.catAttrs "Path" (builtins.attrValues settings));
21
22 mountPaths = builtins.attrNames cfg.settings;
23in
24{
25 options.services.autotierfs = {
26 enable = lib.mkEnableOption "the autotier passthrough tiering filesystem";
27 package = lib.mkPackageOption pkgs "autotier" { };
28 settings = lib.mkOption {
29 type = lib.types.submodule {
30 freeformType = format;
31 };
32 default = { };
33 description = ''
34 The contents of the configuration file for autotier.
35 See the [autotier repo](https://github.com/45Drives/autotier#configuration) for supported values.
36 '';
37 example = lib.literalExpression ''
38 {
39 "/mnt/autotier" = {
40 Global = {
41 "Log Level" = 1;
42 "Tier Period" = 1000;
43 "Copy Buffer Size" = "1 MiB";
44 };
45 "Tier 1" = {
46 Path = "/mnt/tier1";
47 Quota = "30GiB";
48 };
49 "Tier 2" = {
50 Path = "/mnt/tier2";
51 Quota = "200GiB";
52 };
53 };
54 }
55 '';
56 };
57 };
58
59 config = lib.mkIf cfg.enable {
60 assertions = [
61 {
62 assertion = cfg.settings != { };
63 message = "`services.autotierfs.settings` must be configured.";
64 }
65 ];
66
67 system.fsPackages = [ cfg.package ];
68
69 # Not necessary for module to work but makes it easier to pass config into cli
70 environment.etc = lib.attrsets.mapAttrs' (
71 name: value:
72 lib.attrsets.nameValuePair "autotier/${(generateConfigName name)}.conf" { source = value; }
73 ) configFiles;
74
75 systemd.tmpfiles.rules = (map (path: "d ${path} 0770 - autotier - -") mountPaths) ++ [
76 "d ${stateDir} 0774 - autotier - -"
77 ];
78
79 users.groups.autotier = { };
80
81 systemd.services = lib.attrsets.mapAttrs' (
82 path: values:
83 lib.attrsets.nameValuePair (generateConfigName path) {
84 description = "Mount autotierfs virtual path ${path}";
85 unitConfig.RequiresMountsFor = getMountDeps values;
86 wantedBy = [ "local-fs.target" ];
87 serviceConfig = {
88 Type = "forking";
89 ExecStart = "${lib.getExe' cfg.package "autotierfs"} -c /etc/autotier/${generateConfigName path}.conf ${path} -o allow_other,default_permissions";
90 ExecStop = "umount ${path}";
91 };
92 }
93 ) cfg.settings;
94 };
95}