Skip to content

Commit 9bc05b6

Browse files
committed
wait for PersistLeases and LocalLeaseDomain to be upstreamed
1 parent 180f3fd commit 9bc05b6

1 file changed

Lines changed: 65 additions & 5 deletions

File tree

nix/dns-module.nix

Lines changed: 65 additions & 5 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
};
@@ -170,11 +175,66 @@ in
170175
IPv6AcceptRA = "no";
171176
IPv6SendRA = "yes";
172177
};
173-
dhcpServerConfig = {
174-
PersistLeases = "runtime";
175-
LocalLeaseDomain = cfg.container.domain;
176-
};
177178
};
178179
};
180+
181+
systemd.paths.dns-sync-container-leases = {
182+
wantedBy = [ "multi-user.target" ];
183+
description = "Trigger sync script on lease change.";
184+
pathConfig = {
185+
PathChanged = leases-dir;
186+
};
187+
};
188+
systemd.services.dns-sync-container-leases = {
189+
description = "Sync container DHCP leases with the DNS server.";
190+
serviceConfig = {
191+
Restart = "on-failure";
192+
};
193+
path = [
194+
pkgs.jq
195+
];
196+
script = ''
197+
mkdir -p ${dns-dir}
198+
setfacl -R -m g:xnode-dns:r ${dns-dir}
199+
200+
# Function to generate zone file content
201+
generate_zone() {
202+
local hostname="$1"
203+
local ip="$2"
204+
cat <<EOF
205+
$ORIGIN ''${hostname}.${cfg.container.domain}.
206+
@ 3600 IN SOA ${cfg.soa.nameserver}. ${
207+
builtins.replaceStrings [ "@" ] [ "." ] cfg.soa.mailbox
208+
}. $(date +"%y%d%m%H%M") ${cfg.soa.refresh} ${cfg.soa.retry} ${cfg.soa.expire} ${cfg.soa.minimumTTL}
209+
@ 60 IN A ''${ip}
210+
EOF
211+
}
212+
213+
# Process each lease file
214+
for filepath in ${leases-dir}/*; do
215+
# Skip if not a file
216+
[ -f "$filepath" ] || continue
217+
218+
# Try to parse JSON
219+
leases=$(jq -c '.Leases[]?' "$filepath" 2>/dev/null)
220+
if [ -z "$leases" ]; then
221+
echo "Skipping $filepath: invalid JSON or no leases"
222+
continue
223+
fi
224+
225+
# Iterate over leases
226+
echo "$leases" | while read -r lease; do
227+
hostname=$(echo "$lease" | jq -r '.Hostname // empty')
228+
ip=$(echo "$lease" | jq -r '.Address | join(".") // empty')
229+
230+
if [ -n "$hostname" ] && [ -n "$ip" ]; then
231+
out_path="${dns-dir}/db.''${hostname}.${cfg.container.domain}"
232+
generate_zone "$hostname" "$ip" > "$out_path"
233+
echo "Generated zone file: $out_path"
234+
fi
235+
done
236+
done
237+
'';
238+
};
179239
};
180240
}

0 commit comments

Comments
 (0)