From 4676983990b1d35676eba19cee9e24a16e0f60d7 Mon Sep 17 00:00:00 2001 From: Tristan Helmich Date: Mon, 25 Jan 2016 19:36:21 +0100 Subject: nginx module: Add ACME support for ssl sites --- .../modules/services/web-servers/nginx/default.nix | 27 +++++++++++++++++----- .../services/web-servers/nginx/vhost-options.nix | 14 ++++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'nixos/modules/services/web-servers') diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index ab5657a9aa92..a84a3c9f2a2a 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -4,7 +4,13 @@ with lib; let cfg = config.services.nginx; - nginx = cfg.package; + virtualHosts = mapAttrs (vhostName: vhostConfig: + vhostConfig // (optionalAttrs vhostConfig.enableACME { + sslCertificate = "/var/lib/acme/${vhostName}/fullchain.pem"; + sslCertificateKey = "/var/lib/acme/${vhostName}/key.pem"; + }) + ) cfg.virtualHosts; + configFile = pkgs.writeText "nginx.conf" '' user ${cfg.user} ${cfg.group}; error_log stderr; @@ -72,21 +78,23 @@ let port = if vhost.port != null then vhost.port else (if ssl then 443 else 80); listenString = toString port + optionalString ssl " ssl spdy"; in '' - ${if vhost.forceSSL then '' + ${optionalString vhost.forceSSL '' server { listen 80; listen [::]:80; server_name ${serverName} ${concatStringsSep " " vhost.serverAliases}; + ${optionalString vhost.enableACME "location /.well-known/acme-challenge { root ${vhost.acmeRoot}; }"} return 301 https://$host${optionalString (port != 443) ":${port}"}$request_uri; } - '' else ""} + ''} server { listen ${listenString}; listen [::]:${listenString}; server_name ${serverName} ${concatStringsSep " " vhost.serverAliases}; + ${optionalString vhost.enableACME "location /.well-known/acme-challenge { root ${vhost.acmeRoot}; }"} ${optionalString (vhost.root != null) "root ${vhost.root};"} ${optionalString (vhost.globalRedirect != null) '' return 301 https://${vhost.globalRedirect}$request_uri; @@ -101,7 +109,7 @@ let ${vhost.extraConfig} } '' - ) cfg.virtualHosts); + ) virtualHosts); genLocations = locations: concatStringsSep "\n" (mapAttrsToList (location: config: '' location ${location} { ${optionalString (config.proxyPass != null) "proxy_pass ${config.proxyPass};"} @@ -202,7 +210,6 @@ in description = "Nginx Web Server"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - path = [ nginx ]; preStart = '' mkdir -p ${cfg.stateDir}/logs @@ -210,7 +217,7 @@ in chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} ''; serviceConfig = { - ExecStart = "${nginx}/bin/nginx -c ${configFile} -p ${cfg.stateDir}"; + ExecStart = "${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; Restart = "always"; RestartSec = "10s"; @@ -218,6 +225,14 @@ in }; }; + security.acme.certs = mapAttrs (vhostName: vhostConfig: { + webroot = vhostConfig.acmeRoot; + extraDomains = genAttrs vhostConfig.serverAliases (alias: { + "${alias}" = null; + }); + }) virtualHosts; + + users.extraUsers = optionalAttrs (cfg.user == "nginx") (singleton { name = "nginx"; group = cfg.group; diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix index 2acb3743677d..5fa3b18c24f0 100644 --- a/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -26,6 +26,18 @@ with lib; ''; }; + enableACME = mkOption { + type = types.bool; + default = false; + description = "Whether to ask Let's Encrypt to sign a certificate for this vhost."; + }; + + acmeRoot = mkOption { + type = types.str; + default = "/var/lib/acme/acme-challenge"; + description = "Directory to store certificates and keys managed by the ACME service."; + }; + enableSSL = mkOption { type = types.bool; default = false; @@ -44,7 +56,7 @@ with lib; description = "Path to server SSL certificate."; }; - sslCertificateKey= mkOption { + sslCertificateKey = mkOption { type = types.path; example = "/var/host.key"; description = "Path to server SSL certificate key."; -- cgit 1.4.1