]> git.immae.eu Git - perso/Immae/Config/Nix.git/blobdiff - modules/private/certificates.nix
Squash changes containing private information
[perso/Immae/Config/Nix.git] / modules / private / certificates.nix
diff --git a/modules/private/certificates.nix b/modules/private/certificates.nix
deleted file mode 100644 (file)
index 9879946..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-{ lib, pkgs, config, name, ... }:
-{
-  options.myServices.certificates = {
-    enable = lib.mkEnableOption "enable certificates";
-    webroot = lib.mkOption {
-      readOnly = true;
-      default = "/var/lib/acme/acme-challenges";
-    };
-    certConfig = lib.mkOption {
-      default = {
-        webroot = lib.mkForce null; # avoids creation of tmpfiles
-        email = "ismael@bouya.org";
-        postRun = builtins.concatStringsSep "\n" [
-          (lib.optionalString config.services.httpd.Prod.enable "systemctl reload httpdProd.service")
-          (lib.optionalString config.services.httpd.Tools.enable "systemctl reload httpdTools.service")
-          (lib.optionalString config.services.httpd.Inte.enable "systemctl reload httpdInte.service")
-          (lib.optionalString config.services.nginx.enable "systemctl reload nginx.service")
-        ];
-        extraLegoRenewFlags = [ "--reuse-key" ];
-        keyType = lib.mkDefault "ec256"; # https://github.com/NixOS/nixpkgs/pull/83121
-      };
-      description = "Default configuration for certificates";
-    };
-  };
-
-  config = lib.mkIf config.myServices.certificates.enable {
-    services.nginx = {
-      recommendedTlsSettings = true;
-      virtualHosts = {
-        "${config.hostEnv.fqdn}" = {
-          acmeRoot = config.myServices.certificates.webroot;
-          useACMEHost = name;
-          forceSSL = true;
-        };
-      };
-    };
-    services.websites.certs = config.myServices.certificates.certConfig;
-    myServices.databasesCerts = config.myServices.certificates.certConfig;
-    myServices.ircCerts = config.myServices.certificates.certConfig;
-
-    security.acme.acceptTerms = true;
-    security.acme.preliminarySelfsigned = true;
-
-    security.acme.certs = {
-      "${name}" = config.myServices.certificates.certConfig // {
-        domain = config.hostEnv.fqdn;
-      };
-    };
-
-    users.users.acme = {
-      uid = config.ids.uids.acme;
-      group = "acme";
-      description = "Acme user";
-    };
-    users.groups.acme = {
-      gid = config.ids.gids.acme;
-    };
-
-    systemd.services = lib.attrsets.mapAttrs' (k: v:
-      lib.attrsets.nameValuePair "acme-selfsigned-${k}" {
-          wantedBy = [ "acme-selfsigned-certificates.target" ];
-          script = lib.mkAfter ''
-          cp $workdir/server.crt ${config.security.acme.certs."${k}".directory}/cert.pem
-          chown '${v.user}:${v.group}' ${config.security.acme.certs."${k}".directory}/cert.pem
-          chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.certs."${k}".directory}/cert.pem
-
-          cp $workdir/ca.crt ${config.security.acme.certs."${k}".directory}/chain.pem
-          chown '${v.user}:${v.group}' ${config.security.acme.certs."${k}".directory}/chain.pem
-          chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.certs."${k}".directory}/chain.pem
-          '';
-        }
-      ) config.security.acme.certs //
-    lib.attrsets.mapAttrs' (k: data:
-      lib.attrsets.nameValuePair "acme-${k}" {
-        after = lib.mkAfter [ "bind.service" ];
-        serviceConfig =
-          let
-            cfg = config.security.acme;
-            hashOptions = let
-              domains = builtins.concatStringsSep "," (
-                [ data.domain ] ++ (builtins.attrNames data.extraDomains)
-              );
-              certOptions = builtins.concatStringsSep "," [
-                (if data.ocspMustStaple then "must-staple" else "no-must-staple")
-              ];
-            in
-              builtins.hashString "sha256" (builtins.concatStringsSep ";" [ data.keyType domains certOptions ]);
-            accountsDir = "accounts-${data.keyType}";
-            lpath = "acme/${k}";
-            apath = "/var/lib/${lpath}";
-            spath = "/var/lib/acme/.lego/${k}";
-            fileMode = if data.allowKeysForGroup then "640" else "600";
-            dirFileMode = if data.allowKeysForGroup then "750" else "700";
-            globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
-              ++ lib.optionals (cfg.acceptTerms) [ "--accept-tos" ]
-              ++ lib.optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
-              ++ lib.concatLists (lib.mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
-              ++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" config.myServices.certificates.webroot ])
-              ++ lib.optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)];
-            certOpts = lib.optionals data.ocspMustStaple [ "--must-staple" ];
-            runOpts = lib.escapeShellArgs (globalOpts ++ [ "run" ] ++ certOpts);
-            renewOpts = lib.escapeShellArgs (globalOpts ++
-              [ "renew" "--days" (builtins.toString cfg.validMinDays) ] ++
-              certOpts ++ data.extraLegoRenewFlags);
-            forceRenewOpts = lib.escapeShellArgs (globalOpts ++
-              [ "renew" "--days" "999" ] ++
-              certOpts ++ data.extraLegoRenewFlags);
-            keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
-          in {
-            User = lib.mkForce "acme";
-            Group = lib.mkForce "acme";
-            WorkingDirectory = lib.mkForce spath;
-            StateDirectory = lib.mkForce "acme/.lego/${k} acme/.lego/${accountsDir}";
-            ExecStartPre =
-              let
-                script = pkgs.writeScript "acme-prestart" ''
-                  #!${pkgs.runtimeShell} -e
-                  install -m 0755 -o acme -g acme -d ${config.myServices.certificates.webroot}
-                '';
-              in
-                lib.mkForce "+${script}";
-            ExecStart = lib.mkForce (pkgs.writeScript "acme-start" ''
-              #!${pkgs.runtimeShell} -e
-              # lego doesn't check key type after initial creation, we
-              # need to check for him
-              if [ -L ${spath}/accounts -o -d ${spath}/accounts ]; then
-                if [ -L ${spath}/accounts -a "$(readlink ${spath}/accounts)" != ../${accountsDir} ]; then
-                  ln -sfn ../${accountsDir} ${spath}/accounts
-                  mv -f ${spath}/certificates/${keyName}.key ${spath}/certificates/${keyName}.key.old
-                fi
-              else
-                ln -s ../${accountsDir} ${spath}/accounts
-              fi
-              # check if domain changed: lego doesn't check by itself
-              if [ ! -e ${spath}/certificates/${keyName}.crt -o ! -e ${spath}/certificates/${keyName}.key -o ! -e "${spath}/accounts/acme-v02.api.letsencrypt.org/${data.email}/account.json" ]; then
-                ${pkgs.lego}/bin/lego ${runOpts}
-              elif [ ! -f ${spath}/currentDomains -o "$(cat ${spath}/currentDomains)" != "${hashOptions}" ]; then
-                ${pkgs.lego}/bin/lego ${forceRenewOpts}
-              else
-                ${pkgs.lego}/bin/lego ${renewOpts}
-              fi
-            '');
-            ExecStartPost =
-              let
-                ISRG_Root_X1 = pkgs.fetchurl {
-                  url = "https://letsencrypt.org/certs/isrgrootx1.pem";
-                  sha256 = "1la36n2f31j9s03v847ig6ny9lr875q3g7smnq33dcsmf2i5gd92";
-                };
-                fix_ISRG_Root_X1 = pkgs.writeScript "fix-pem" ''
-                  for file in chain fullchain full; do
-                    if grep -q MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA "$file.pem"; then
-                      cat ${ISRG_Root_X1} | grep -v " CERTIFICATE" | \
-                      sed -i.bak -ne "/MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ {r /dev/stdin" -e ":a; n; /Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5/ { b }; ba };p" $file.pem
-                    fi
-                  done
-                '';
-                script = pkgs.writeScript "acme-post-start" ''
-                  #!${pkgs.runtimeShell} -e
-                  install -m 0755 -o root -g root -d /var/lib/acme
-                  install -m 0${dirFileMode} -o ${data.user} -g ${data.group} -d /var/lib/acme/${k}
-                  cd /var/lib/acme/${k}
-
-                  # Test that existing cert is older than new cert
-                  KEY=${spath}/certificates/${keyName}.key
-                  KEY_CHANGED=no
-                  if [ -e $KEY -a $KEY -nt key.pem ]; then
-                    KEY_CHANGED=yes
-                    cp -p ${spath}/certificates/${keyName}.key key.pem
-                    cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
-                    cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
-                    ln -sf fullchain.pem cert.pem
-                    cat key.pem fullchain.pem > full.pem
-                    echo -n "${hashOptions}" > ${spath}/currentDomains
-                  fi
-
-                  ${fix_ISRG_Root_X1}
-                  chmod ${fileMode} *.pem
-                  chown '${data.user}:${data.group}' *.pem
-
-                  if [ "$KEY_CHANGED" = "yes" ]; then
-                    : # noop in case postRun is empty
-                    ${data.postRun}
-                  fi
-                '';
-              in
-                lib.mkForce "+${script}";
-          };
-      }
-    ) config.security.acme.certs //
-    {
-      httpdProd = lib.mkIf config.services.httpd.Prod.enable
-        { after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
-      httpdTools = lib.mkIf config.services.httpd.Tools.enable
-        { after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
-      httpdInte = lib.mkIf config.services.httpd.Inte.enable
-        { after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
-    };
-  };
-}