From c536fb72938e6a6e729d701ecb9f52b26bde2da5 Mon Sep 17 00:00:00 2001 From: Christopher Bacher Date: Sat, 29 Oct 2022 14:09:43 +0200 Subject: [PATCH] refactor: move support functions to ./lib; change piholeConfiguration option to piholeConfig The first part of the refactor simplifies the logic in the module and hides functions which are only used to extract container env vars. Second the option renaming to piholeConfig unifies the naming with the hostConfig option. --- flake.nix | 5 ++- lib/options.nix | 40 +++++++++++++++++++ lib/util.nix | 32 +++++++++++---- modules/pihole-container.factory.nix | 59 ++-------------------------- 4 files changed, 73 insertions(+), 63 deletions(-) create mode 100644 lib/options.nix diff --git a/flake.nix b/flake.nix index 0ad326a..933855e 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,10 @@ flake-utils.url = "github:numtide/flake-utils"; - linger.url = "github:mindsbackyard/linger-flake"; + linger = { + url = "github:mindsbackyard/linger-flake"; + inputs.flake-utils.follows = "flake-utils"; + }; }; outputs = { self, nixpkgs, flake-utils, linger }: with flake-utils.lib; eachSystem (with system; [ x86_64-linux aarch64-linux ]) (curSystem: diff --git a/lib/options.nix b/lib/options.nix new file mode 100644 index 0000000..f52be68 --- /dev/null +++ b/lib/options.nix @@ -0,0 +1,40 @@ +nixpkgsLib: with nixpkgsLib; { + mkContainerEnvOption = { envVar, ... }@optionAttrs: + (mkOption (removeAttrs optionAttrs [ "envVar" ])) + // { inherit envVar; }; + + mkHostPortsOption = { service, publicDefaultPort }: { + hostInternalPort = mkOption { + type = types.port; + description = '' + The internal port on the host on which the ${service} port of the pihole container should be exposed. + Only needs to be specified if he container port should be exposed + or if the port-forwarding for this service is enabled. + + As the pihole container is running rootless this cannot be a privileged port (<1024). + ''; + }; + + hostPublicPort = mkOption { + type = types.port; + description = '' + The public port on the host on which the ${service} port of the pihole container should be forwared to. + + This option can be used to together with the according `forwardPublicToInternal` to expose a pihole subservice on a privileged port, + e.g., if you want to expose the DNS service on port 53. + ''; + default = publicDefaultPort; + }; + + forwardPublicToInternal = mkOption { + type = types.bool; + description = '' + Enable port-forwarding between the public & the internal port of the host. + This effectively makes pihole's ${service} port available on the network to which the host is connected to. + + Use this option together with the according `hostPublicPort` to expose a pihole subservice on a privileged port. + ''; + default = false; + }; + }; +} diff --git a/lib/util.nix b/lib/util.nix index 2b29586..532f8e2 100644 --- a/lib/util.nix +++ b/lib/util.nix @@ -1,5 +1,5 @@ -{ - collectAttrFragments = predicate: attrs: with builtins; let +with builtins; let + collectAttrFragments = predicate: attrs: let _collectAttrFragments = attrs: concatMap (key: _collectAttrFragmentsBelowKey key attrs.${key}) (attrNames attrs) ; @@ -12,7 +12,7 @@ in _collectAttrFragments attrs ; - accessValueOfFragment = attrs: fragment: with builtins; let + accessValueOfFragment = attrs: fragment: let _accessValueOfFragment = value: fragment: if fragment == [] then value else _accessValueOfFragment (value.${head fragment}) (tail fragment) @@ -20,8 +20,26 @@ in _accessValueOfFragment attrs fragment ; - toEnvValue = value: with builtins; - if isBool value then (if value then "true" else "false") - else if isList value then "[${concatStringSep ";" value}]" - else value; + toEnvValue = value: + if isBool value then (if value then "true" else "false") + else if isList value then "[${concatStringSep ";" value}]" + else value + ; + +in { + extractContainerEnvVars = piholeOptionDeclarations: piholeOptionDefinitions: let + _opt = piholeOptionDeclarations; + _cfg = piholeOptionDefinitions; + + _envVarFragments = collectAttrFragments (value: isAttrs value && value ? "envVar") _opt.piholeConfig; + in filter + (envVar: envVar.value != null) + (map + (fragment: { + name = getAttr "envVar" (accessValueOfFragment _opt.piholeConfig fragment); + value = toEnvValue (accessValueOfFragment _cfg.piholeConfig fragment); + }) + _envVarFragments + ) + ; } diff --git a/modules/pihole-container.factory.nix b/modules/pihole-container.factory.nix index 41ffcf7..7802701 100644 --- a/modules/pihole-container.factory.nix +++ b/modules/pihole-container.factory.nix @@ -1,50 +1,12 @@ { piholeFlake, lingerFlake }: { config, pkgs, lib, ... }: with lib; with builtins; let - inherit (import ../lib/util.nix) collectAttrFragments accessValueOfFragment toEnvValue; + inherit (import ../lib/util.nix) extractContainerEnvVars; + inherit (import ../lib/options.nix lib) mkContainerEnvOption mkHostPortsOption; cfg = config.services.pihole; hostUserCfg = config.users.users.${cfg.hostConfig.user}; systemTimeZone = config.time.timeZone; defaultPiholeVolumesDir = "${config.users.users.${cfg.hostConfig.user}.home}/pihole-volumes"; - mkContainerEnvOption = { envVar, ... }@optionAttrs: - (mkOption (removeAttrs optionAttrs [ "envVar" ])) - // { inherit envVar; }; - - mkHostPortsOption = { service, publicDefaultPort }: { - hostInternalPort = mkOption { - type = types.port; - description = '' - The internal port on the host on which the ${service} port of the pihole container should be exposed. - Only needs to be specified if he container port should be exposed - or if the port-forwarding for this service is enabled. - - As the pihole container is running rootless this cannot be a privileged port (<1024). - ''; - }; - - hostPublicPort = mkOption { - type = types.port; - description = '' - The public port on the host on which the ${service} port of the pihole container should be forwared to. - - This option can be used to together with the according `forwardPublicToInternal` to expose a pihole subservice on a privileged port, - e.g., if you want to expose the DNS service on port 53. - ''; - default = publicDefaultPort; - }; - - forwardPublicToInternal = mkOption { - type = types.bool; - description = '' - Enable port-forwarding between the public & the internal port of the host. - This effectively makes pihole's ${service} port available on the network to which the host is connected to. - - Use this option together with the according `hostPublicPort` to expose a pihole subservice on a privileged port. - ''; - default = false; - }; - }; - in rec { options = { services.pihole = { @@ -113,7 +75,7 @@ in rec { }; - piholeConfiguration = { + piholeConfig = { tz = mkContainerEnvOption { type = types.str; description = "Set your timezone to make sure logs rotate at local midnight instead of at UTC midnight."; @@ -334,20 +296,7 @@ in rec { path = [ "/run/wrappers" ]; serviceConfig = let - opt = options.services.pihole; - - containerEnvVars = let - envVarFragments = collectAttrFragments (value: isAttrs value && value ? "envVar") opt.piholeConfiguration; - in filter - (envVar: envVar.value != null) - (map - (fragment: { - name = getAttr "envVar" (accessValueOfFragment opt.piholeConfiguration fragment); - value = toEnvValue (accessValueOfFragment cfg.piholeConfiguration fragment); - }) - envVarFragments - ) - ; + containerEnvVars = extractContainerEnvVars options.services.pihole cfg; in { ExecStartPre = mkIf cfg.hostConfig.persistVolumes [ "${pkgs.coreutils}/bin/mkdir -p ${cfg.hostConfig.volumesPath}/etc-pihole"