diff options
author | Sandro <sandro.jaeckel@gmail.com> | 2024-04-21 21:38:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-21 21:38:22 +0200 |
commit | 04a3a2a8fe31810fb08db49068d279d86839867a (patch) | |
tree | b2d37210abc79cd888a8e201d9f769813e367396 /nixos/modules | |
parent | 484fa31a403d3593ce9d455d582f842db2ecda57 (diff) | |
parent | 121490461b1c4228bdb2e315e77c1e14a57dc653 (diff) |
Merge pull request #260962 from lunik1/inadyn-module
nixos/inadyn: init
Diffstat (limited to 'nixos/modules')
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/networking/inadyn.nix | 250 |
2 files changed, 251 insertions, 0 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 29c373788c1fe..511d991e919cd 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1012,6 +1012,7 @@ ./services/networking/icecream/daemon.nix ./services/networking/icecream/scheduler.nix ./services/networking/imaginary.nix + ./services/networking/inadyn.nix ./services/networking/inspircd.nix ./services/networking/iodine.nix ./services/networking/iperf3.nix diff --git a/nixos/modules/services/networking/inadyn.nix b/nixos/modules/services/networking/inadyn.nix new file mode 100644 index 0000000000000..5af1ec9c91efe --- /dev/null +++ b/nixos/modules/services/networking/inadyn.nix @@ -0,0 +1,250 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.inadyn; + + # check if a value of an attrset is not null or an empty collection + nonEmptyValue = _: v: v != null && v != [ ] && v != { }; + + renderOption = k: v: + if builtins.elem k [ "provider" "custom" ] then + lib.concatStringsSep "\n" + (mapAttrsToList + (name: config: '' + ${k} ${name} { + ${lib.concatStringsSep "\n " (mapAttrsToList renderOption (filterAttrs nonEmptyValue config))} + }'') + v) + else if k == "include" then + "${k}(\"${v}\")" + else if k == "hostname" && builtins.isList v then + "${k} = { ${builtins.concatStringsSep ", " (map (s: "\"${s}\"") v)} }" + else if builtins.isBool v then + "${k} = ${boolToString v}" + else if builtins.isString v then + "${k} = \"${v}\"" + else + "${k} = ${toString v}"; + + configFile' = pkgs.writeText "inadyn.conf" + '' + # This file was generated by nix + # do not edit + + ${(lib.concatStringsSep "\n" (mapAttrsToList renderOption (filterAttrs nonEmptyValue cfg.settings)))} + ''; + + configFile = if (cfg.configFile != null) then cfg.configFile else configFile'; +in +{ + options.services.inadyn = with types; + let + providerOptions = + { + include = mkOption { + default = null; + description = mdDoc "File to include additional settings for this provider from."; + type = nullOr path; + }; + ssl = mkOption { + default = true; + description = mdDoc "Whether to use HTTPS for this DDNS provider."; + type = bool; + }; + username = mkOption { + default = null; + description = mdDoc "Username for this DDNS provider."; + type = nullOr str; + }; + password = mkOption { + default = null; + description = mdDoc '' + Password for this DDNS provider. + + WARNING: This will be world-readable in the nix store. + To store credentials securely, use the `include` or `configFile` options. + ''; + type = nullOr str; + }; + hostname = mkOption { + default = "*"; + example = "your.cool-domain.com"; + description = mdDoc "Hostname alias(es)."; + type = either str (listOf str); + }; + }; + in + { + enable = mkEnableOption (mdDoc '' + synchronise your machine's IP address with a dynamic DNS provider using inadyn + ''); + user = mkOption { + default = "inadyn"; + type = types.str; + description = lib.mdDoc '' + User account under which inadyn runs. + + ::: {.note} + If left as the default value this user will automatically be created + on system activation, otherwise you are responsible for + ensuring the user exists before the inadyn service starts. + ::: + ''; + }; + group = mkOption { + default = "inadyn"; + type = types.str; + description = lib.mdDoc '' + Group account under which inadyn runs. + + ::: {.note} + If left as the default value this user will automatically be created + on system activation, otherwise you are responsible for + ensuring the user exists before the inadyn service starts. + ::: + ''; + }; + interval = mkOption { + default = "*-*-* *:*:00"; + description = mdDoc '' + How often to check the current IP. + Uses the format described in {manpage}`systemd.time(7)`"; + ''; + type = str; + }; + logLevel = lib.mkOption { + type = lib.types.enum [ "none" "err" "warning" "info" "notice" "debug" ]; + default = "notice"; + description = lib.mdDoc "Set inadyn's log level."; + }; + settings = mkOption { + default = { }; + description = "See `inadyn.conf (5)`"; + type = submodule { + freeformType = attrs; + options = { + allow-ipv6 = mkOption { + default = config.networking.enableIPv6; + defaultText = "`config.networking.enableIPv6`"; + description = mdDoc "Whether to get IPv6 addresses from interfaces."; + type = bool; + }; + forced-update = mkOption { + default = 2592000; + description = mdDoc "Duration (in seconds) after which an update is forced."; + type = ints.positive; + }; + provider = mkOption { + default = { }; + description = mdDoc '' + Settings for DDNS providers built-in to inadyn. + + For a list of built-in providers, see `inadyn.conf (5)`. + ''; + type = attrsOf (submodule { + freeformType = attrs; + options = providerOptions; + }); + }; + custom = mkOption { + default = { }; + description = mdDoc '' + Settings for custom DNS providers. + ''; + type = attrsOf (submodule { + freeformType = attrs; + options = providerOptions // { + ddns-server = mkOption { + description = mdDoc "DDNS server name."; + type = str; + }; + ddns-path = mkOption { + description = mdDoc '' + DDNS server path. + + See `inadnyn.conf (5)` for a list for format specifiers that can be used. + ''; + example = "/update?user=%u&password=%p&domain=%h&myip=%i"; + type = str; + }; + }; + }); + }; + }; + }; + }; + configFile = mkOption { + default = null; + description = mdDoc '' + Configuration file for inadyn. + + Setting this will override all other configuration options. + + Passed to the inadyn service using LoadCredential. + ''; + type = nullOr path; + }; + }; + + config = lib.mkIf cfg.enable { + systemd = { + services.inadyn = { + description = "Update nameservers using inadyn"; + documentation = [ + "man:inadyn" + "man:inadyn.conf" + "file:${pkgs.inadyn}/share/doc/inadyn/README.md" + ]; + requires = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + startAt = cfg.interval; + serviceConfig = { + Type = "oneshot"; + ExecStart = ''${lib.getExe pkgs.inadyn} -f ${configFile} --cache-dir ''${CACHE_DIRECTORY}/inadyn -1 --foreground -l ${cfg.logLevel}''; + LoadCredential = "config:${configFile}"; + CacheDirectory = "inadyn"; + + User = cfg.user; + Group = cfg.group; + UMask = "0177"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK"; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectSystem = "strict"; + ProtectProc = "invisible"; + ProtectHome = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = "@system-service"; + CapabilityBoundingSet = ""; + }; + }; + + timers.inadyn.timerConfig.Persistent = true; + }; + + users.users.inadyn = mkIf (cfg.user == "inadyn") { + group = cfg.group; + isSystemUser = true; + }; + + users.groups = mkIf (cfg.group == "inadyn") { + inadyn = { }; + }; + }; +} |