{ config, lib, pkgs, ... }: let inherit (lib) getExe literalExpression mkEnableOption mkIf mkOption types ; cfg = config.services.ddnnss; ddnnss = pkgs.callPackage ./package.nix { }; configFile = pkgs.writeText "ddnnss.json" (builtins.toJSON cfg.settings); in { options.services.ddnnss = { enable = mkEnableOption "ddnnss"; interval = mkOption { type = types.str; default = "5min"; description = '' How often to run an update cycle. ''; }; settings = mkOption { type = types.attrs; description = '' The ddnnss configuration. Any key values expand environment variables. ''; example = literalExpression '' { records = [{ zone = "rnrd.eu"; name = "silly"; type = "AAAA"; provider = "bunny-rnrd"; source = "icanhazip"; }]; providers.bunny-rnrd = { kind = "bunny"; keyFile = "$CREDENTIALS_DIRECTORY/bunny-dns"; }; sources.icanhazip = { kind = "icanhazip"; }; } ''; }; credentials = mkOption { type = types.attrsOf types.path; default = { }; description = '' Secrets exposed to ddnnss during the cycle, as systemd credentials. ''; example = literalExpression '' { bunny-dns = config.age.secrets.bunny-dns.path; } ''; }; }; config = mkIf cfg.enable { systemd.services.ddnnss = { description = "ddnnss dynamic dns update cycle"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; DynamicUser = true; LoadCredential = lib.mapAttrsToList (name: path: "${name}:${path}") cfg.credentials; ExecStart = "${getExe ddnnss} -config ${configFile}"; }; }; systemd.timers.ddnnss = { wantedBy = [ "timers.target" ]; timerConfig = { # wait 2 minutes from the start, with 30 second jitter. OnBootSec = "2min"; RandomizedDelaySec = "30s"; OnUnitActiveSec = cfg.interval; }; }; }; }