hosts/options/dyndns.nix

113 lines
3.7 KiB
Nix
Raw Permalink Normal View History

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";
};
2023-08-26 11:11:12 +02:00
domains = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Domain names to update";
2023-06-23 19:56:35 +02:00
};
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 {
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 = {
2023-08-26 11:11:12 +02:00
Description = "Update AAAA records via DynDNS";
2023-06-23 19:56:35 +02:00
};
serviceConfig = {
DynamicUser = true;
PrivateTmp = true;
PrivateDevices = true;
ProtectSystem = true;
ProtectHome = true;
NoNewPrivileges = true;
ReadWriteDirectories = [ homeDirectory ];
StateDirectory = stateDirectory;
2023-06-23 19:56:35 +02:00
};
script = ''
#!${pkgs.bash}/bin/bash
set -eu
interface="${cfg.interface}"
dyndns_server="${cfg.server}"
dyndns_user="${cfg.username}"
dyndns_password="$(cat "${cfg.passwordFile}")"
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-08-26 11:11:12 +02:00
for host in ${builtins.concatStringsSep " " cfg.domains} ; do
echo "Checking $host."
2023-08-26 11:11:12 +02:00
state_file="${homeDirectory}/current_ipv6_$host"
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
2023-06-23 19:56:35 +02:00
2023-08-26 11:11:12 +02:00
current_ip=$(cat "$state_file")
2023-06-23 19:56:35 +02:00
2023-08-26 11:11:12 +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."
continue
fi
2023-06-23 19:56:35 +02:00
2023-08-26 11:11:12 +02:00
echo "Updating IP to $new_ip."
${pkgs.curl}/bin/curl "https://$dyndns_user:$dyndns_password@$dyndns_server/?hostname=$host&myip=$new_ip"
2023-08-26 11:11:12 +02:00
echo "$new_ip" > "$state_file"
done
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";
};
};
};
}