Skip to content

Commit

Permalink
nginx: make enabling SSL port-specific
Browse files Browse the repository at this point in the history
  • Loading branch information
rnhmjoj committed Jul 27, 2017
1 parent e40f3be commit a912a6a
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 26 deletions.
66 changes: 56 additions & 10 deletions nixos/modules/services/web-servers/nginx/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,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"};";

Expand All @@ -152,7 +168,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}
Expand All @@ -163,7 +179,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};"}
Expand Down Expand Up @@ -392,6 +408,7 @@ in
example = literalExample ''
{
"hydra.example.com" = {
addSSL = true;
forceSSL = true;
enableACME = true;
locations."/" = {
Expand All @@ -408,11 +425,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 = {
Expand Down
51 changes: 35 additions & 16 deletions nixos/modules/services/web-servers/nginx/vhost-options.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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>.
'';
};

Expand All @@ -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 {
Expand Down

0 comments on commit a912a6a

Please sign in to comment.