diff options
Diffstat (limited to 'hosts/surtr/dns/default.nix')
| -rw-r--r-- | hosts/surtr/dns/default.nix | 137 |
1 files changed, 64 insertions, 73 deletions
diff --git a/hosts/surtr/dns/default.nix b/hosts/surtr/dns/default.nix index 5d55c815..57146d67 100644 --- a/hosts/surtr/dns/default.nix +++ b/hosts/surtr/dns/default.nix | |||
| @@ -3,15 +3,38 @@ | |||
| 3 | with lib; | 3 | with lib; |
| 4 | 4 | ||
| 5 | let | 5 | let |
| 6 | acmeChallengeZonefile = domain: let | 6 | reverseDomain = domain: concatStringsSep "." (reverseList (splitString "." domain)); |
| 7 | reverseDomain = concatStringsSep "." (reverseList (["_acme-challenge"] ++ splitString "." domain)); | 7 | |
| 8 | in pkgs.writeText "${reverseDomain}.zone" '' | 8 | acmeChallengeZonefile = domain: pkgs.writeText "${reverseDomain "_acme-challenge.${domain}"}.soa" '' |
| 9 | $ORIGIN _acme-challenge.${domain}. | 9 | $ORIGIN _acme-challenge.${domain}. |
| 10 | $TTL 3600 | 10 | $TTL 3600 |
| 11 | @ IN SOA ns.yggdrasil.li. root.yggdrasil.li. 2022022103 10800 3600 604800 30 | 11 | @ IN SOA ns.yggdrasil.li. root.yggdrasil.li. 2022022103 10800 3600 604800 30 |
| 12 | 12 | ||
| 13 | IN NS ns.yggdrasil.li. | 13 | IN NS ns.yggdrasil.li. |
| 14 | ''; | 14 | ''; |
| 15 | |||
| 16 | knotKeys = let | ||
| 17 | dir = ./keys; | ||
| 18 | toKeyInfo = name: v: | ||
| 19 | if v == "regular" || v == "symlink" | ||
| 20 | then { path = dir + "/${name}"; inherit name; } | ||
| 21 | else null; | ||
| 22 | in filter (v: v != null) (mapAttrsToList toKeyInfo (builtins.readDir dir)); | ||
| 23 | |||
| 24 | indentString = indentation: str: concatMapStringsSep "\n" (str: " ${str}") (splitString "\n" (removeSuffix "\n" str)); | ||
| 25 | |||
| 26 | mkZone = {domain, path ? (./zones + "/${reverseDomain domain}.soa"), acmeDomains ? [domain]}: indentString " " '' | ||
| 27 | - domain: ${domain} | ||
| 28 | template: inwx_zone | ||
| 29 | ${optionalString (acmeDomains != []) "acl: [local_acl, inwx_acl]"} | ||
| 30 | file: ${path} | ||
| 31 | ${concatMapStringsSep "\n" (acmeDomain: '' | ||
| 32 | - domain: _acme-challenge.${acmeDomain} | ||
| 33 | template: acme_zone | ||
| 34 | acl: [${assert (config.sops.secrets ? "${acmeDomain}_acme.yaml"); "${acmeDomain}_acme_acl"}] | ||
| 35 | file: ${acmeChallengeZonefile acmeDomain} | ||
| 36 | '') acmeDomains} | ||
| 37 | ''; | ||
| 15 | in { | 38 | in { |
| 16 | config = { | 39 | config = { |
| 17 | fileSystems."/var/lib/knot" = | 40 | fileSystems."/var/lib/knot" = |
| @@ -23,11 +46,7 @@ in { | |||
| 23 | 46 | ||
| 24 | services.knot = { | 47 | services.knot = { |
| 25 | enable = true; | 48 | enable = true; |
| 26 | keyFiles = [ | 49 | keyFiles = map ({name, ...}: config.sops.secrets.${name}.path) knotKeys; |
| 27 | config.sops.secrets."rheperire.org_acme_key.yaml".path | ||
| 28 | config.sops.secrets."webdav.141.li_acme_key.yaml".path | ||
| 29 | config.sops.secrets."knot_local_key.yaml".path | ||
| 30 | ]; | ||
| 31 | extraConfig = '' | 50 | extraConfig = '' |
| 32 | server: | 51 | server: |
| 33 | listen: 127.0.0.1@53 | 52 | listen: 127.0.0.1@53 |
| @@ -48,16 +67,23 @@ in { | |||
| 48 | - id: inwx_acl | 67 | - id: inwx_acl |
| 49 | address: 185.181.104.96 | 68 | address: 185.181.104.96 |
| 50 | action: transfer | 69 | action: transfer |
| 51 | - id: rheperire.org_acme_acl | ||
| 52 | key: rheperire.org_acme_key | ||
| 53 | action: update | ||
| 54 | - id: webdav.141.li_acme_acl | ||
| 55 | key: webdav.141.li_acme_key | ||
| 56 | action: update | ||
| 57 | - id: local_acl | 70 | - id: local_acl |
| 58 | key: local_key | 71 | key: local_key |
| 59 | action: update | 72 | action: update |
| 60 | update-type: DS | 73 | update-type: DS |
| 74 | ${let | ||
| 75 | toACMEACL = { name, ... }: | ||
| 76 | if hasSuffix "_acme.yaml" name | ||
| 77 | then | ||
| 78 | let | ||
| 79 | base = removeSuffix ".yaml" name; | ||
| 80 | in indentString " " '' | ||
| 81 | - id: ${base}_acl | ||
| 82 | key: ${base}_key | ||
| 83 | action: update | ||
| 84 | '' | ||
| 85 | else null; | ||
| 86 | in concatStringsSep "\n" (filter (v: v != null) (map toACMEACL knotKeys))} | ||
| 61 | 87 | ||
| 62 | mod-rrl: | 88 | mod-rrl: |
| 63 | - id: default | 89 | - id: default |
| @@ -124,68 +150,33 @@ in { | |||
| 124 | dnssec-policy: ed25519_local-push | 150 | dnssec-policy: ed25519_local-push |
| 125 | 151 | ||
| 126 | zone: | 152 | zone: |
| 127 | - domain: yggdrasil.li | 153 | ${concatMapStringsSep "\n" mkZone [ |
| 128 | template: inwx_zone | 154 | { domain = "yggdrasil.li"; |
| 129 | file: ${./zones/li.yggdrasil.soa} | 155 | } |
| 130 | 156 | { domain = "nights.email"; | |
| 131 | - domain: nights.email | 157 | } |
| 132 | template: inwx_zone | 158 | { domain = "141.li"; |
| 133 | file: ${./zones/email.nights.soa} | 159 | acmeDomains = ["webdav.141.li" "141.li"]; |
| 134 | 160 | } | |
| 135 | - domain: 141.li | 161 | { domain = "kleen.li"; |
| 136 | template: inwx_zone | 162 | } |
| 137 | acl: [local_acl, inwx_acl] | 163 | { domain = "xmpp.li"; |
| 138 | file: ${./zones/li.141.soa} | 164 | } |
| 139 | - domain: _acme-challenge.webdav.141.li | 165 | { domain = "dirty-haskell.org"; |
| 140 | template: acme_zone | 166 | } |
| 141 | acl: [webdav.141.li_acme_acl] | 167 | { domain = "praseodym.org"; |
| 142 | file: ${acmeChallengeZonefile "webdav.141.li"} | 168 | } |
| 143 | 169 | { domain = "rheperire.org"; | |
| 144 | - domain: kleen.li | 170 | } |
| 145 | template: inwx_zone | 171 | ]} |
| 146 | file: ${./zones/li.kleen.soa} | ||
| 147 | |||
| 148 | - domain: xmpp.li | ||
| 149 | template: inwx_zone | ||
| 150 | file: ${./zones/li.xmpp.soa} | ||
| 151 | |||
| 152 | - domain: dirty-haskell.org | ||
| 153 | template: inwx_zone | ||
| 154 | file: ${./zones/org.dirty-haskell.soa} | ||
| 155 | |||
| 156 | - domain: praseodym.org | ||
| 157 | template: inwx_zone | ||
| 158 | file: ${./zones/org.praseodym.soa} | ||
| 159 | |||
| 160 | - domain: rheperire.org | ||
| 161 | template: inwx_zone | ||
| 162 | acl: [local_acl, inwx_acl] | ||
| 163 | file: ${./zones/org.rheperire.soa} | ||
| 164 | - domain: _acme-challenge.rheperire.org | ||
| 165 | template: acme_zone | ||
| 166 | acl: [rheperire.org_acme_acl] | ||
| 167 | file: ${acmeChallengeZonefile "rheperire.org"} | ||
| 168 | ''; | 172 | ''; |
| 169 | }; | 173 | }; |
| 170 | 174 | ||
| 171 | sops.secrets = { | 175 | sops.secrets = listToAttrs (map ({name, path}: nameValuePair name { |
| 172 | "rheperire.org_acme_key.yaml" = { | 176 | format = "binary"; |
| 173 | format = "binary"; | 177 | owner = "knot"; |
| 174 | owner = "knot"; | 178 | sopsFile = path; |
| 175 | sopsFile = ./keys/rheperire.org_acme.yaml; | 179 | }) knotKeys); |
| 176 | }; | ||
| 177 | "webdav.141.li_acme_key.yaml" = { | ||
| 178 | format = "binary"; | ||
| 179 | owner = "knot"; | ||
| 180 | sopsFile = ./keys/webdav.141.li_acme.yaml; | ||
| 181 | }; | ||
| 182 | "knot_local_key.yaml" = { | ||
| 183 | format = "binary"; | ||
| 184 | owner = "knot"; | ||
| 185 | sopsFile = ./keys/local_key.yaml; | ||
| 186 | }; | ||
| 187 | }; | ||
| 188 | |||
| 189 | 180 | ||
| 190 | fileSystems."/var/lib/unbound" = | 181 | fileSystems."/var/lib/unbound" = |
| 191 | { device = "surtr/local/var-lib-unbound"; | 182 | { device = "surtr/local/var-lib-unbound"; |
