summary refs log tree commit diff
path: root/nixos/modules/services/web-servers
diff options
context:
space:
mode:
authorWout Mertens <Wout.Mertens@gmail.com>2017-08-07 16:46:28 +0200
committerGitHub <noreply@github.com>2017-08-07 16:46:28 +0200
commit339330b32290d284dbf201e4b31ee35cee1ae1a5 (patch)
tree7c9ec77885e8733a07ea3bf205dc9bfb9b261a74 /nixos/modules/services/web-servers
parent4f80406fdd762a1244c7952a04179f32ad6b451c (diff)
parenta912a6a291eaa5f6a2ad9143c9e276779c357a41 (diff)
downloadnixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.tar
nixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.tar.gz
nixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.tar.bz2
nixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.tar.lz
nixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.tar.xz
nixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.tar.zst
nixlib-339330b32290d284dbf201e4b31ee35cee1ae1a5.zip
Merge pull request #27426 from rnhmjoj/nginx
nginx: make enabling SSL port-specific
Diffstat (limited to 'nixos/modules/services/web-servers')
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix66
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix51
2 files changed, 91 insertions, 26 deletions
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 2f691b0e9df9..293fa77107e3 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -129,16 +129,32 @@ let
   '';
 
   vhosts = concatStringsSep "\n" (mapAttrsToList (vhostName: vhost:
-      let
-        ssl = vhost.enableSSL || vhost.forceSSL;
-        defaultPort = if ssl then 443 else 80;
-
-        listenString = { addr, port, ... }:
-          "listen ${addr}:${toString (if port != null then port else defaultPort)} "
+    let
+        ssl = with vhost; addSSL || onlySSL || enableSSL;
+
+        defaultListen = with vhost;
+          if listen != [] then listen
+          else if onlySSL || enableSSL then
+               singleton                          { addr = "0.0.0.0"; port = 443; ssl = true;  }
+               ++ optional enableIPv6             { addr = "[::]";    port = 443; ssl = true;  }
+          else singleton                          { addr = "0.0.0.0"; port = 80;  ssl = false; }
+               ++ optional enableIPv6             { addr = "[::]";    port = 80;  ssl = false; }
+               ++ optional addSSL                 { addr = "0.0.0.0"; port = 443; ssl = true;  }
+               ++ optional (enableIPv6 && addSSL) { addr = "[::]";    port = 443; ssl = true;  };
+
+        hostListen =
+          if !vhost.forceSSL
+            then defaultListen
+            else filter (x: x.ssl) defaultListen;
+
+        listenString = { addr, port, ssl, ... }:
+          "listen ${addr}:${toString port} "
           + optionalString ssl "ssl http2 "
-          + optionalString vhost.default "default_server"
+          + optionalString vhost.default "default_server "
           + ";";
 
+        redirectListen = filter (x: !x.ssl) defaultListen;
+
         redirectListenString = { addr, ... }:
           "listen ${addr}:80 ${optionalString vhost.default "default_server"};";
 
@@ -159,7 +175,7 @@ let
       in ''
         ${optionalString vhost.forceSSL ''
           server {
-            ${concatMapStringsSep "\n" redirectListenString vhost.listen}
+            ${concatMapStringsSep "\n" redirectListenString redirectListen}
 
             server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
             ${optionalString vhost.enableACME acmeLocation}
@@ -170,7 +186,7 @@ let
         ''}
 
         server {
-          ${concatMapStringsSep "\n" listenString vhost.listen}
+          ${concatMapStringsSep "\n" listenString hostListen}
           server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
           ${optionalString vhost.enableACME acmeLocation}
           ${optionalString (vhost.root != null) "root ${vhost.root};"}
@@ -425,6 +441,7 @@ in
         example = literalExample ''
           {
             "hydra.example.com" = {
+              addSSL = true;
               forceSSL = true;
               enableACME = true;
               locations."/" = {
@@ -441,11 +458,40 @@ in
   config = mkIf cfg.enable {
     # TODO: test user supplied config file pases syntax test
 
-    assertions = let hostOrAliasIsNull = l: l.root == null || l.alias == null; in [
+    warnings =
+    let
+      deprecatedSSL = name: config: optional config.enableSSL
+      ''
+        config.services.nginx.virtualHosts.<name>.enableSSL is deprecated,
+        use config.services.nginx.virtualHosts.<name>.onlySSL instead.
+      '';
+
+    in flatten (mapAttrsToList deprecatedSSL virtualHosts);
+
+    assertions =
+    let
+      hostOrAliasIsNull = l: l.root == null || l.alias == null;
+    in [
       {
         assertion = all (host: all hostOrAliasIsNull (attrValues host.locations)) (attrValues virtualHosts);
         message = "Only one of nginx root or alias can be specified on a location.";
       }
+
+      {
+        assertion = all (conf: with conf; !(addSSL && (onlySSL || enableSSL))) (attrValues virtualHosts);
+        message = ''
+          Options services.nginx.service.virtualHosts.<name>.addSSL and
+          services.nginx.virtualHosts.<name>.onlySSL are mutually esclusive
+        '';
+      }
+
+      {
+        assertion = all (conf: with conf; forceSSL -> addSSL) (attrValues virtualHosts);
+        message = ''
+          Option services.nginx.virtualHosts.<name>.forceSSL requires
+          services.nginx.virtualHosts.<name>.addSSL set to true.
+        '';
+      }
     ];
 
     systemd.services.nginx = {
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index 60260512bc2f..362f8ee90524 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -27,25 +27,21 @@ with lib;
     };
 
     listen = mkOption {
-      type = with types; listOf (submodule {
-        options = {
-          addr = mkOption { type = str; description = "IP address."; };
-          port = mkOption { type = nullOr int; description = "Port number."; };
-        };
-      });
-      default =
-        [ { addr = "0.0.0.0"; port = null; } ]
-        ++ optional config.networking.enableIPv6
-          { addr = "[::]"; port = null; };
+      type = with types; listOf (submodule { options = {
+        addr = mkOption { type = str;  description = "IP address.";  };
+        port = mkOption { type = int;  description = "Port number."; default = 80; };
+        ssl  = mkOption { type = bool; description = "Enable SSL.";  default = false; };
+      }; });
+      default = [];
       example = [
-        { addr = "195.154.1.1"; port = 443; }
-        { addr = "192.168.1.2"; port = 443; }
+        { addr = "195.154.1.1"; port = 443; ssl = true;}
+        { addr = "192.154.1.1"; port = 80; }
       ];
       description = ''
         Listen addresses and ports for this virtual host.
         IPv6 addresses must be enclosed in square brackets.
-        Setting the port to <literal>null</literal> defaults
-        to 80 for http and 443 for https (i.e. when enableSSL is set).
+        Note: this option overrides <literal>addSSL</literal>
+        and <literal>onlySSL</literal>.
       '';
     };
 
@@ -70,16 +66,39 @@ with lib;
       '';
     };
 
+    addSSL = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable HTTPS in addition to plain HTTP. This will set defaults for
+        <literal>listen</literal> to listen on all interfaces on the respective default
+        ports (80, 443).
+      '';
+    };
+
+    onlySSL = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable HTTPS and reject plain HTTP connections. This will set
+        defaults for <literal>listen</literal> to listen on all interfaces on port 443.
+      '';
+    };
+
     enableSSL = mkOption {
       type = types.bool;
+      visible = false;
       default = false;
-      description = "Whether to enable SSL (https) support.";
     };
 
     forceSSL = mkOption {
       type = types.bool;
       default = false;
-      description = "Whether to always redirect to https.";
+      description = ''
+        Whether to add a separate nginx server block that permanently redirects (301)
+        all plain HTTP traffic to HTTPS. This option needs <literal>addSSL</literal>
+        to be set to true.
+      '';
     };
 
     sslCertificate = mkOption {