1 { config, lib, pkgs, ... }:
3 cfg = config.services.inadyn;
5 # check if a value of an attrset is not null or an empty collection
6 nonEmptyValue = _: v: v != null && v != [ ] && v != { };
9 if builtins.elem k [ "provider" "custom" ] then
10 lib.concatStringsSep "\n"
14 ${lib.concatStringsSep "\n " (lib.mapAttrsToList renderOption (lib.filterAttrs nonEmptyValue config))}
17 else if k == "include" then
19 else if k == "hostname" && builtins.isList v then
20 "${k} = { ${builtins.concatStringsSep ", " (map (s: "\"${s}\"") v)} }"
21 else if builtins.isBool v then
22 "${k} = ${lib.boolToString v}"
23 else if builtins.isString v then
26 "${k} = ${toString v}";
28 configFile' = pkgs.writeText "inadyn.conf"
30 # This file was generated by nix
33 ${(lib.concatStringsSep "\n" (lib.mapAttrsToList renderOption (lib.filterAttrs nonEmptyValue cfg.settings)))}
36 configFile = if (cfg.configFile != null) then cfg.configFile else configFile';
39 options.services.inadyn = with lib.types;
43 include = lib.mkOption {
45 description = "File to include additional settings for this provider from.";
50 description = "Whether to use HTTPS for this DDNS provider.";
53 username = lib.mkOption {
55 description = "Username for this DDNS provider.";
58 password = lib.mkOption {
61 Password for this DDNS provider.
63 WARNING: This will be world-readable in the nix store.
64 To store credentials securely, use the `include` or `configFile` options.
68 hostname = lib.mkOption {
70 example = "your.cool-domain.com";
71 description = "Hostname alias(es).";
72 type = either str (listOf str);
77 enable = lib.mkEnableOption (''
78 synchronise your machine's IP address with a dynamic DNS provider using inadyn
84 User account under which inadyn runs.
87 If left as the default value this user will automatically be created
88 on system activation, otherwise you are responsible for
89 ensuring the user exists before the inadyn service starts.
93 group = lib.mkOption {
97 Group account under which inadyn runs.
100 If left as the default value this user will automatically be created
101 on system activation, otherwise you are responsible for
102 ensuring the user exists before the inadyn service starts.
106 interval = lib.mkOption {
107 default = "*-*-* *:*:00";
109 How often to check the current IP.
110 Uses the format described in {manpage}`systemd.time(7)`";
114 logLevel = lib.mkOption {
115 type = lib.types.enum [ "none" "err" "warning" "info" "notice" "debug" ];
117 description = "Set inadyn's log level.";
119 settings = lib.mkOption {
121 description = "See `inadyn.conf (5)`";
123 freeformType = attrs;
125 allow-ipv6 = lib.mkOption {
126 default = config.networking.enableIPv6;
127 defaultText = "`config.networking.enableIPv6`";
128 description = "Whether to get IPv6 addresses from interfaces.";
131 forced-update = lib.mkOption {
133 description = "Duration (in seconds) after which an update is forced.";
134 type = ints.positive;
136 provider = lib.mkOption {
139 Settings for DDNS providers built-in to inadyn.
141 For a list of built-in providers, see `inadyn.conf (5)`.
143 type = attrsOf (submodule {
144 freeformType = attrs;
145 options = providerOptions;
148 custom = lib.mkOption {
151 Settings for custom DNS providers.
153 type = attrsOf (submodule {
154 freeformType = attrs;
155 options = providerOptions // {
156 ddns-server = lib.mkOption {
157 description = "DDNS server name.";
160 ddns-path = lib.mkOption {
164 See `inadnyn.conf (5)` for a list for format specifiers that can be used.
166 example = "/update?user=%u&password=%p&domain=%h&myip=%i";
175 configFile = lib.mkOption {
178 Configuration file for inadyn.
180 Setting this will override all other configuration options.
182 Passed to the inadyn service using LoadCredential.
188 config = lib.mkIf cfg.enable {
191 description = "Update nameservers using inadyn";
195 "file:${pkgs.inadyn}/share/doc/inadyn/README.md"
197 requires = [ "network-online.target" ];
198 wantedBy = [ "multi-user.target" ];
199 startAt = cfg.interval;
202 ExecStart = ''${lib.getExe pkgs.inadyn} -f ${configFile} --cache-dir ''${CACHE_DIRECTORY} -1 --foreground -l ${cfg.logLevel}'';
203 LoadCredential = "config:${configFile}";
204 CacheDirectory = "inadyn";
209 LockPersonality = true;
210 MemoryDenyWriteExecute = true;
211 RestrictAddressFamilies = "AF_INET AF_INET6 AF_NETLINK";
212 NoNewPrivileges = true;
213 PrivateDevices = true;
216 ProtectSystem = "strict";
217 ProtectProc = "invisible";
220 ProtectControlGroups = true;
221 ProtectHostname = true;
222 ProtectKernelLogs = true;
223 ProtectKernelModules = true;
224 ProtectKernelTunables = true;
225 RestrictNamespaces = true;
226 RestrictRealtime = true;
227 RestrictSUIDSGID = true;
228 SystemCallArchitectures = "native";
229 SystemCallErrorNumber = "EPERM";
230 SystemCallFilter = "@system-service";
231 CapabilityBoundingSet = "";
235 timers.inadyn.timerConfig.Persistent = true;
238 users.users.inadyn = lib.mkIf (cfg.user == "inadyn") {
243 users.groups = lib.mkIf (cfg.group == "inadyn") {