summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2021-07-17 00:05:09 +0000
committerGitHub <noreply@github.com>2021-07-17 00:05:09 +0000
commite9ca8c279621fe99b77eb2d13ef876cfce2d8178 (patch)
treebb1877f7c8be11c8d11032fc54d0d4b686e5721b /nixos
parent049494e76e1be4c9a686bb0b0a5c73b15d1aa54c (diff)
parent8d3b6e10f19d75cdc8b4367b3321370e76641145 (diff)
downloadnixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.tar
nixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.tar.gz
nixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.tar.bz2
nixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.tar.lz
nixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.tar.xz
nixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.tar.zst
nixpkgs-e9ca8c279621fe99b77eb2d13ef876cfce2d8178.zip
Merge master into haskell-updates
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2111.section.xml16
-rw-r--r--nixos/doc/manual/release-notes/rl-2111.section.md4
-rw-r--r--nixos/modules/services/web-apps/wordpress.nix126
-rw-r--r--nixos/tests/wordpress.nix66
4 files changed, 173 insertions, 39 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
index b9967ffb982..fcaac9e8bec 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
@@ -546,6 +546,22 @@
           <literal>claws-mail-gtk2</literal> package.
         </para>
       </listitem>
+      <listitem>
+        <para>
+          The wordpress module provides a new interface which allows to
+          use different webservers with the new option
+          <link xlink:href="options.html#opt-services.wordpress.webserver"><literal>services.wordpress.webserver</literal></link>.
+          Currently <literal>httpd</literal> and
+          <literal>nginx</literal> are supported. The definitions of
+          wordpress sites should now be set in
+          <link xlink:href="options.html#opt-services.wordpress.sites"><literal>services.wordpress.sites</literal></link>.
+        </para>
+        <para>
+          Sites definitions that use the old interface are automatically
+          migrated in the new option. This backward compatibility will
+          be removed in 22.05.
+        </para>
+      </listitem>
     </itemizedlist>
   </section>
 </section>
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md
index 377dbf598d9..030f1d21818 100644
--- a/nixos/doc/manual/release-notes/rl-2111.section.md
+++ b/nixos/doc/manual/release-notes/rl-2111.section.md
@@ -135,3 +135,7 @@ In addition to numerous new and upgraded packages, this release has the followin
 - Sway: The terminal emulator `rxvt-unicode` is no longer installed by default via `programs.sway.extraPackages`. The current default configuration uses `alacritty` (and soon `foot`) so this is only an issue when using a customized configuration and not installing `rxvt-unicode` explicitly.
 
 - The `claws-mail` package now references the new GTK+ 3 release branch, major version 4. To use the GTK+ 2 releases, one can install the `claws-mail-gtk2` package.
+
+- The wordpress module provides a new interface which allows to use different webservers with the new option [`services.wordpress.webserver`](options.html#opt-services.wordpress.webserver).  Currently `httpd` and `nginx` are supported. The definitions of wordpress sites should now be set in [`services.wordpress.sites`](options.html#opt-services.wordpress.sites).
+
+  Sites definitions that use the old interface are automatically migrated in the new option. This backward compatibility will be removed in 22.05.
diff --git a/nixos/modules/services/web-apps/wordpress.nix b/nixos/modules/services/web-apps/wordpress.nix
index 775ecb3acaf..6f1ef815bc4 100644
--- a/nixos/modules/services/web-apps/wordpress.nix
+++ b/nixos/modules/services/web-apps/wordpress.nix
@@ -3,13 +3,18 @@
 let
   inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types;
   inherit (lib) any attrValues concatMapStringsSep flatten literalExample;
-  inherit (lib) mapAttrs mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString;
+  inherit (lib) filterAttrs mapAttrs mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString;
 
-  eachSite = config.services.wordpress;
+  cfg = migrateOldAttrs config.services.wordpress;
+  eachSite = cfg.sites;
   user = "wordpress";
-  group = config.services.httpd.group;
+  webserver = config.services.${cfg.webserver};
   stateDir = hostName: "/var/lib/wordpress/${hostName}";
 
+  # Migrate config.services.wordpress.<hostName> to config.services.wordpress.sites.<hostName>
+  oldSites = filterAttrs (o: _: o != "sites" && o != "webserver");
+  migrateOldAttrs = cfg: cfg // { sites = cfg.sites // oldSites cfg; };
+
   pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec {
     pname = "wordpress-${hostName}";
     version = src.version;
@@ -261,21 +266,48 @@ in
   # interface
   options = {
     services.wordpress = mkOption {
-      type = types.attrsOf (types.submodule siteOpts);
+      type = types.submodule {
+        # Used to support old interface
+        freeformType = types.attrsOf (types.submodule siteOpts);
+
+        # New interface
+        options.sites = mkOption {
+          type = types.attrsOf (types.submodule siteOpts);
+          default = {};
+          description = "Specification of one or more WordPress sites to serve";
+        };
+
+        options.webserver = mkOption {
+          type = types.enum [ "httpd" "nginx" ];
+          default = "httpd";
+          description = ''
+            Whether to use apache2 or nginx for virtual host management.
+
+            Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
+            See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
+
+            Further apache2 configuration can be done by adapting <literal>services.httpd.virtualHosts.&lt;name&gt;</literal>.
+            See <xref linkend="opt-services.httpd.virtualHosts"/> for further information.
+          '';
+        };
+      };
       default = {};
-      description = "Specification of one or more WordPress sites to serve via Apache.";
+      description = "Wordpress configuration";
     };
+
   };
 
   # implementation
-  config = mkIf (eachSite != {}) {
+  config = mkIf (eachSite != {}) (mkMerge [{
 
     assertions = mapAttrsToList (hostName: cfg:
       { assertion = cfg.database.createLocally -> cfg.database.user == user;
-        message = "services.wordpress.${hostName}.database.user must be ${user} if the database is to be automatically provisioned";
+        message = ''services.wordpress.sites."${hostName}".database.user must be ${user} if the database is to be automatically provisioned'';
       }
     ) eachSite;
 
+    warnings = mapAttrsToList (hostName: _: ''services.wordpress."${hostName}" is deprecated use services.wordpress.sites."${hostName}"'') (oldSites cfg);
+
     services.mysql = mkIf (any (v: v.database.createLocally) (attrValues eachSite)) {
       enable = true;
       package = mkDefault pkgs.mariadb;
@@ -289,14 +321,18 @@ in
 
     services.phpfpm.pools = mapAttrs' (hostName: cfg: (
       nameValuePair "wordpress-${hostName}" {
-        inherit user group;
+        inherit user;
+        group = webserver.group;
         settings = {
-          "listen.owner" = config.services.httpd.user;
-          "listen.group" = config.services.httpd.group;
+          "listen.owner" = webserver.user;
+          "listen.group" = webserver.group;
         } // cfg.poolConfig;
       }
     )) eachSite;
 
+  }
+
+  (mkIf (cfg.webserver == "httpd") {
     services.httpd = {
       enable = true;
       extraModules = [ "proxy_fcgi" ];
@@ -332,11 +368,13 @@ in
         '';
       } ]) eachSite;
     };
+  })
 
+  {
     systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [
-      "d '${stateDir hostName}' 0750 ${user} ${group} - -"
-      "d '${cfg.uploadsDir}' 0750 ${user} ${group} - -"
-      "Z '${cfg.uploadsDir}' 0750 ${user} ${group} - -"
+      "d '${stateDir hostName}' 0750 ${user} ${webserver.group} - -"
+      "d '${cfg.uploadsDir}' 0750 ${user} ${webserver.group} - -"
+      "Z '${cfg.uploadsDir}' 0750 ${user} ${webserver.group} - -"
     ]) eachSite);
 
     systemd.services = mkMerge [
@@ -350,7 +388,7 @@ in
           serviceConfig = {
             Type = "oneshot";
             User = user;
-            Group = group;
+            Group = webserver.group;
           };
       })) eachSite)
 
@@ -360,9 +398,65 @@ in
     ];
 
     users.users.${user} = {
-      group = group;
+      group = webserver.group;
       isSystemUser = true;
     };
+  }
 
-  };
+  (mkIf (cfg.webserver == "nginx") {
+    services.nginx = {
+      enable = true;
+      virtualHosts = mapAttrs (hostName: cfg: {
+        serverName = mkDefault hostName;
+        root = "${pkg hostName cfg}/share/wordpress";
+        extraConfig = ''
+          index index.php;
+        '';
+        locations = {
+          "/" = {
+            priority = 200;
+            extraConfig = ''
+              try_files $uri $uri/ /index.php$is_args$args;
+            '';
+          };
+          "~ \\.php$" = {
+            priority = 500;
+            extraConfig = ''
+              fastcgi_split_path_info ^(.+\.php)(/.+)$;
+              fastcgi_pass unix:${config.services.phpfpm.pools."wordpress-${hostName}".socket};
+              fastcgi_index index.php;
+              include "${config.services.nginx.package}/conf/fastcgi.conf";
+              fastcgi_param PATH_INFO $fastcgi_path_info;
+              fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
+              # Mitigate https://httpoxy.org/ vulnerabilities
+              fastcgi_param HTTP_PROXY "";
+              fastcgi_intercept_errors off;
+              fastcgi_buffer_size 16k;
+              fastcgi_buffers 4 16k;
+              fastcgi_connect_timeout 300;
+              fastcgi_send_timeout 300;
+              fastcgi_read_timeout 300;
+            '';
+          };
+          "~ /\\." = {
+            priority = 800;
+            extraConfig = "deny all;";
+          };
+          "~* /(?:uploads|files)/.*\\.php$" = {
+            priority = 900;
+            extraConfig = "deny all;";
+          };
+          "~* \\.(js|css|png|jpg|jpeg|gif|ico)$" = {
+            priority = 1000;
+            extraConfig = ''
+              expires max;
+              log_not_found off;
+            '';
+          };
+        };
+      }) eachSite;
+    };
+  })
+
+  ]);
 }
diff --git a/nixos/tests/wordpress.nix b/nixos/tests/wordpress.nix
index a5c10c2de74..45c58b5b65c 100644
--- a/nixos/tests/wordpress.nix
+++ b/nixos/tests/wordpress.nix
@@ -10,48 +10,68 @@ import ./make-test-python.nix ({ pkgs, ... }:
     ];
   };
 
-  machine =
-    { ... }:
-    { services.httpd.adminAddr = "webmaster@site.local";
+  nodes = {
+    wp_httpd = { ... }: {
+      services.httpd.adminAddr = "webmaster@site.local";
       services.httpd.logPerVirtualHost = true;
 
-      services.wordpress."site1.local" = {
-        database.tablePrefix = "site1_";
+      services.wordpress = {
+        # Test support for old interface
+        "site1.local" = {
+          database.tablePrefix = "site1_";
+        };
+        sites = {
+          "site2.local" = {
+            database.tablePrefix = "site2_";
+          };
+        };
       };
 
-      services.wordpress."site2.local" = {
-        database.tablePrefix = "site2_";
+      networking.firewall.allowedTCPPorts = [ 80 ];
+      networking.hosts."127.0.0.1" = [ "site1.local" "site2.local" ];
+    };
+
+    wp_nginx = { ... }: {
+      services.wordpress.webserver = "nginx";
+      services.wordpress.sites = {
+        "site1.local" = {
+          database.tablePrefix = "site1_";
+        };
+        "site2.local" = {
+          database.tablePrefix = "site2_";
+        };
       };
 
+      networking.firewall.allowedTCPPorts = [ 80 ];
       networking.hosts."127.0.0.1" = [ "site1.local" "site2.local" ];
     };
+  };
 
   testScript = ''
     import re
 
     start_all()
 
-    machine.wait_for_unit("httpd")
-
-    machine.wait_for_unit("phpfpm-wordpress-site1.local")
-    machine.wait_for_unit("phpfpm-wordpress-site2.local")
+    wp_httpd.wait_for_unit("httpd")
+    wp_nginx.wait_for_unit("nginx")
 
     site_names = ["site1.local", "site2.local"]
 
-    with subtest("website returns welcome screen"):
+    for machine in (wp_httpd, wp_nginx):
         for site_name in site_names:
-            assert "Welcome to the famous" in machine.succeed(f"curl -fL {site_name}")
+            machine.wait_for_unit(f"phpfpm-wordpress-{site_name}")
 
-    with subtest("wordpress-init went through"):
-        for site_name in site_names:
-            info = machine.get_unit_info(f"wordpress-init-{site_name}")
-            assert info["Result"] == "success"
+            with subtest("website returns welcome screen"):
+                assert "Welcome to the famous" in machine.succeed(f"curl -L {site_name}")
 
-    with subtest("secret keys are set"):
-        pattern = re.compile(r"^define.*NONCE_SALT.{64,};$", re.MULTILINE)
-        for site_name in site_names:
-            assert pattern.search(
-                machine.succeed(f"cat /var/lib/wordpress/{site_name}/secret-keys.php")
-            )
+            with subtest("wordpress-init went through"):
+                info = machine.get_unit_info(f"wordpress-init-{site_name}")
+                assert info["Result"] == "success"
+
+            with subtest("secret keys are set"):
+                pattern = re.compile(r"^define.*NONCE_SALT.{64,};$", re.MULTILINE)
+                assert pattern.search(
+                    machine.succeed(f"cat /var/lib/wordpress/{site_name}/secret-keys.php")
+                )
   '';
 })