2023-06-23 19:56:35 +02:00
|
|
|
{ pkgs, lib, config, ... }:
|
|
|
|
let
|
|
|
|
cfg = config.services.dyndns;
|
|
|
|
in
|
|
|
|
{
|
|
|
|
options.services.dyndns = {
|
|
|
|
enable = lib.mkEnableOption "Update DNS AAAA records via dyndns";
|
|
|
|
|
|
|
|
interface = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Identifier of the network interface to use";
|
|
|
|
};
|
|
|
|
|
|
|
|
domain = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Domain name to update";
|
|
|
|
};
|
|
|
|
|
|
|
|
server = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "DynDNS server name";
|
|
|
|
};
|
|
|
|
|
|
|
|
username = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "Username for DynDNS updates";
|
|
|
|
};
|
|
|
|
|
|
|
|
passwordFile = lib.mkOption {
|
|
|
|
type = lib.types.str;
|
|
|
|
description = "File containing the DynDNS password";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = lib.mkIf cfg.enable {
|
2023-06-23 21:33:42 +02:00
|
|
|
systemd.services.dyndns = let
|
|
|
|
stateDirectory = "dyndns";
|
|
|
|
homeDirectory = "/var/lib/${stateDirectory}";
|
|
|
|
in
|
|
|
|
{
|
2023-06-23 19:56:35 +02:00
|
|
|
enable = true;
|
|
|
|
after = [ "network.target" ];
|
|
|
|
unitConfig = {
|
|
|
|
Description = "Update AAAA records for ${cfg.domain} via DynDNS";
|
|
|
|
};
|
|
|
|
serviceConfig = {
|
|
|
|
DynamicUser = true;
|
|
|
|
PrivateTmp = true;
|
|
|
|
PrivateDevices = true;
|
|
|
|
ProtectSystem = true;
|
|
|
|
ProtectHome = true;
|
|
|
|
NoNewPrivileges = true;
|
2023-06-23 21:33:42 +02:00
|
|
|
ReadWriteDirectories = [ homeDirectory ];
|
|
|
|
StateDirectory = stateDirectory;
|
2023-06-23 19:56:35 +02:00
|
|
|
};
|
2023-06-23 21:33:42 +02:00
|
|
|
# preStart = ''
|
|
|
|
# #!${pkgs.bash}/bin/bash
|
|
|
|
|
|
|
|
# [ -d "${homeDirectory}" ] || mkdir -p "${homeDirectory}"
|
|
|
|
# '';
|
2023-06-23 19:56:35 +02:00
|
|
|
script = ''
|
|
|
|
#!${pkgs.bash}/bin/bash
|
|
|
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
host="${cfg.domain}"
|
|
|
|
interface="${cfg.interface}"
|
|
|
|
dyndns_server="${cfg.server}"
|
|
|
|
dyndns_user="${cfg.username}"
|
|
|
|
dyndns_password="$(cat "${cfg.passwordFile}")"
|
2023-06-23 21:33:42 +02:00
|
|
|
state_file="${homeDirectory}/current_ipv6"
|
2023-06-23 19:56:35 +02:00
|
|
|
|
|
|
|
new_ip=$(${pkgs.iproute}/bin/ip -6 a show scope global -temporary dev "$interface" | ${pkgs.gnused}/bin/sed -n -E 's/^\ *inet6\ (2001(:[0-9a-f]+)+).*$/\1/p' | head -1)
|
|
|
|
|
|
|
|
if [ -z "$new_ip" ] ; then
|
|
|
|
echo "Could not determine IP address."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-06-23 21:33:42 +02:00
|
|
|
if [ ! -f "$state_file" ] ; then
|
|
|
|
echo "No state file found, determining currently set IP via DNS query."
|
|
|
|
${pkgs.dig}/bin/dig aaaa +short "$host" > "$state_file"
|
|
|
|
fi
|
|
|
|
|
|
|
|
current_ip=$(cat "$state_file")
|
2023-06-23 19:56:35 +02:00
|
|
|
|
|
|
|
if [ -z "$current_ip" ] ; then
|
|
|
|
echo "Could not determine current AAAA record."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ "$current_ip" = "$new_ip" ] ; then
|
|
|
|
echo "Current AAAA record is already $current_ip, no update needed."
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "Updating IP to $new_ip."
|
|
|
|
${pkgs.curl}/bin/curl "https://$dyndns_user:$dyndns_password@$dyndns_server/?hostname=$host&myip=$new_ip"
|
2023-06-23 21:33:42 +02:00
|
|
|
|
|
|
|
echo "$new_ip" > "$state_file"
|
2023-06-23 19:56:35 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
systemd.timers.dyndns = {
|
|
|
|
description = "Timer for triggering DynDNS updates";
|
|
|
|
wantedBy = [ "timers.target" ];
|
|
|
|
timerConfig = {
|
|
|
|
OnBootSec = "2min";
|
|
|
|
OnUnitActiveSec = "20min";
|
|
|
|
Unit = "dyndns.service";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|