Skip to content

Commit f4965ae

Browse files
committed
wait for LocalLeaseDomain to be upstreamed
1 parent 180f3fd commit f4965ae

1 file changed

Lines changed: 65 additions & 2 deletions

File tree

nix/dns-module.nix

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ in
8787
config =
8888
let
8989
acme-dir = "/var/lib/xnode-dns/acme";
90+
leases-dir = "/var/lib/systemd/network/dhcp-server-lease";
91+
dns-dir = "/var/lib/xnode-dns/container";
9092
in
9193
lib.mkIf cfg.enable {
9294
users.groups.xnode-dns = { };
@@ -119,7 +121,10 @@ in
119121
allow net 127.0.0.1 ::1
120122
block
121123
}
122-
forward . 127.0.0.1:5353
124+
auto {
125+
directory ${dns-dir}
126+
reload 10s
127+
}
123128
}
124129
'';
125130
};
@@ -172,9 +177,67 @@ in
172177
};
173178
dhcpServerConfig = {
174179
PersistLeases = "runtime";
175-
LocalLeaseDomain = cfg.container.domain;
176180
};
177181
};
178182
};
183+
184+
systemd.paths.dns-sync-container-leases = {
185+
wantedBy = [ "multi-user.target" ];
186+
description = "Trigger sync script on lease change.";
187+
pathConfig = {
188+
PathChanged = leases-dir;
189+
};
190+
};
191+
systemd.services.dns-sync-container-leases = {
192+
description = "Sync container DHCP leases with the DNS server.";
193+
serviceConfig = {
194+
Restart = "on-failure";
195+
};
196+
path = [
197+
pkgs.jq
198+
];
199+
script = ''
200+
mkdir -p ${dns-dir}
201+
setfacl -R -m g:xnode-dns:r ${dns-dir}
202+
203+
# Function to generate zone file content
204+
generate_zone() {
205+
local hostname="$1"
206+
local ip="$2"
207+
cat <<EOF
208+
$ORIGIN ''${hostname}.${cfg.container.domain}.
209+
@ 3600 IN SOA ${cfg.soa.nameserver}. ${
210+
builtins.replaceStrings [ "@" ] [ "." ] cfg.soa.mailbox
211+
}. $(date +"%y%d%m%H%M") ${cfg.soa.refresh} ${cfg.soa.retry} ${cfg.soa.expire} ${cfg.soa.minimumTTL}
212+
@ 60 IN A ''${ip}
213+
EOF
214+
}
215+
216+
# Process each lease file
217+
for filepath in ${leases-dir}/*; do
218+
# Skip if not a file
219+
[ -f "$filepath" ] || continue
220+
221+
# Try to parse JSON
222+
leases=$(jq -c '.Leases[]?' "$filepath" 2>/dev/null)
223+
if [ -z "$leases" ]; then
224+
echo "Skipping $filepath: invalid JSON or no leases"
225+
continue
226+
fi
227+
228+
# Iterate over leases
229+
echo "$leases" | while read -r lease; do
230+
hostname=$(echo "$lease" | jq -r '.Hostname // empty')
231+
ip=$(echo "$lease" | jq -r '.Address | join(".") // empty')
232+
233+
if [ -n "$hostname" ] && [ -n "$ip" ]; then
234+
out_path="${dns-dir}/db.''${hostname}.${cfg.container.domain}"
235+
generate_zone "$hostname" "$ip" > "$out_path"
236+
echo "Generated zone file: $out_path"
237+
fi
238+
done
239+
done
240+
'';
241+
};
179242
};
180243
}

0 commit comments

Comments
 (0)