summary refs log tree commit diff
path: root/nixos/modules/services/security/simp_le.nix
diff options
context:
space:
mode:
authorFranz Pletz <fpletz@fnordicwalking.de>2015-12-06 16:55:09 +0100
committerFranz Pletz <fpletz@fnordicwalking.de>2015-12-12 16:06:51 +0100
commit612781e8169bf13fde26091f2d6c55ebed6ccb6f (patch)
treefcff0d0dee06bac02caa16ce9d371da930165e11 /nixos/modules/services/security/simp_le.nix
parent069b1891d34f2a1a674daf6baad02d73ab8228c6 (diff)
downloadnixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.tar
nixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.tar.gz
nixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.tar.bz2
nixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.tar.lz
nixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.tar.xz
nixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.tar.zst
nixpkgs-612781e8169bf13fde26091f2d6c55ebed6ccb6f.zip
simp_le service: letsencrypt cert auto-renewal
This new service invokes `simp_le` for a defined set of certs on a regular
basis with a systemd timer. `simp_le` is smart enough to handle account
registration, domain validation and renewal on its own. The only thing
required is an existing HTTP server that serves the path
`/.well-known/acme-challenge` from the webroot cert parameter.

Example:

  services.simp_le.certs."foo.example.com" = {
    webroot = "/var/www/challenges";
    extraDomains = [ "www.example.com" ];
    email = "foo@example.com";
    validMin = 2592000;
    renewInterval = "weekly";
  };

Example Nginx vhost:

  services.nginx.appendConfig = ''
    http {
      server {
        server_name _;
        listen 80;
        listen [::]:80;

        location /.well-known/acme-challenge {
          root /var/www/challenges;
        }

        location / {
          return 301 https://$host$request_uri;
        }
      }
    }
  '';
Diffstat (limited to 'nixos/modules/services/security/simp_le.nix')
-rw-r--r--nixos/modules/services/security/simp_le.nix133
1 files changed, 133 insertions, 0 deletions
diff --git a/nixos/modules/services/security/simp_le.nix b/nixos/modules/services/security/simp_le.nix
new file mode 100644
index 00000000000..d578d5bb679
--- /dev/null
+++ b/nixos/modules/services/security/simp_le.nix
@@ -0,0 +1,133 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.simp_le;
+
+  certOpts = { ... }: {
+    options = {
+      webroot = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "Where the webroot of the HTTP vhost is located.";
+      };
+
+      validMin = mkOption {
+        type = types.int;
+        default = 2592000;
+        description = "Minimum remaining validity before renewal in seconds.";
+      };
+
+      renewInterval = mkOption {
+        type = types.str;
+        default = "weekly";
+        description = "Systemd calendar expression when to check for renewal. See systemd.time(7).";
+      };
+
+      email = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = "Contact email address for the CA to be able to reach you.";
+      };
+
+      plugins = mkOption {
+        type = types.listOf (types.enum [
+          "cert.der" "cert.pem" "chain.der" "chain.pem" "external_pem.sh"
+          "fullchain.der" "fullchain.pem" "key.der" "key.pem"
+        ]);
+        default = [ "fullchain.pem" "key.pem" ];
+        description = "Plugins to enable.";
+      };
+
+      extraDomains = mkOption {
+        default = [ ];
+        type = types.listOf types.str;
+        description = "More domains to include in the certificate.";
+        example = [ "example.com" "foo.example.com:/var/www/foo" ];
+      };
+    };
+  };
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+    services.simp_le = {
+      directory = mkOption {
+        default = "/etc/ssl";
+        type = types.str;
+        description = ''
+          Directory where certs will be stored by default.
+        '';
+      };
+
+      certs = mkOption {
+        default = { };
+        type = types.loaOf types.optionSet;
+        description = ''
+          Attribute set of certificates to get signed and renewed.
+        '';
+        options = [ certOpts ];
+        example = {
+          "foo.example.com" = {
+            webroot = "/var/www/challenges/";
+            email = "foo@example.com";
+            extraDomains = [ "www.example.com" "example.com" ];
+          };
+          "bar.example.com" = {
+            webroot = "/var/www/challenges/";
+            email = "bar@example.com";
+          };
+        };
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf (cfg.certs != { }) {
+
+    systemd.services = flip mapAttrs' cfg.certs (cert: data: nameValuePair
+      ("simp_le-${cert}")
+      ({
+        description = "simp_le cert renewal for ${cert}";
+        after = [ "network.target" ];
+        serviceConfig = {
+          Type = "oneshot";
+          SuccessExitStatus = "0 1";
+        };
+        preStart = ''
+          mkdir -p "${cfg.directory}/${cert}"
+        '';
+        script = ''
+          WEBROOT="${optionalString (data.webroot == null) data.webroot}"
+          cd "${cfg.directory}/${cert}"
+          ${pkgs.simp_le}/bin/simp_le -v \
+            ${concatMapStringsSep " " (p: "-f ${p}") data.plugins} \
+            -d ${cert} --default_root "$WEBROOT" \
+            ${concatMapStringsSep " " (p: "-d ${p}") data.extraDomains} \
+            ${optionalString (data.email != null) "--email ${data.email}"} \
+            --valid_min ${toString data.validMin}
+        '';
+      })
+    );
+
+    systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair
+      ("simp_le-${cert}")
+      ({
+        description = "timer for simp_le cert renewal of ${cert}";
+        wantedBy = [ "timers.target" ];
+        timerConfig = {
+          OnCalendar = data.renewInterval;
+          Unit = "simp_le-${cert}.service";
+        };
+      })
+    );
+
+  };
+
+}