From b491abe06561dc96394ea9c2670a2c549c5dca5d Mon Sep 17 00:00:00 2001 From: javalsai Date: Sun, 3 May 2026 19:32:39 +0200 Subject: [PATCH] nixos/services: make dns configuration easier --- agenix/dns/tuxcord.net/tuxcord.net.key.age | Bin 0 -> 536 bytes .../dns/tuxcord.test/sub.tuxcord.test.key.age | 34 +++++ agenix/dns/tuxcord.test/tuxcord.test.key.age | Bin 0 -> 1898 bytes agenix/ntfy.age | 47 ++++--- agenix/secrets.nix | 9 +- nixos/common.nix | 8 -- nixos/hosts/tuxcord-ca/default.nix | 1 + nixos/hosts/tuxcord-test/default.nix | 1 + nixos/modules/dns.nix | 120 ++++++++++++------ 9 files changed, 155 insertions(+), 65 deletions(-) create mode 100644 agenix/dns/tuxcord.net/tuxcord.net.key.age create mode 100644 agenix/dns/tuxcord.test/sub.tuxcord.test.key.age create mode 100644 agenix/dns/tuxcord.test/tuxcord.test.key.age diff --git a/agenix/dns/tuxcord.net/tuxcord.net.key.age b/agenix/dns/tuxcord.net/tuxcord.net.key.age new file mode 100644 index 0000000000000000000000000000000000000000..bcc342b7b79b0800286be5de64607805daec46a1 GIT binary patch literal 536 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+&oN4Kaa2flE-ZD) z_RewiDD}(IHcZVmNHTFVH8m`7GxgUu3`olGHcAQ$k8}#JOy}|~4K_-0$}-FIiL&%H z&oOd$Gj#DuPb@Ds$n?n1EzS&fDslJBGxkh2FhRGi%Fo#%*ik{>G0dbyUtixiskoxb z%sn90-^edG#5By=JISXo!!aT%Grc4rFtX6oIh(60*f%dDETY24H!?WO(lIgB(k(;Z z(90sxD>Azv#L=~^Fvv0}#5||O*A?A1*Gxx8?{bB#z`&w3&!CKav+$yVDi`0ear z57*#w`S!Xy z@vi+EshM$K_V2lClLUX;9p6?SCFix ssh-ed25519 Wl2fDA ChDpKnwSPrXx13z22y4Q7+E6T+6Jr6pL6ZCxGidDhz4 +VqzsCq9P5KSFRoKu+LR02VwR1qO8tbVyPnOf0dUw0HQ +-> ssh-ed25519 zNC8SA MQvBihnVCRdXg4PdrTZ3mhvzwyJeACVXfPNawPsRMl4 +8HOZLbg9FuKD9k+0lS+3FksXMhLYXVOaa/7zzTgX+jc +-> ssh-ed25519 EiAAKw pxeU5N5J9ItEXP3Q2mOvWEjOe552atnfEMw1m/scbws +kswNWzaK5cKuyWeuRMxizL1tR63IaAbxkT6Yk2hplkc +-> ssh-rsa eFi+Zw +otzKOxpWdae4NnDceLHW6bYlZaXWYb2N2A6PLp6CJ/TRzT4F6aKO9oIG3dyGyVy6 +JYNYDCrqgr0OrJdBB1pADbrhXxlaTlMW3K/5FkhPj4GOJQqYR/7148EHtv721eDi +mqJExC7lbEzO7ZcWT5ohPT8hP2Gv9xcKCRiAVrybo0HR4+tQrYDpr9PTrYy0lTOE +e9Ik3eT3+ub9FdJhgfKaGJVQS9cpuyghXN1AlO0EPTVwiOoYLZ/KSmrV+2hxaaui +KJ7VVjhWrbcFq0zDuZaxS93Ot3MN91TjOTqWewuj/Ahnl/pxOPzsy8zTN0FwkIXh +6dvM21kQQg/r5Lq40yQYxk6HA2vkzZm4PYFbuEegG0XG3CoLcvPme2hWec6fbbL4 +0M3RsIKS5yLNdgtB4r6uzjyqaOO6TYP1Yndb7wd7befwoNkPXBfEfxvChoZEoXCF +/IlFtUqOcZLTLkL+yfqU60RRkvurbZVYtMI7yTpCAKUsMMJoD6ZA49E/1FSVkFxR + +-> ssh-ed25519 QovoLQ P6/XAKtF+DGLR6VhsHV8/LwAacQj4TySaH/A+c7qW1A +NrZTXLxCCDqTV3FHg9P4FyJ+3Up7Nm+Docrv/YKxDYA +-> ssh-rsa OFkEIg +qABFIWIcl7Qq8UXzxwXyVJQRgCxxXWDr4nUyOExxuVZcksDJPHN1VN1lbizEFXtN +eIujZ2PodAuy05NKP0k+BhV9PH7NoXzpgKYD3mVFU8xJo/3gytUgbIg2EHAUmctK +PAwdCbA8hT5T7KZV17hGNEkVjV8h6haRYuKCZIYkwIwFGRC++OqMZSOSB+2iAFSA +QBGQCn835EjE57M+yCOVvSQagqoaimNKx7Idtkjqvx3wOvuy4Px2FxtE4PloW9i2 +zR2NH9NAsGcUA+i8eFO3KKtXFoKm6QsRUPVn0o3nsxDXjYO/OSB6yS7GNjLJSkfO +n+UcKy5/lHNQqtBSLg+OLH0ZSj+nyHX5Dk1Cq+MB0J0KbcXA6XVm6+hhQE5xzegP +RSzgKxmqCEAcSGD4Li4nJJK3bwB971njDVyIaNBRC+7T8zY6h7LIZlB7Bq2SQ3Wb +tsnYHOldgfkkAEqkS8oQzxNMe94BzsfL5/JuPHF5+gx9ljLB1kOk5a0B6YWiVCyE +Iy/PH2ikTa3CYcNOfGnlkfBsk7Sf6C5ZvYaVWrb13Cxh5DZFGg4HIc58pmKkvq4B +o07/I6nA8Dw/j0hX/wtF8h8CsASTkRlu09GIPimV1f3gAALFwmYOEFjSEJ4tE++O +Dz/v5lzBUw7TDYGrylLLerOd+mH5FYl8ai2OFu9dtsE +--- oWcM9irmHBy2/btfhFIoLfsdkQQV1GFY4q0wy3q9h4U +F(BFRQC -%wzJAvCa.,v+EQ{] +ut|t+BP_خ!&fRVCjlj \`/m iYm(ɑ(N&C/ \ No newline at end of file diff --git a/agenix/dns/tuxcord.test/tuxcord.test.key.age b/agenix/dns/tuxcord.test/tuxcord.test.key.age new file mode 100644 index 0000000000000000000000000000000000000000..729524b5ff076e05adc740d5154b33cda64a882e GIT binary patch literal 1898 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCR+&oN4Kaa8a!^^AA18 zq4^fMQB{r^Ro-s7Rj!UXmO*}&-o+IbMTP-po~b3Jp5}h#-cBZ5LFvU2jscOL{t@m0 z$@xW5{@Tge`c5V3LFpxx9@<5DZrK_7sl}G*<`Dr#-Z?IXjyaaa5s?wvDgGhu6{Xrq zT!mF-78dE+LFJ_thS@&m`Dw{Hq28VqRUtl=ekFnCmg%KcWoG#$&Lvsqj!9L%1*uWm zMUjyPK~W(kDVDirK3t(GMOl?zNm<^O1?Kq{`tAlMSstM|xg{xHUM5+E#?B^HsmV!E zVZnJx7WsMR*~zZ%PNA8>CZQD}`K~6}Ub$RGiT;&E!4VObY2J>hx#eMzIfmJxmZ_Qf zkzpSCPC5Q%#*tyBMuBOrPL?Ibk&*rZ?)px~C1nA=t|>v;t{%=@Ng0)f20q^YrBy{C zuKHo=1zv^)CAk^diKe-shNY!ZMk$pQJ{GCj*-2SZ$wrm|sh<9UN!~`8rkU9#hNX$2 zT#2b3nFdaof#sH-9wjbGVMV4+L8iW@9$ETk<&_ap>BW}m+93sg#zv85CFXt>WtmQ< zrd4TqMo})I&Y_{{=3J)knE{>^MfypO5yr`mCE6CQP60{9K^}&FA;uDgIf#>I{$l_5Tr21N$O5fQ$Y!4=LHi8*QIsZPczX8Muld4;Z)nL*he zj%9gKKBioOC256@Zs9(j85t%iSq4Fd+TK$-hL%U z9>L}AuI0hW!NKmvo|P3TQKg|#F8Sq!j(!D6MkQuh$xbG2z9uE!CMMzL5nSPx7G;?Q z89C-rWhr?^#o8A6S>8crIpO-|j-^2!`W}XUl^&MahKYH>ptN6P9%5|lt?wM+pO>5A zFZ$@ zm=l?qmmT7hTcn@nXPRc|@4@Be6qxSpn4Mf`8EEd}>73zh6yO?^lj4|_tX&x5Sr(9! zXyzHIZ)vXWosyJk5gJ(@;$xiQ>*bN7ZRpf%ndjq{<>a2kWszv<7?^7m zXzZVq<7`@}?^fv=pdFayS5+33l$7M>lV_S(nC9u673gSUnr=~I9^~p&p6%&VZjc$2 z5}xQ3&J}7_>1pns6;Wnh?3)?jo)nmumY8cEk`_^5;hW@S?(FFooM;xFmR=r`&!wxY zt6&zM;+LBk7!r`@TbY@W;q6i7SWuW=R8bz96c!d791sxX7UdfnT<+{t&efe8)OmGQ zOKHs3I^|@shP151`|+w|Fb$HT5Syor;(q?NhM?Y^Y! lxv=BZ*?PVz7Eebn{?u^0uRQt;K}QQ2!slk(Z8tl38USFOdkg>o literal 0 HcmV?d00001 diff --git a/agenix/ntfy.age b/agenix/ntfy.age index 27e6cf7..7f5812c 100644 --- a/agenix/ntfy.age +++ b/agenix/ntfy.age @@ -1,17 +1,34 @@ age-encryption.org/v1 --> ssh-ed25519 Wl2fDA JMymqEdh+xJbl8VcL5wg7Y2Dk4667DzNO85RCskX+0Q -ZQqF0eYpvrLujGdIvAMbfwPnKGa+mfNvAhHGMdXiYaI --> ssh-ed25519 zNC8SA UCQhQA4f3OiNoxejDBMabnls3LjS0GQmvIqPpjB/FH8 -0qvv6W1heZiE1DDYEj1U5N2e99DZLxlJ6A8EoZ31DhM --> ssh-rsa 3G83yA -Gnpw8t6njIXGm98jTS47Afx6TogPnIJP59rapF0CkYkDXZNrW7WK+fcERHLN2+a+ -PSkjwkql3LfAtCNqrIJZwWLj/URnKQF5N3ZKwOa1+wsM3GeUzjvaQwPZunj4jyFs -IJlL+ika2sBk/HvOa1r6ntj2cvLM1fIhbs9bOEZW3br3M3sfXk386TgrytqzM248 -3xS2iIwIBmBiI5Xem8KO2+J/2Vk9Px/ZPkBpdIAaZAmihe3g/VWNKHhXrwdM9ZA7 -tHgw5ohK8ug88ep9XCIFD75DPeK/60wqAdkGs4PE6THcsKqhN061TAEq3SWRl8wp -Kd17yAzHDLhsbdWXT/Q912Y4YJCB3TnD0MFGzPF7sks2NknB6yowwjnCGlqzf5rW -RBKHp6PTM+x/eDi89vS+uIBtyGFaFU7wBTl4FzJpKoOsRIDYNktGkJSxdTzrMO1n -XqXtJtqZaXN7UExA+ko9ln446I7RG8c3hNGx4A4bR1xUEUE8WD/TMhjzrbzysYSl +-> ssh-ed25519 Wl2fDA dM0TgKtswZcbEV9tGGY26YCksV2xadHWXv7D/KksAWk +1vCcuHmVP2xiHd/7hh0z2Hiq/EeA8uvdsRtQReC5hNY +-> ssh-ed25519 zNC8SA uTO/3ePjgiKqk3jeRGZX5D3LjzhSBlp2rD2ZakKmfX0 +tVkEEcP/KfD9x52l7iz5F3hKK0LSckjXWK5YP2aeBt4 +-> ssh-ed25519 EiAAKw Etu0I4IzJ3BB2SzCeiexx+dhcLUO5d2Ws+WiJyLk/Sw +9GBcZPsIXO3mXbri3lFYjtBBu0wFYul6hKsCvBKVLFs +-> ssh-rsa eFi+Zw +uOZsBC+IMHdX2h9Jq/CF/L3BsxDW+dULk04JQbDeM85Mrxxdrv2X3w7AW8YU2KS+ +Xg8LnzH01z4Nfs89uysM/lsWptc9qMeaK9o0oHC+tSJH4Ch43MejbmFYjFibHaCm +krQM7dAGIJwc/o0+ykaCrbXSvXAyfd6Nw1izou2ZcDRI7mTipOZO8F949SIk//Rc +UJgPLqpGwScEfrHf4f6tySC4LmD0bPIV1xDpmmXcS7c83E9+iVOtb5Y1In6CQrF1 +XZQCb9MkPySbuicwR022CySb+lc7Ru44RdqBgV1e+wphyZCoqCk09i18egV3hNs6 +iEul3M8dqV27yRKrWIUD5jT2tUszTNJfreiuZl9eDmLkcVWExkWzqWPUFJ48hQiZ +89Z4Evn04vZGoeL67K5q93lSRHz109zT/KIJSQMZpbaecGAoiZDM8Mdq3KzawGSG +ENQazx6lnGoMccvxFhjrVqfYj3U4S/pnCow5fatvkBQSyysL63UxE5ivcFUHHppB ---- BuKW3bW48i1OD38J2bj5sRkn+zg/WKiLtf8zgycCr2A -g2k5 !]0kWءt>Qk[I3V4Ewc`L;UvVe)mm鿀 ۸ \ No newline at end of file +-> ssh-ed25519 QovoLQ wgg0cFlYEVafE3rXK4GrID3RTatZdKPYzsjT18WskFM +bgv+7an3xgdqf6WaiB1FFkXObcykUnvH6lJmX5gFJkQ +-> ssh-rsa OFkEIg +IIQbFB6VUwbB+ZtKR7Ayg9Im6vMU1AzqHT8CBagA5fwJ7Vp1GuX1X9SxL9hMPkd3 +4osEbSu3JJDMwfC6AfFtcEjmxjmRYyiYlzmIjhVEsaTlwyeucAPd+fdj+TPjHidZ +dffizNEOiENY49jlmWTjMqYKnBsSP9GfH4ZsKpCaWMm2h9p687weuXFfbYfjYMII +a3C4iG8m+mZ4crYTKZu6WPbnHn9g0pMxZBs4v6MnBHk6eEJ0uiJvrzYApoFE5om7 +9AknL27ra/+A1UQl+1kzLT+IivJa8FCfZ+zF1RYLRvSATlIzCqCiBiayAsVtQg5O +girBRnlAJTPisszyoAhsqbECvD6bJfwlTW0STg/M1u3ZPMTGL4V0gJgynANmjb7Y +TXd11zuhjRYgOBAj09trQFTmmwIgPvvu8+VXNDNPAp02ffBT8kMUvSEik98/35x1 +Dwvm38t05O6nqyHUF957CRVTzPQPAnb5Cd+Rw/joID2YPyFN9IZwE4mi2Bf3zdZo +roxtqCupmWkpxMNN7GZJrmCE/Lh6YV4DgUd6VNQc7QlGsq5K4XRT7aa+s+17cC8e +HCxQfGM8sMe9T6IK+K4p6qTqluyI/X0r95kGfzhNmgzufc44i6X497i3fDSVoLpx +Uo7Ao3QRNPyaUXcqTTIg8Kx9YiLQC3tDblVJjIZU89o +--- Vb9o/bhuN6XXjfK04haEEUXnuIA02j4GH9PmAh0ayN8 +EdGs; +,OH{>*wAL\0SQ*{6f+X. \ No newline at end of file diff --git a/agenix/secrets.nix b/agenix/secrets.nix index a3119d1..3101494 100644 --- a/agenix/secrets.nix +++ b/agenix/secrets.nix @@ -6,7 +6,10 @@ in { "ntfy.age".publicKeys = [ tuxcord-ca ] ++ builtins.attrValues users; - # tsig-keygen sub.domain.tld. - "dns/tuxcord.key".publicKeys = [ tuxcord-ca ] ++ [ users.error users.javalsai ]; - # "dns/users/XXX.key".publicKeys = [ users.XXX ]; + # tsig-keygen etc.sub.domain.tld. + "dns/tuxcord.net/tuxcord.net.key.age".publicKeys = [ tuxcord-ca ] ++ [ users.error users.javalsai ]; + # "dns/tuxcord.net/XXX.tuxcord.net.key.age".publicKeys = [ tuxcord-ca ] ++ [ users.XXX ]; + + "dns/tuxcord.test/tuxcord.test.key.age".publicKeys = [ tuxcord-ca ] ++ builtins.attrValues users; + "dns/tuxcord.test/sub.tuxcord.test.key.age".publicKeys = [ tuxcord-ca ] ++ builtins.attrValues users; } diff --git a/nixos/common.nix b/nixos/common.nix index 51e88f5..a6a0487 100644 --- a/nixos/common.nix +++ b/nixos/common.nix @@ -28,14 +28,6 @@ in ./vm.nix ]; - age.secrets = { - dns-root-key = { - file = ../agenix/dns/tuxcord.key; - group = "named"; - owner = "named"; - }; - }; - nix = { package = inputs'.nix-super.packages.default; diff --git a/nixos/hosts/tuxcord-ca/default.nix b/nixos/hosts/tuxcord-ca/default.nix index b0b24c4..a3eeb69 100644 --- a/nixos/hosts/tuxcord-ca/default.nix +++ b/nixos/hosts/tuxcord-ca/default.nix @@ -4,6 +4,7 @@ ./storage.nix ]; + dns.enable = true; networking.fqdn = "tuxcord.net"; time.timeZone = "Canada/Eastern"; } diff --git a/nixos/hosts/tuxcord-test/default.nix b/nixos/hosts/tuxcord-test/default.nix index 1fdcfdf..ad811a1 100644 --- a/nixos/hosts/tuxcord-test/default.nix +++ b/nixos/hosts/tuxcord-test/default.nix @@ -1,3 +1,4 @@ { + dns.enable = true; networking.fqdn = "tuxcord.test"; } diff --git a/nixos/modules/dns.nix b/nixos/modules/dns.nix index 388d08d..ffed8c7 100644 --- a/nixos/modules/dns.nix +++ b/nixos/modules/dns.nix @@ -1,58 +1,100 @@ -{ config, ... }: +{ config, lib, ... }: let - fqdn = "tuxcord.net"; - # fqdn = config.networking.fqdn; + agenixDnsDir = ../../agenix/dns + "/${config.dns.domain}"; + agenixKeys = builtins.attrNames (builtins.readDir agenixDnsDir); - zonesub = _: "zonesub"; - subdomain = name: "subdomain ${name}"; + keys = map ( + filename: + let + zonesub = _: "zonesub"; + subdomain = name: "subdomain ${name}"; - # careful, assumes the fqdn (name) matches the key name content - keys = [ + zoneDomain = + if lib.strings.hasSuffix ".key.age" filename then + lib.strings.removeSuffix ".key.age" filename + else + throw "${filename} is not a `.key.age` file"; + in { - name = "tuxcord.net"; - path = config.age.secrets.dns-root-key.path; - type = zonesub; + name = zoneDomain; + path = config.age.secrets."dns/${filename}".path; + type = if zoneDomain == config.dns.domain then zonesub else subdomain; } - ]; + ) agenixKeys; + + cfg = config.dns; + inherit (lib) + mkEnableOption + mkOption + mkIf + ; in { - services.bind = { - enable = true; + options.dns = { + enable = mkEnableOption "" // { + default = true; + }; - extraConfig = builtins.concatStringsSep "\n" (map (key: "include \"${key.path}\";") keys); - - zones = { - "${fqdn}" = { - # grant "tuxcord.net" zonesub ANY; - extraConfig = '' - update-policy { - ${builtins.concatStringsSep "\n" ( - map (key: "grant \"${key.name}\" ${key.type key.name} ANY;") keys - )} - }; - ''; - file = "/var/dns/${fqdn}.zone"; # need to put default stuff - master = true; - }; + domain = mkOption { + type = with lib.types; str; + default = config.networking.fqdn; }; }; - environment.persistence."/persist" = { - directories = [ + config = mkIf cfg.enable { + age.secrets = builtins.listToAttrs ( + map ( + filename: + let + path = "${agenixDnsDir}/${filename}"; + in + { + name = "dns/${filename}"; + value = { + file = path; + group = "named"; + owner = "named"; + }; + } + ) agenixKeys + ); + + services.bind = { + enable = true; + + extraConfig = builtins.concatStringsSep "\n" (map (key: "include \"${key.path}\";") keys); + + zones = { + "${config.dns.domain}" = { + # grant "tuxcord.net" zonesub ANY; + extraConfig = '' + update-policy { + ${builtins.concatStringsSep "\n" ( + map (key: "grant \"${key.name}\" ${key.type key.name} ANY;") keys + )} + }; + ''; + file = "/var/dns/${config.dns.domain}.zone"; # need to put default stuff + master = true; + }; + }; + }; + + environment.persistence."/persist".directories = [ { directory = "/var/dns"; group = "named"; user = "named"; } ]; - }; - networking.firewall = - let - ports = [ config.services.bind.listenOnPort ]; - in - { - allowedTCPPorts = ports; - allowedUDPPorts = ports; - }; + networking.firewall = + let + ports = [ config.services.bind.listenOnPort ]; + in + { + allowedTCPPorts = ports; + allowedUDPPorts = ports; + }; + }; }