{ config, pkgs, lib, inputs, ... }: let cfg = config.services.domeneshop-updater; in { # auto domain update # TODO: ensure dns64 does not interfere with this options = with lib; { services.domeneshop-updater.targets = mkOption { type = with types; listOf str; example = [ config.networking.fqdn ]; }; }; config = lib.mkIf (cfg.targets != []) { users.users.domeneshop.isSystemUser = true; users.users.domeneshop.group = "domeneshop"; users.groups.domeneshop = {}; sops.secrets."domeneshop/token".sopsFile = "${inputs.self}/secrets/dns.yaml"; sops.secrets."domeneshop/token".owner = "domeneshop"; sops.secrets."domeneshop/token".group = "domeneshop"; sops.secrets."domeneshop/secret".sopsFile = "${inputs.self}/secrets/dns.yaml"; sops.secrets."domeneshop/secret".owner = "domeneshop"; sops.secrets."domeneshop/secret".group = "domeneshop"; systemd.services.domeneshop-updater = { description = "domene.shop dyndns domain updater"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = let prog = pkgs.writeShellApplication { name = "domeneshop-dyndns-updater.sh"; runtimeInputs = with pkgs; [ curl iproute2 jq ]; text = '' test -s /run/secrets/domeneshop/token || { >&2 echo "ERROR: /run/secrets/domeneshop/token not found!" exit 1 } test -s /run/secrets/domeneshop/secret || { >&2 echo "ERROR: /run/secrets/domeneshop/secret not found!" exit 1 } DOMENESHOP_TOKEN="$( cat /run/secrets/domeneshop/token)" DOMENESHOP_SECRET="$(cat /run/secrets/domeneshop/secret)" # get stable ipv6 addr, fallback to ipv4, fallback to curl default IF=$( ip -6 -json addr show scope global -temporary \ | jq '.[]| select(.ifname|contains("docker")|not) | .addr_info[].local | select(.==null|not)' -r \ | head -n1 ) if [[ -z "$IF" ]]; then IF=$( ip -4 -json addr show scope global -temporary \ | jq '.[]| select(.ifname|contains("docker")|not) | .addr_info[].local | select(.==null|not)' -r \ | head -n1 ) fi if [[ -n "$IF" ]]; then IF="--interface $IF" else IF="" fi ${lib.concatMapStringsSep "\n" (target: '' # shellcheck disable=SC2086 curl $IF https://"$DOMENESHOP_TOKEN":"$DOMENESHOP_SECRET"@api.domeneshop.no/v0/dyndns/update?hostname="${target}" '') cfg.targets} ''; }; in { User = "domeneshop"; Group = "domeneshop"; #DynamicUser = true; # maybe re-enable when sops-nix is in place? ExecStart = "${prog}/bin/domeneshop-dyndns-updater.sh"; PrivateTmp = true; }; }; systemd.timers.domeneshop-updater = let interval = "2h"; in { description = "Update domene.shop every ${interval}"; wantedBy = [ "timers.target" ]; timerConfig = { OnBootSec = "5m"; OnUnitInactiveSec = interval; Unit = "domeneshop-updater.service"; }; }; }; }