diff options
Diffstat (limited to 'hosts/surtr/tls')
| -rw-r--r-- | hosts/surtr/tls/default.nix | 156 | ||||
| -rw-r--r-- | hosts/surtr/tls/tsig_keys/rheperire.org | 26 |
2 files changed, 182 insertions, 0 deletions
diff --git a/hosts/surtr/tls/default.nix b/hosts/surtr/tls/default.nix new file mode 100644 index 00000000..a1548feb --- /dev/null +++ b/hosts/surtr/tls/default.nix | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | { config, lib, customUtils, pkgs, ... }: | ||
| 2 | |||
| 3 | with lib; | ||
| 4 | |||
| 5 | let | ||
| 6 | inherit (customUtils) mapFilterAttrs; | ||
| 7 | |||
| 8 | tsigSecretName = domain: "${domain}_tsig-secret"; | ||
| 9 | |||
| 10 | cfg = config.security.acme; | ||
| 11 | knotCfg = config.services.knot; | ||
| 12 | |||
| 13 | knotDNSCredentials = domain: let | ||
| 14 | zone = if cfg.domains.${domain}.zone == null then domain else cfg.domains.${domain}.zone; | ||
| 15 | in pkgs.writeText "lego-credentials" '' | ||
| 16 | EXEC_PATH=${knotDNSExec zone}/bin/update-dns.sh | ||
| 17 | EXEC_PROPAGATION_TIMEOUT=300 | ||
| 18 | EXEC_POLLING_INTERVAL=5 | ||
| 19 | ''; | ||
| 20 | knotDNSExec = zone: pkgs.writeScriptBin "update-dns.sh" '' | ||
| 21 | #!${pkgs.zsh}/bin/zsh -xe | ||
| 22 | |||
| 23 | mode=$1 | ||
| 24 | fqdn=$2 | ||
| 25 | challenge=$3 | ||
| 26 | |||
| 27 | owner=''${fqdn%".${zone}."} | ||
| 28 | |||
| 29 | commited= | ||
| 30 | function abort() { | ||
| 31 | [[ -n "''${commited}" ]] || ${knotCfg.cliWrappers}/bin/knotc zone-abort "${zone}" | ||
| 32 | } | ||
| 33 | |||
| 34 | ${knotCfg.cliWrappers}/bin/knotc zone-begin "${zone}" | ||
| 35 | trap abort EXIT | ||
| 36 | |||
| 37 | case "''${mode}" in | ||
| 38 | present) | ||
| 39 | if ${knotCfg.cliWrappers}/bin/knotc zone-get ${zone} "''${owner}" TXT; then | ||
| 40 | ${knotCfg.cliWrappers}/bin/knotc zone-unset ${zone} "''${owner}" TXT '""' | ||
| 41 | fi | ||
| 42 | ${knotCfg.cliWrappers}/bin/knotc zone-set ${zone} "''${owner}" 30 TXT "''${challenge}" | ||
| 43 | ;; | ||
| 44 | cleanup) | ||
| 45 | ${knotCfg.cliWrappers}/bin/knotc zone-unset ${zone} "''${owner}" TXT "''${challenge}" | ||
| 46 | ${knotCfg.cliWrappers}/bin/knotc zone-set ${zone} "''${owner}" 30 TXT '""' | ||
| 47 | ;; | ||
| 48 | *) | ||
| 49 | exit 2 | ||
| 50 | ;; | ||
| 51 | esac | ||
| 52 | |||
| 53 | ${knotCfg.cliWrappers}/bin/knotc zone-commit "${zone}" | ||
| 54 | commited=yes | ||
| 55 | ''; | ||
| 56 | |||
| 57 | domainOptions = { | ||
| 58 | options = { | ||
| 59 | wildcard = mkOption { | ||
| 60 | type = types.bool; | ||
| 61 | default = false; | ||
| 62 | }; | ||
| 63 | zone = mkOption { | ||
| 64 | type = types.nullOr types.str; | ||
| 65 | default = null; | ||
| 66 | }; | ||
| 67 | certCfg = mkOption { | ||
| 68 | type = types.attrs; | ||
| 69 | default = {}; | ||
| 70 | }; | ||
| 71 | }; | ||
| 72 | }; | ||
| 73 | in { | ||
| 74 | options = { | ||
| 75 | security.acme = { | ||
| 76 | domains = mkOption { | ||
| 77 | type = types.attrsOf (types.submodule domainOptions); | ||
| 78 | default = {}; | ||
| 79 | }; | ||
| 80 | }; | ||
| 81 | }; | ||
| 82 | |||
| 83 | config = { | ||
| 84 | security.acme.domains = genAttrs ["dirty-haskell.org" "141.li" "xmpp.li" "yggdrasil.li" "praseodym.org" "rheperire.org" "kleen.li" "nights.email"] (domain: { wildcard = true; }); | ||
| 85 | |||
| 86 | fileSystems."/var/lib/acme" = | ||
| 87 | { device = "surtr/safe/var-lib-acme"; | ||
| 88 | fsType = "zfs"; | ||
| 89 | }; | ||
| 90 | |||
| 91 | security.acme = { | ||
| 92 | acceptTerms = true; | ||
| 93 | preliminarySelfsigned = true; # DNS challenge is slow | ||
| 94 | defaults = { | ||
| 95 | email = "phikeebaogobaegh@141.li"; | ||
| 96 | keyType = "rsa4096"; # we don't like NIST curves | ||
| 97 | # extraLegoFlags = ["--preferred-chain" "ISRG Root X1"]; | ||
| 98 | }; | ||
| 99 | certs = | ||
| 100 | let | ||
| 101 | domainAttrset = domain: let | ||
| 102 | tsigPath = ./tsig_keys + "/${domain}"; | ||
| 103 | tsigSecret = config.sops.secrets.${tsigSecretName domain}; | ||
| 104 | isTsig = pathExists tsigPath; | ||
| 105 | shared = { | ||
| 106 | inherit domain; | ||
| 107 | extraDomainNames = optional cfg.domains.${domain}.wildcard "*.${domain}"; | ||
| 108 | dnsResolver = "127.0.0.1:5353"; | ||
| 109 | }; | ||
| 110 | mkKnotc = shared // { | ||
| 111 | dnsProvider = "exec"; | ||
| 112 | credentialsFile = knotDNSCredentials domain; | ||
| 113 | }; | ||
| 114 | mkRFC2136 = let | ||
| 115 | tsigInfo = readYaml tsigPath; | ||
| 116 | in shared // { | ||
| 117 | dnsProvider = "rfc2136"; | ||
| 118 | credentialsFile = pkgs.writeText "${domain}_credentials.env" '' | ||
| 119 | RFC2136_NAMESERVER=127.0.0.1:53 | ||
| 120 | RFC2136_TSIG_ALGORITHM=hmac-sha256. | ||
| 121 | RFC2136_TSIG_KEY=${domain}_acme | ||
| 122 | RFC2136_TSIG_SECRET_FILE=${tsigSecret.path} | ||
| 123 | RFC2136_PROPAGATION_TIMEOUT=300 | ||
| 124 | RFC2136_POLLING_INTERVAL=5 | ||
| 125 | RFC2136_TTL=300 | ||
| 126 | ''; | ||
| 127 | }; | ||
| 128 | in // cfg.domains.${domain}.certCfg; | ||
| 129 | in genAttrs (attrNames cfg.domains) domainAttrset; | ||
| 130 | }; | ||
| 131 | |||
| 132 | sops.secrets = let | ||
| 133 | toTSIGSecret = n: v: | ||
| 134 | if v == "regular" || v == "symlink" | ||
| 135 | then nameValuePair (tsigSecretName n) { | ||
| 136 | format = "binary"; | ||
| 137 | owner = if config.security.acme.useRoot then "root" else "acme"; | ||
| 138 | group = "acme"; | ||
| 139 | sopsFile = ./tsig_keys + "/${n}"; | ||
| 140 | } else null; | ||
| 141 | in mapFilterAttrs (_: v: v != null) toTSIGSecret (readDir ./tsig_keys); | ||
| 142 | |||
| 143 | systemd.services = | ||
| 144 | let | ||
| 145 | serviceAttrset = domain: { | ||
| 146 | after = [ "knot.service" ]; | ||
| 147 | bindsTo = [ "knot.service" ]; | ||
| 148 | serviceConfig = { | ||
| 149 | ReadWritePaths = ["/run/knot/knot.sock"]; | ||
| 150 | SupplementaryGroups = ["knot"]; | ||
| 151 | RestrictAddressFamilies = ["AF_UNIX"]; | ||
| 152 | }; | ||
| 153 | }; | ||
| 154 | in mapAttrs' (domain: nameValuePair "acme-${domain}") (genAttrs (attrNames config.security.acme.certs) serviceAttrset); | ||
| 155 | }; | ||
| 156 | } | ||
diff --git a/hosts/surtr/tls/tsig_keys/rheperire.org b/hosts/surtr/tls/tsig_keys/rheperire.org new file mode 100644 index 00000000..1f3dc4a4 --- /dev/null +++ b/hosts/surtr/tls/tsig_keys/rheperire.org | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | { | ||
| 2 | "data": "ENC[AES256_GCM,data:Lb1IWtwPdBxeXGrOr74MlR7lKBMIg2ix3enRMVN4MPEDh7CIFv1nhAfLCDU=,iv:TcyGtcKEL7yUXgHrfJ5pDjl8r5V7ltYQw2wcnsFN1bc=,tag:gBaYj6MkQKvD/uO+Pudnzg==,type:str]", | ||
| 3 | "sops": { | ||
| 4 | "kms": null, | ||
| 5 | "gcp_kms": null, | ||
| 6 | "azure_kv": null, | ||
| 7 | "hc_vault": null, | ||
| 8 | "age": null, | ||
| 9 | "lastmodified": "2022-02-22T09:46:27Z", | ||
| 10 | "mac": "ENC[AES256_GCM,data:vtymuSymOeh34ZbAumxCEcemtI0UFBoQwj4axpKf7AzVnQOubWYxPI5x23CiOE12Y+FThg1dYEnDWlkkQjMVWQvcJzfP1g25S98MuZ42E9R0nBxGzTrIaKS7kgNAriYDy8ib7Z3DUbajEGfvLLazCdHu3g9gE0dLewKcUTHaXwM=,iv:j8vS2Ej58HLf+CP9fe1rN+4UuniGlv/0M+Zzt3nlk5I=,tag:xn33GGm2knsIdH+EJ1zDcA==,type:str]", | ||
| 11 | "pgp": [ | ||
| 12 | { | ||
| 13 | "created_at": "2022-02-22T09:46:26Z", | ||
| 14 | "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DyFKFNkTVG5oSAQdA1++YsCSiRkVGoVF6uvYeY7JjZjsdjAUwubCF3fLDtS8w\nHFSQltgrqkul1Ei1fUFQqFbSpMSfBQhk0kMH0Xuk5SoDd1lWumqTP9gaJj/CM+yz\n0l4BHiQ4Ktyc01f127Az36nQZGKdJvL9etQAceNtNM7Y4XkLQ78OXFJoERrf81s/\n4wm5za7xqEBE1oE0QWAelzyjBqxI1iCjDl3p6heUdhqlcvAifXgqAk0qxq/4T4FG\n=2Bwl\n-----END PGP MESSAGE-----\n", | ||
| 15 | "fp": "7ED22F4AA7BB55728B643DC5471B7D88E4EF66F8" | ||
| 16 | }, | ||
| 17 | { | ||
| 18 | "created_at": "2022-02-22T09:46:26Z", | ||
| 19 | "enc": "-----BEGIN PGP MESSAGE-----\n\nhF4DXxoViZlp6dISAQdA4jg570qc5Zu3yAJPmjf11r20eYMyjAeEWw/RreZga3Uw\nmTy2jo/de11m3r/aIxp0Q/vFZ1m4JGeoIzIgQxGnhX0s0NpfCbCih0P7UMjZRatC\n0l4BCzWq7c0A2GbjPq+aKF2IYfQV5gdwjgCAJO3Oylb/SAltwnyGChANw4ckUCjV\n9DWYIcerMP2scxpjf5nJXpHNMjpGR7fcqS71PoVoJoActMqrG0deOMUSUEOVP8nR\n=+ux+\n-----END PGP MESSAGE-----\n", | ||
| 20 | "fp": "30D3453B8CD02FE2A3E7C78C0FB536FB87AE8F51" | ||
| 21 | } | ||
| 22 | ], | ||
| 23 | "unencrypted_suffix": "_unencrypted", | ||
| 24 | "version": "3.7.1" | ||
| 25 | } | ||
| 26 | } \ No newline at end of file | ||
