summaryrefslogtreecommitdiff
path: root/hosts/vidhar/network/dhcp/default.nix
diff options
context:
space:
mode:
Diffstat (limited to 'hosts/vidhar/network/dhcp/default.nix')
-rw-r--r--hosts/vidhar/network/dhcp/default.nix264
1 files changed, 264 insertions, 0 deletions
diff --git a/hosts/vidhar/network/dhcp/default.nix b/hosts/vidhar/network/dhcp/default.nix
new file mode 100644
index 00000000..ccc22c7f
--- /dev/null
+++ b/hosts/vidhar/network/dhcp/default.nix
@@ -0,0 +1,264 @@
1{ flake, config, pkgs, lib, ... }:
2{
3 config = {
4 services.kea = {
5 dhcp4 = {
6 enable = true;
7 settings = {
8 valid-lifetime = 4000;
9 rebind-timer = 2000;
10 renew-timer = 1000;
11
12 interfaces-config = {
13 interfaces = [ "lan" "mgmt" ];
14 };
15
16 lease-database = {
17 name = "/var/lib/kea/dhcp4.leases";
18 persist = true;
19 type = "memfile";
20 };
21
22 client-classes = [
23 { name = "ipxe";
24 test = "option[77].hex == 'iPXE'";
25 next-server = "10.141.0.1";
26 boot-file-name = "netboot.ipxe";
27 only-if-required = true;
28 }
29 { name = "uefi-64";
30 test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:00007' or substring(option[60].hex,0,20) == 'PXEClient:Arch:00008' or substring(option[60].hex,0,20) == 'PXEClient:Arch:00009'";
31 only-if-required = true;
32 option-data = [
33 { name = "tftp-server-name"; data = "10.141.0.1"; }
34 ];
35 boot-file-name = "ipxe.efi";
36 }
37 { name = "uefi-32";
38 test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:00002' or substring(option[60].hex,0,20) == 'PXEClient:Arch:00006'";
39 only-if-required = true;
40 option-data = [
41 { name = "tftp-server-name"; data = "10.141.0.1"; }
42 ];
43 boot-file-name = "i386-ipxe.efi";
44 }
45 { name = "legacy";
46 test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:00000'";
47 only-if-required = true;
48 option-data = [
49 { name = "tftp-server-name"; data = "10.141.0.1"; }
50 ];
51 boot-file-name = "undionly.kpxe";
52 }
53 ];
54
55 dhcp-ddns.enable-updates = true;
56 ddns-send-updates = false;
57 ddns-override-client-update = true;
58 ddns-override-no-update = true;
59 ddns-replace-client-name = "when-not-present";
60 ddns-generated-prefix = "noname";
61 ddns-update-on-renew = true;
62
63 subnet4 = [
64 { subnet = "10.141.0.0/24";
65 option-data = [
66 { name = "domain-name-servers";
67 data = "10.141.0.1";
68 }
69 { name = "broadcast-address";
70 data = "10.141.0.255";
71 }
72 { name = "routers";
73 data = "10.141.0.1";
74 }
75 { name = "domain-name";
76 data = "yggdrasil";
77 }
78 { name = "domain-search";
79 data = "lan.yggdrasil, yggdrasil";
80 }
81 ];
82 ddns-send-updates = true;
83 ddns-qualifying-suffix = "lan.yggdrasil";
84 pools = [ { pool = "10.141.0.128 - 10.141.0.254"; } ];
85 require-client-classes = ["ipxe" "uefi-64" "uefi-32" "legacy"];
86 reservations = [
87 { hostname = "sif";
88 hw-address = "3c:e1:a1:52:24:35";
89 }
90 { hostname = "sif";
91 hw-address = "ee:32:68:76:83:ac";
92 }
93 { hostname = "sif";
94 hw-address = "48:2a:e3:64:62:97";
95 }
96 { hostname = "eos";
97 hw-address = "00:d8:61:79:c5:40";
98 }
99 ];
100 }
101 { subnet = "10.141.1.0/24";
102 option-data = [
103 { name = "domain-name-servers";
104 data = "10.141.1.1";
105 }
106 { name = "broadcast-address";
107 data = "10.141.1.255";
108 }
109 { name = "domain-name";
110 data = "yggdrasil";
111 }
112 { name = "domain-search";
113 data = "mgmt.yggdrasil, yggdrasil";
114 }
115 ];
116 ddns-send-updates = true;
117 ddns-qualifying-suffix = "mgmt.yggdrasil";
118 pools = [ { pool = "10.141.1.128 - 10.141.1.254"; } ];
119 reservations = [
120 { hostname = "switch01";
121 hw-address = "60:a4:b7:53:94:b5";
122 ip-address = "10.141.1.2";
123 }
124 { hostname = "ap01";
125 hw-address = "74:ac:b9:29:ad:9a";
126 ip-address = "10.141.1.4";
127 }
128 ];
129 }
130 { subnet = "10.141.2.0/24";
131 option-data = [
132 { name = "domain-name-servers";
133 data = "10.141.2.1";
134 }
135 { name = "broadcast-address";
136 data = "10.141.2.255";
137 }
138 { name = "routers";
139 data = "10.141.2.1";
140 }
141 ];
142 ddns-send-updates = false;
143 pools = [ { pool = "10.141.2.128 - 10.141.2.254"; } ];
144 reservations = [];
145 }
146 ];
147 };
148 };
149 dhcp6 = {
150 enable = true;
151 settings = {
152 interfaces-config = {
153 interfaces = [ "lan" ];
154 };
155
156 lease-database = {
157 name = "/var/lib/kea/dhcp6.leases";
158 persist = true;
159 type = "memfile";
160 };
161 };
162 };
163 dhcp-ddns = {
164 enable = true;
165 settings = {
166 forward-ddns = {
167 ddns-domains = [
168 { name = "lan.yggdrasil.";
169 dns-servers = [
170 { ip-address = "127.0.0.1";
171 port = 5353;
172 key-name = "local_key";
173 }
174 ];
175 }
176 { name = "mgmt.yggdrasil.";
177 dns-servers = [
178 { ip-address = "127.0.0.1";
179 port = 5353;
180 key-name = "local_key";
181 }
182 ];
183 }
184 ];
185 };
186 reverse-ddns = {
187 ddns-domains = [
188 { name = "0.141.10.in-addr.arpa.";
189 dns-servers = [
190 { ip-address = "127.0.0.1";
191 port = 5353;
192 key-name = "local_key";
193 }
194 ];
195 }
196 { name = "1.141.10.in-addr.arpa.";
197 dns-servers = [
198 { ip-address = "127.0.0.1";
199 port = 5353;
200 key-name = "local_key";
201 }
202 ];
203 }
204 ];
205 };
206 };
207 };
208 };
209
210 systemd.services.kea-dhcp-ddns-server = {
211 preStart = let
212 configLines = [
213 "<?include \"\${CREDENTIALS_DIRECTORY}/knot-tsig.json.frag\"?>"
214 ] ++ lib.mapAttrsToList (k: v:
215 "\"${k}\": ${builtins.toJSON v}"
216 ) config.services.kea.dhcp-ddns.settings;
217
218 config-template = pkgs.writeText "dhcp-ddns.conf" ''
219 {"DhcpDdns": {
220 ${lib.concatStringsSep ",\n " configLines}
221 }}
222 '';
223 in ''
224 ${pkgs.envsubst}/bin/envsubst -i "${config-template}" -o "''${RUNTIME_DIRECTORY}/dhcp-ddns.conf"
225 '';
226
227 serviceConfig = {
228 ExecStart = lib.mkForce ''
229 ${pkgs.kea}/bin/kea-dhcp-ddns -c "''${RUNTIME_DIRECTORY}/dhcp-ddns.conf" ${lib.escapeShellArgs config.services.kea.dhcp-ddns.extraArgs}
230 '';
231 LoadCredential = [
232 "knot-tsig.json.frag:${config.sops.secrets."kea-knot-tsig.json.frag".path}"
233 ];
234 };
235 };
236
237 sops.secrets."kea-knot-tsig.json.frag" = {
238 format = "binary";
239 sopsFile = ./knot-tsig.json.frag;
240 };
241
242 systemd.services."installer-atftpd" = {
243 description = "TFTP Server for PXE Booting NixOS Installer";
244 after = [ "network.target" ];
245 wantedBy = [ "multi-user.target" ];
246 serviceConfig.ExecStart = let
247 installerBuild = flake.nixosConfigurations.installer-x86_64-linux-netboot.config.system.build;
248 ipxe = pkgs.ipxe.override {
249 additionalTargets = {
250 "bin-i386-efi/ipxe.efi" = "i386-ipxe.efi";
251 };
252 };
253 tftpRoot = pkgs.runCommandLocal "installer-netboot" {} ''
254 mkdir -p $out
255 install -m 0444 -t $out \
256 ${installerBuild.netbootRamdisk}/initrd \
257 ${installerBuild.kernel}/bzImage \
258 ${installerBuild.netbootIpxeScript}/netboot.ipxe \
259 ${ipxe}/ipxe.efi ${ipxe}/i386-ipxe.efi ${ipxe}/undionly.kpxe
260 '';
261 in "${pkgs.atftp}/sbin/atftpd --daemon --no-fork --bind-address=10.141.0.1 ${tftpRoot}";
262 };
263 };
264}