about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorJonas Heinrich <onny@project-insanity.org>2023-01-14 13:49:51 +0100
committerJonas Heinrich <onny@project-insanity.org>2023-01-16 14:06:10 +0100
commitc51dd423118cb4c85b7682cbae2f27188aeb11bc (patch)
tree48671879e79074bf0ce1370b258f02a75aa88562 /nixos
parent95338455f754138578c1f6f127667e4ec6d52501 (diff)
nixos/wordpress: add settings option
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2305.section.xml10
-rw-r--r--nixos/doc/manual/release-notes/rl-2305.section.md2
-rw-r--r--nixos/modules/services/web-apps/wordpress.nix113
3 files changed, 101 insertions, 24 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
index 12023ce0797cc..66e53106cbce8 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
@@ -339,6 +339,16 @@
       </listitem>
       <listitem>
         <para>
+          The <literal>wordpress</literal> service now takes
+          configuration via the
+          <literal>services.wordpress.sites.&lt;name&gt;.settings</literal>
+          attribute set, <literal>extraConfig</literal> is still
+          available to append additional text to
+          <literal>wp-config.php</literal>.
+        </para>
+      </listitem>
+      <listitem>
+        <para>
           To reduce closure size in
           <literal>nixos/modules/profiles/minimal.nix</literal> profile
           disabled installation documentations and manuals. Also
diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md
index c2ba8658d69c3..98e7c6455c23f 100644
--- a/nixos/doc/manual/release-notes/rl-2305.section.md
+++ b/nixos/doc/manual/release-notes/rl-2305.section.md
@@ -92,6 +92,8 @@ In addition to numerous new and upgraded packages, this release has the followin
   The `{aclUse,superUser,disableActions}` attributes have been renamed, `pluginsConfig` now also accepts an attribute set of booleans, passing plain PHP is deprecated.
   Same applies to `acl` which now also accepts structured settings.
 
+- The `wordpress` service now takes configuration via the `services.wordpress.sites.<name>.settings` attribute set, `extraConfig` is still available to append  additional text to `wp-config.php`.
+
 - To reduce closure size in `nixos/modules/profiles/minimal.nix` profile disabled installation documentations and manuals. Also disabled `logrotate` and `udisks2` services.
 
 - The minimal ISO image now uses the `nixos/modules/profiles/minimal.nix` profile.
diff --git a/nixos/modules/services/web-apps/wordpress.nix b/nixos/modules/services/web-apps/wordpress.nix
index 43a6d7e75dc6c..416ad8556bdda 100644
--- a/nixos/modules/services/web-apps/wordpress.nix
+++ b/nixos/modules/services/web-apps/wordpress.nix
@@ -38,29 +38,53 @@ let
     '';
   };
 
-  wpConfig = hostName: cfg: pkgs.writeText "wp-config-${hostName}.php" ''
-    <?php
-      define('DB_NAME', '${cfg.database.name}');
-      define('DB_HOST', '${cfg.database.host}:${if cfg.database.socket != null then cfg.database.socket else toString cfg.database.port}');
-      define('DB_USER', '${cfg.database.user}');
-      ${optionalString (cfg.database.passwordFile != null) "define('DB_PASSWORD', file_get_contents('${cfg.database.passwordFile}'));"}
-      define('DB_CHARSET', 'utf8');
-      $table_prefix  = '${cfg.database.tablePrefix}';
-
-      require_once('${stateDir hostName}/secret-keys.php');
-
-      # wordpress is installed onto a read-only file system
-      define('DISALLOW_FILE_EDIT', true);
-      define('AUTOMATIC_UPDATER_DISABLED', true);
-
-      ${cfg.extraConfig}
-
-      if ( !defined('ABSPATH') )
-        define('ABSPATH', dirname(__FILE__) . '/');
+  mergeConfig = cfg: {
+    # wordpress is installed onto a read-only file system
+    DISALLOW_FILE_EDIT = true;
+    AUTOMATIC_UPDATER_DISABLED = true;
+    DB_NAME = cfg.database.name;
+    DB_HOST = "${cfg.database.host}:${if cfg.database.socket != null then cfg.database.socket else toString cfg.database.port}";
+    DB_USER = cfg.database.user;
+    DB_CHARSET = "utf8";
+    # Always set DB_PASSWORD even when passwordFile is not set. This is the
+    # default Wordpress behaviour.
+    DB_PASSWORD =  if (cfg.database.passwordFile != null) then { _file = cfg.database.passwordFile; } else "";
+  } // cfg.settings;
+
+  wpConfig = hostName: cfg: let
+    conf_gen = c: mapAttrsToList (k: v: "define('${k}', ${mkPhpValue v});") cfg.mergedConfig;
+  in pkgs.writeTextFile {
+    name = "wp-config-${hostName}.php";
+    text = ''
+      <?php
+        $table_prefix  = '${cfg.database.tablePrefix}';
+
+        require_once('${stateDir hostName}/secret-keys.php');
+
+        ${cfg.extraConfig}
+        ${concatStringsSep "\n" (conf_gen cfg.mergedConfig)}
+
+        if ( !defined('ABSPATH') )
+          define('ABSPATH', dirname(__FILE__) . '/');
+
+        require_once(ABSPATH . 'wp-settings.php');
+      ?>
+    '';
+    checkPhase = "${pkgs.php81}/bin/php --syntax-check $target";
+  };
 
-      require_once(ABSPATH . 'wp-settings.php');
-    ?>
-  '';
+  mkPhpValue = v: let
+    isHasAttr = s: isAttrs v && hasAttr s v;
+  in
+    if isString v then escapeShellArg v
+    # NOTE: If any value contains a , (comma) this will not get escaped
+    else if isList v && any lib.strings.isCoercibleToString v then escapeShellArg (concatMapStringsSep "," toString v)
+    else if isInt v then toString v
+    else if isBool v then boolToString v
+    else if isHasAttr "_file" then "trim(file_get_contents(${lib.escapeShellArg v._file}))"
+    else if isHasAttr "_raw" then v._raw
+    else abort "The Wordpress config value ${lib.generators.toPretty {} v} can not be encoded."
+  ;
 
   secretsVars = [ "AUTH_KEY" "SECURE_AUTH_KEY" "LOGGED_IN_KEY" "NONCE_KEY" "AUTH_SALT" "SECURE_AUTH_SALT" "LOGGED_IN_SALT" "NONCE_SALT" ];
   secretsScript = hostStateDir: ''
@@ -77,7 +101,7 @@ let
     fi
   '';
 
-  siteOpts = { lib, name, ... }:
+  siteOpts = { lib, name, config, ... }:
     {
       options = {
         package = mkOption {
@@ -283,6 +307,42 @@ let
           '';
         };
 
+        settings = mkOption {
+          type = types.attrsOf types.anything;
+          default = {};
+          description = lib.mdDoc ''
+            Structural Wordpress configuration.
+            Refer to <https://developer.wordpress.org/apis/wp-config-php>
+            for details and supported values.
+          '';
+          example = literalExpression ''
+            {
+              WP_DEFAULT_THEME = "twentytwentytwo";
+              WP_SITEURL = "https://example.org";
+              WP_HOME = "https://example.org";
+              WP_DEBUG = true;
+              WP_DEBUG_DISPLAY = true;
+              WPLANG = "de_DE";
+              FORCE_SSL_ADMIN = true;
+              AUTOMATIC_UPDATER_DISABLED = true;
+            }
+          '';
+        };
+
+        mergedConfig = mkOption {
+          readOnly = true;
+          default = mergeConfig config;
+          defaultText = literalExpression ''
+            {
+              DISALLOW_FILE_EDIT = true;
+              AUTOMATIC_UPDATER_DISABLED = true;
+            }
+          '';
+          description = lib.mdDoc ''
+            Read only representation of the final configuration.
+          '';
+        };
+
         extraConfig = mkOption {
           type = types.lines;
           default = "";
@@ -290,11 +350,16 @@ let
             Any additional text to be appended to the wp-config.php
             configuration file. This is a PHP script. For configuration
             settings, see <https://codex.wordpress.org/Editing_wp-config.php>.
+
+            **Note**: Please pass structured settings via
+            `services.wordpress.sites.${name}.settings` instead.
           '';
           example = ''
-            define( 'AUTOSAVE_INTERVAL', 60 ); // Seconds
+            @ini_set( 'log_errors', 'Off' );
+            @ini_set( 'display_errors', 'On' );
           '';
         };
+
       };
 
       config.virtualHost.hostName = mkDefault name;