modules/betanin: support settings
This commit is contained in:
		| @@ -4,14 +4,27 @@ let | |||||||
|   inherit (lib) mkIf mkOption optionalAttrs types; |   inherit (lib) mkIf mkOption optionalAttrs types; | ||||||
|   cfg = config.services.betanin; |   cfg = config.services.betanin; | ||||||
|  |  | ||||||
|   yaml = pkgs.formats.yaml { }; |  | ||||||
|   configFile = |  | ||||||
|     if (cfg.beetsConfigFile != null) |  | ||||||
|     then cfg.beetsConfigFile |  | ||||||
|     else yaml.generate "beets-config.yaml" cfg.beetsConfig; |  | ||||||
|  |  | ||||||
|   defaultUser = "betanin"; |   defaultUser = "betanin"; | ||||||
|   defaultGroup = "betanin"; |   defaultGroup = "betanin"; | ||||||
|  |  | ||||||
|  |   finalSettings = | ||||||
|  |     let | ||||||
|  |       base = lib.filterAttrsRecursive (n: _: lib.hasSuffix "_file" n) cfg.settings; | ||||||
|  |       clean = { | ||||||
|  |         frontend.password = cfg.settings.frontend.password or "@password@"; | ||||||
|  |         clients.api_key = cfg.settings.clients.api_key or "@api_key@"; | ||||||
|  |       }; | ||||||
|  |     in | ||||||
|  |     lib.recursiveUpdate base clean; | ||||||
|  |  | ||||||
|  |   settingsFormat = pkgs.formats.toml { }; | ||||||
|  |   settingsFile = settingsFormat.generate "betanin.toml" finalSettings; | ||||||
|  |  | ||||||
|  |   beetsFormat = pkgs.formats.yaml { }; | ||||||
|  |   beetsFile = | ||||||
|  |     if (cfg.beetsFile != null) | ||||||
|  |     then cfg.beetsFile | ||||||
|  |     else beetsFormat.generate "betanin-beets.yaml" cfg.beetsConfig; | ||||||
| in | in | ||||||
| { | { | ||||||
|   options = { |   options = { | ||||||
| @@ -54,25 +67,123 @@ in | |||||||
|         default = "/var/lib/betanin"; |         default = "/var/lib/betanin"; | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|  |       settings = mkOption { | ||||||
|  |         type = types.submodule { | ||||||
|  |           freeformType = settinsgFormat.type; | ||||||
|  |  | ||||||
|  |           frontend.username = mkOption { | ||||||
|  |             type = types.str; | ||||||
|  |             default = ""; | ||||||
|  |             description = "Username used to log into the frontend. Must be set."; | ||||||
|  |           }; | ||||||
|  |  | ||||||
|  |           frontend.password = mkOption { | ||||||
|  |             type = types.str; | ||||||
|  |             default = ""; | ||||||
|  |             description = '' | ||||||
|  |               Password used to log into the frontend. Either password or | ||||||
|  |               password_file must be set. | ||||||
|  |             ''; | ||||||
|  |           }; | ||||||
|  |  | ||||||
|  |           frontend.password_file = mkOption { | ||||||
|  |             type = with types; nullOr (either str path); | ||||||
|  |             default = null; | ||||||
|  |             description = '' | ||||||
|  |               File containing the password used to log into the frontend. The | ||||||
|  |               file must be readable by the betanin user/group. | ||||||
|  |  | ||||||
|  |               Using a password file keeps the password out of the Nix store, but | ||||||
|  |               the password is still stored in plain text in the service data | ||||||
|  |               directory. | ||||||
|  |             ''; | ||||||
|  |           }; | ||||||
|  |  | ||||||
|  |           clients.api_key = mkOption { | ||||||
|  |             type = types.nullOr types.str; | ||||||
|  |             default = ""; | ||||||
|  |             description = '' | ||||||
|  |               API key used to access Betanin (e.g., from other services). | ||||||
|  |             ''; | ||||||
|  |           }; | ||||||
|  |  | ||||||
|  |           clients.api_key_file = mkOption { | ||||||
|  |             type = with types; nullOr (either str path); | ||||||
|  |             default = null; | ||||||
|  |             description = '' | ||||||
|  |               File containing the API key used to access Betanin (e.g., from | ||||||
|  |               other services). The file must be readable by the betanin | ||||||
|  |               user/group. | ||||||
|  |  | ||||||
|  |               Using a API key file keeps the API key out of the Nix store, but | ||||||
|  |               the API key is still stored in plain text in the service data | ||||||
|  |               directory. | ||||||
|  |             ''; | ||||||
|  |  | ||||||
|  |             notifications.strings.title = mkOption { | ||||||
|  |               type = types.str; | ||||||
|  |               default = "[betanin] torrent `$name` $status"; | ||||||
|  |               description = "Notification title."; | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             notifications.strings.body = mkOption { | ||||||
|  |               type = types.str; | ||||||
|  |               default = "@ $time. view/use the console at http://127.0.0.1:${cfg.port}/$console_path"; | ||||||
|  |               description = "Notification body."; | ||||||
|  |             }; | ||||||
|  |           }; | ||||||
|  |         }; | ||||||
|  |         example = lib.literalExpression '' | ||||||
|  |           { | ||||||
|  |             frontend = { | ||||||
|  |               username = "foo"; | ||||||
|  |               password_file = "/run/secrets/betaninPasswordFile"; | ||||||
|  |             }; | ||||||
|  |             clients = { | ||||||
|  |               api_key_file = "/run/secrets/betaninApiKeyFile"; | ||||||
|  |             }; | ||||||
|  |             server = { | ||||||
|  |               num_parallel_jobs = 1; | ||||||
|  |             }; | ||||||
|  |           } | ||||||
|  |         ''; | ||||||
|  |         description = "Configuration for betanin."; | ||||||
|  |       }; | ||||||
|  |  | ||||||
|       beetsConfig = mkOption { |       beetsConfig = mkOption { | ||||||
|         description = "beets configuration."; |         description = "beets configuration."; | ||||||
|         type = yaml.type; |         type = beetsFormat.type; | ||||||
|         default = { }; |         default = { }; | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|       beetsConfigFile = mkOption { |       beetsFile = mkOption { | ||||||
|         description = "beets configuration file."; |         description = "beets configuration file."; | ||||||
|         type = nullOr (either str path); |         type = with types; nullOr (either str path); | ||||||
|         default = null; |         default = null; | ||||||
|       }; |       }; | ||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   config = mkIf cfg.enable { |   config = mkIf cfg.enable { | ||||||
|     assertions = [{ |     assertions = [ | ||||||
|       assertion = (cfg.beetsConfig == { }) != (cfg.beetsConfigFile == null); |  | ||||||
|       message = "either services.betanin.beetsConfig or services.betanin.beetsConfigFile is required"; |       { | ||||||
|     }]; |         assertion = cfg.settings.frontend.username != ""; | ||||||
|  |         message = "services.betanin.settings.frontend.username is required"; | ||||||
|  |       } | ||||||
|  |       { | ||||||
|  |         assertion = (cfg.settings.frontend.password == "") != (cfg.settings.frontend.password_file); | ||||||
|  |         message = "services.betanin.settings.frontend.password or services.betanin.settings.frontend.password_file is required"; | ||||||
|  |       } | ||||||
|  |       { | ||||||
|  |         assertion = (cfg.settings.clients.api_key == "") != (cfg.settings.clients.api_key_file); | ||||||
|  |         message = "services.betanin.settings.clients.api_key or services.betanin.settings.clients.api_key_file is required"; | ||||||
|  |       } | ||||||
|  |       { | ||||||
|  |         assertion = (cfg.beetsConfig == { }) != (cfg.beetsFile == null); | ||||||
|  |         message = "either services.betanin.beetsConfig or services.betanin.beetsFile is required"; | ||||||
|  |       } | ||||||
|  |     ]; | ||||||
|  |  | ||||||
|     networking.firwall = mkIf cfg.openFirewall { |     networking.firwall = mkIf cfg.openFirewall { | ||||||
|       allowedTCPPorts = [ cfg.port ]; |       allowedTCPPorts = [ cfg.port ]; | ||||||
| @@ -85,11 +196,29 @@ in | |||||||
|       environment = { |       environment = { | ||||||
|         HOME = cfg.dataDir; |         HOME = cfg.dataDir; | ||||||
|       }; |       }; | ||||||
|  |  | ||||||
|  |       script = '' | ||||||
|  |         #!/bin/sh | ||||||
|  |         mkdir -p ${cfg.dataDir}/.config/betanin | ||||||
|  |         mkdir -p ${cfg.dataDir}/.config/beets | ||||||
|  |         mkdir -p ${cfg.dataDir}/.local/share/betanin | ||||||
|  |         cat ${settingsFile} > ${cfg.dataDir}/.config/betanin/config.toml | ||||||
|  |         ln -sf ${beetsFile} ${cfg.dataDir}/.config/betanin/config.toml | ||||||
|  |       '' ++ lib.optionalString (cfg.settings.frontend.password_file != null) '' | ||||||
|  |         sed -i "s/@password@/$(cat ${cfg.settings.frontend.password_file})/" \ | ||||||
|  |           ${cfg.dataDir}/.config/betanin/config.toml | ||||||
|  |       '' ++ lib.optionalString (cfg.settings.frontend.api_key_file != null) '' | ||||||
|  |         sed -i "s/@api_key@/$(cat ${cfg.settings.frontend.api_key_file})/" \ | ||||||
|  |           ${cfg.dataDir}/.config/betanin/config.toml | ||||||
|  |       '' ++ '' | ||||||
|  |         chmod -w ${cfg.dataDir}/.config/betanin/config.toml | ||||||
|  |         ${cfg.package}/bin/betanin --port ${cfg.port} | ||||||
|  |       ''; | ||||||
|  |  | ||||||
|       serviceConfig = lib.mkMerge [ |       serviceConfig = lib.mkMerge [ | ||||||
|         { |         { | ||||||
|           User = cfg.user; |           User = cfg.user; | ||||||
|           Group = cfg.group; |           Group = cfg.group; | ||||||
|           ExecStart = "${cfg.package}/bin/betanin --port ${cfg.port}"; |  | ||||||
|           PrivateTmp = true; |           PrivateTmp = true; | ||||||
|           Restart = "always"; |           Restart = "always"; | ||||||
|           WorkingDirectory = cfg.dataDir; |           WorkingDirectory = cfg.dataDir; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user