trust-dns: port to dyn-dns for determining WAN IP
although the systemd wantedBy directive is working, `before` seems to be ignored when the unit fails. so on first run, dyn-dns runs, fails (poor net connectivity), then trust-dns starts (fails), then they both restart 10s later. it's not great, but good enough. also, wan IP is persisted, so this likely won't happen much in practice.
This commit is contained in:
parent
3122334a41
commit
97044bf70e
|
@ -49,62 +49,21 @@
|
|||
"/var/lib/trust-dns/native.uninsane.org.zone"
|
||||
];
|
||||
|
||||
systemd.services.ddns-trust-dns = {
|
||||
description = "update dynamic DNS entries for self-hosted trust-dns";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "trust-dns.service" ];
|
||||
restartTriggers = [(
|
||||
builtins.toJSON config.sane.services.trust-dns
|
||||
)];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = let
|
||||
check-ip = "${pkgs.sane-scripts}/bin/sane-ip-check-router-wan";
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
zone-dir = "/var/lib/trust-dns";
|
||||
zone-out = "${zone-dir}/native.uninsane.org.zone";
|
||||
diff = "${pkgs.diffutils}/bin/diff";
|
||||
systemctl = "${pkgs.systemd}/bin/systemctl";
|
||||
zone-template = pkgs.writeText "native.uninsane.org.zone.in" ''
|
||||
@ A %NATIVE%
|
||||
ns1 A %NATIVE%
|
||||
native A %NATIVE%
|
||||
'';
|
||||
in ''
|
||||
set -ex
|
||||
mkdir -p ${zone-dir}
|
||||
ip=$(${check-ip})
|
||||
|
||||
${sed} s/%NATIVE%/$ip/ ${zone-template} > ${zone-out}.new
|
||||
|
||||
# see if anything changed
|
||||
# TODO: instead of diffing, we could `dig` against the actual deployment.
|
||||
# - that could be more resilient to races.
|
||||
touch ${zone-out} # in case it didn't exist yet
|
||||
cp ${zone-out} ${zone-out}.old
|
||||
mv ${zone-out}.new ${zone-out}
|
||||
# if so, restart trust-dns
|
||||
if [ ${diff} -u ${zone-out}.old ${zone-out} ]
|
||||
then
|
||||
echo "zone unchanged. ip: $ip"
|
||||
else
|
||||
echo "zone changed."
|
||||
status=$(${systemctl} is-active trust-dns.service || true)
|
||||
echo $status
|
||||
if [ "$status" = "active" ]
|
||||
then
|
||||
echo "restarting trust-dns."
|
||||
${systemctl} restart trust-dns.service
|
||||
fi
|
||||
fi
|
||||
systemd.services.trust-dns.preStart = let
|
||||
sed = "${pkgs.gnused}/bin/sed";
|
||||
zone-dir = "/var/lib/trust-dns";
|
||||
zone-out = "${zone-dir}/native.uninsane.org.zone";
|
||||
zone-template = pkgs.writeText "native.uninsane.org.zone.in" ''
|
||||
@ A %NATIVE%
|
||||
ns1 A %NATIVE%
|
||||
native A %NATIVE%
|
||||
'';
|
||||
};
|
||||
in ''
|
||||
# make WAN records available to trust-dns
|
||||
mkdir -p ${zone-dir}
|
||||
ip=$(cat '${config.sane.services.dyn-dns.ipPath}')
|
||||
${sed} s/%NATIVE%/$ip/ ${zone-template} > ${zone-out}
|
||||
'';
|
||||
|
||||
systemd.timers.ddns-trust-dns = {
|
||||
# wantedBy = [ "multi-user.target" ];
|
||||
wantedBy = [ "trust-dns.service" ];
|
||||
timerConfig = {
|
||||
OnStartupSec = "10min";
|
||||
OnUnitActiveSec = "10min";
|
||||
};
|
||||
};
|
||||
sane.services.dyn-dns.restartOnChange = [ "trust-dns.service" ];
|
||||
}
|
||||
|
|
|
@ -41,32 +41,39 @@ in
|
|||
config = mkIf cfg.enable {
|
||||
systemd.services.dyn-dns = {
|
||||
description = "update this host's record of its WAN IP";
|
||||
after = [ "network.target" ];
|
||||
restartTriggers = [(builtins.toJSON cfg)];
|
||||
serviceConfig.Type = "oneshot";
|
||||
restartTriggers = [(builtins.toJSON cfg)];
|
||||
|
||||
after = [ "network.target" ];
|
||||
wantedBy = cfg.restartOnChange;
|
||||
before = cfg.restartOnChange;
|
||||
|
||||
script = ''
|
||||
mkdir -p $(dirname '${cfg.ipPath}')
|
||||
mkdir -p "$(dirname '${cfg.ipPath}')"
|
||||
newIp=$(${cfg.ipCmd})
|
||||
oldIp=$(cat '${cfg.ipPath}' || true)
|
||||
# systemd path units are triggered on any file write action,
|
||||
# regardless of content change. so only update the file if our IP *actually* changed
|
||||
if [ "$newIp" != "$(cat '${cfg.ipPath}')" ]
|
||||
if [ "$newIp" != "$oldIp" ]
|
||||
then
|
||||
echo "$newIp" > '${cfg.ipPath}'
|
||||
echo "WAN ip changed $oldIp -> $newIp"
|
||||
fi
|
||||
exit $(test -f '${cfg.ipPath}')
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.timers.dyn-dns = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# if anything wants dyn-dns.service, they surely want the timer too.
|
||||
wantedBy = [ "dyn-dns.service" ];
|
||||
timerConfig = {
|
||||
OnStartupSec = cfg.interval;
|
||||
OnUnitActiveSec = cfg.interval;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.paths.dyn-dns-watcher = {
|
||||
before = [ "dyn-dns.service" ];
|
||||
wantedBy = [ "dyn-dns.service" ];
|
||||
before = [ "dyn-dns.timer" ];
|
||||
wantedBy = [ "dyn-dns.timer" ];
|
||||
pathConfig = {
|
||||
Unit = "dyn-dns-reactor.service";
|
||||
PathChanged = [ cfg.ipPath ];
|
||||
|
|
|
@ -137,8 +137,6 @@ in
|
|||
RestartSec = "10s";
|
||||
# TODO: hardening (like, don't run as root!)
|
||||
};
|
||||
wants = [ "ddns-trust-dns.service" "ddns-trust-dns.timer" ];
|
||||
# XXX: can't be after ddns-trust-dns.service, because the latter `restarts` this one -- *before* it's done activating.
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user