summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorThomas Strobel <ts468@cam.ac.uk>2015-08-03 19:16:38 +0200
committerThomas Strobel <ts468@cam.ac.uk>2015-08-28 09:33:08 +0200
commite6f0cd336dd286232136503c02598372162f1b8d (patch)
treecca60fab54782a9cc300610dbc2c1866681a3aa4 /nixos
parent7f3566da8a74bcb013503c7439d8ec9568b6d8b8 (diff)
downloadnixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.tar
nixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.tar.gz
nixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.tar.bz2
nixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.tar.lz
nixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.tar.xz
nixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.tar.zst
nixpkgs-e6f0cd336dd286232136503c02598372162f1b8d.zip
reverse_proxy module: helper to run nginx as reverse proxy
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix31
-rw-r--r--nixos/modules/services/web-servers/nginx/reverse_proxy.nix233
3 files changed, 263 insertions, 2 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 8ee54ce7ef4..6734fa0b862 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -393,6 +393,7 @@
   ./services/web-servers/lighttpd/default.nix
   ./services/web-servers/lighttpd/gitweb.nix
   ./services/web-servers/nginx/default.nix
+  ./services/web-servers/nginx/reverse_proxy.nix
   ./services/web-servers/phpfpm.nix
   ./services/web-servers/shellinabox.nix
   ./services/web-servers/tomcat.nix
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index fe50c182bfe..b16f701a0c9 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -11,7 +11,9 @@ let
     ${cfg.config}
     ${optionalString (cfg.httpConfig != "") ''
     http {
-      ${cfg.httpConfig}
+    ${cfg.httpConfig}
+    ${cfg.httpServers}
+    ${cfg.httpDefaultServer}
     }
     ''}
     ${cfg.appendConfig}
@@ -60,7 +62,32 @@ in
       httpConfig = mkOption {
         type = types.lines;
         default = "";
-        description = "Configuration lines to be appended inside of the http {} block.";
+        description = ''
+          Configuration lines to be placed at the top inside of
+          the http {} block. The option is intended to be used for
+          the default configuration of the servers.
+        '';
+      };
+
+      httpServers = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Configuration lines to be placed inside of the http {}
+          block. The option is intended to be used for defining
+          individual servers.
+        '';
+      };
+
+      httpDefaultServer = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Configuration lines to be placed at the bottom inside of
+          the http {} block. The option is intended to be used for
+          setting up the default servers. The default server is used
+          if no previously specified server matches a request.
+        '';
       };
 
       stateDir = mkOption {
diff --git a/nixos/modules/services/web-servers/nginx/reverse_proxy.nix b/nixos/modules/services/web-servers/nginx/reverse_proxy.nix
new file mode 100644
index 00000000000..c21406dff29
--- /dev/null
+++ b/nixos/modules/services/web-servers/nginx/reverse_proxy.nix
@@ -0,0 +1,233 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.nginx;
+
+  defaultSSL = cfg.httpDefaultKey != null || cfg.httpDefaultCertificate != null;
+
+  validSSL = key: cert: cert != null && key != null || cert == null && key == null;
+
+in
+
+{
+  options = {
+
+    services.nginx = {
+
+      reverseProxies = mkOption {
+        type = types.attrsOf (types.submodule (
+          {
+            options = {
+              proxy = mkOption {
+                type = types.str;
+                default = [];
+                description = ''
+                  Exclude files and directories matching these patterns.
+                '';
+              };
+
+              key = mkOption {
+                type = types.nullOr types.path;
+                default = null;
+                description = ''
+                  Exclude files and directories matching these patterns.
+                '';
+              };
+
+              certificate = mkOption {
+                type = types.nullOr types.path;
+                default = null;
+                description = ''
+                  Exclude files and directories matching these patterns.
+                '';
+              };
+            };
+          }
+        ));
+
+        default = {};
+
+        example = literalExample ''
+          {
+            "hydra.yourdomain.org" =
+              { proxy = "localhost:3000";
+                key = "/etc/nixos/certs/hydra_key.key";
+                certificate = "/etc/nixos/certs/hydra_cert.crt";
+              };
+          }
+        '';
+
+        description = ''
+          A reverse proxy server configuration is created for every attribute.
+          The attribute name corresponds to the name the server is listening to,
+          and the proxy option defines the target to forward the requests to.
+          If a key and certificate are given, then the server is secured through
+          a SSL connection. Non-SSL requests on port 80 are automatically
+          re-directed to the SSL server on port 443.
+        '';
+      };
+
+      httpDefaultKey = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/etc/nixos/certs/defaut_key.key";
+        description = ''
+           Key of SSL certificate for default server.
+           The default certificate is presented by the default server during
+           the SSL handshake when no specialized server configuration matches
+           a request.
+           A default SSL certificate is also helpful if browsers do not
+           support the TLS Server Name Indication extension (SNI, RFC 6066).
+        '';
+      };
+
+      httpDefaultCertificate = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/etc/nixos/certs/defaut_key.crt";
+        description = ''
+           SSL certificate for default server.
+           The default certificate is presented by the default server during
+           the SSL handshake when no specialized server configuration matches
+           a request.
+           A default SSL certificate is also helpful if browsers do not
+           support the TLS Server Name Indication extension (SNI, RFC 6066).
+        '';
+      };
+
+    };
+
+  };
+
+
+  config = mkIf (cfg.reverseProxies != {}) {
+
+    assertions = [
+      { assertion = all id (mapAttrsToList (n: v: validSSL v.certificate v.key) cfg.reverseProxies);
+        message = ''
+          One (or more) reverse proxy configurations specify only either
+          the key option or the certificate option. Both certificate
+          with associated key have to be configured to enable SSL for a
+          server configuration.
+
+          services.nginx.reverseProxies: ${toString cfg.reverseProxies}
+        '';
+      }
+      { assertion = validSSL cfg.httpDefaultCertificate cfg.httpDefaultKey;
+        message = ''
+          The default server configuration specifies only either the key
+          option or the certificate option. Both httpDefaultCertificate
+          with associated httpDefaultKey have to be configured to enable
+          SSL for the default server configuration.
+
+          services.nginx.httpDefaultCertificate: ${toString cfg.httpDefaultCertificate}
+
+          services.nginx.httpDefaultKey : ${toString cfg.httpDefaultKey}
+        '';
+      }
+    ];
+
+    services.nginx.config = mkBefore ''
+      worker_processes 1;
+      error_log logs/error.log debug;
+      pid logs/nginx.pid;
+      events {
+         worker_connections  1024;
+      }
+    '';
+
+    services.nginx.httpConfig = mkBefore ''
+      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                '$status $body_bytes_sent "$http_referer" '
+                '"$http_user_agent" "$http_x_forwarded_for"';
+      access_log  logs/access.log  main;
+      sendfile        on;
+      tcp_nopush      on;
+      keepalive_timeout  10;
+      gzip            on;
+
+      ${lib.optionalString defaultSSL ''
+      ssl_session_cache    shared:SSL:10m;
+      ssl_session_timeout  10m;
+      ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
+      ssl_ciphers          HIGH:!aNULL:!MD5;
+      ssl_certificate      ${cfg.httpDefaultCertificate};
+      ssl_certificate_key  ${cfg.httpDefaultKey};
+      ''}
+    '';
+
+    services.nginx.httpDefaultServer = mkBefore ''
+      # reject as default policy
+      server {
+          listen 80 default_server;
+          listen [::]:80 default_server;
+          ${lib.optionalString defaultSSL "listen 443 default_server ssl;"}
+          return      444;
+      }
+    '';
+
+    services.nginx.httpServers =
+      let
+        useSSL = certificate: key: certificate != null && key != null;
+
+        server = servername: proxy: certificate: key: useSSL: ''
+          server {
+            server_name ${servername};
+            keepalive_timeout    70;
+
+            ${if !useSSL then ''
+            listen 80;
+            listen [::]:80;
+            '' else ''
+            listen 443 ssl;
+            ssl_session_cache    shared:SSL:10m;
+            ssl_session_timeout  10m;
+            ssl_certificate      ${certificate};
+            ssl_certificate_key  ${key};
+            ''}
+
+            location / {
+              proxy_pass ${proxy};
+
+              ### force timeouts if one of backend is dead ##
+              proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+
+              ### Set headers ####
+              proxy_set_header        Accept-Encoding   "";
+              proxy_set_header        Host            $host;
+              proxy_set_header        X-Real-IP       $remote_addr;
+              proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
+
+              ${lib.optionalString useSSL ''
+              ### Most PHP, Python, Rails, Java App can use this header ###
+              #proxy_set_header X-Forwarded-Proto https;##
+              #This is better##
+              proxy_set_header        X-Forwarded-Proto $scheme;
+              add_header              Front-End-Https   on;
+              ''}
+
+              ### By default we don't want to redirect it ####
+              proxy_redirect     off;
+              proxy_buffering    off;
+            }
+          }
+
+          ${lib.optionalString useSSL ''
+          # redirect http to https
+          server {
+              listen 80;
+              listen [::]:80;
+              server_name ${servername};
+              return 301 https://$server_name$request_uri;
+          }
+          ''}
+        '';
+      in
+      concatStrings (mapAttrsToList (n: v: server n v.proxy v.certificate v.key (useSSL v.proxy v.certificate)) cfg.reverseProxies);
+
+  };
+
+}