Change:
Some wordpress applications, , assume this variable is present, even if they do not use it. I am unclear if this is undefined behaviour or a convention, but I have had to set to get wordpress to not crash after activating the plugin. Could we use or as the fallback, instead of leaving it undefined? Steps to reproduce the behavior: Please run and paste the result.
We should check what the Wordpress installer does in this case and if is usually written into
I have not manually tested it, but as best as I can grok, they set whatever the user provides, so seems more canonical?
Tested in a VM and you're right, setting DB_PASSWORD to '' seems to be the default case ! We should fix that and add a comment in the Wordpress module that this is the default behavior. Thanks for pointing that issue out!
Trying to fix this in this PR

Discussion:
</listitem> <listitem> <para> <ins> 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> </ins> To reduce closure size in <literal>nixos/modules/profiles/minimal.nix</literal> profile disabled installation documentations and manuals. Also

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. <ins> - 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`. </ins> - 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.

''; }; <del> 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__) . '/'); </del> <ins> 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"; }; </ins> <del> require_once(ABSPATH . 'wp-settings.php'); ?> ''; </del> <ins> 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." ; </ins> secretsVars = [ "AUTH_KEY" "SECURE_AUTH_KEY" "LOGGED_IN_KEY" "NONCE_KEY" "AUTH_SALT" "SECURE_AUTH_SALT" "LOGGED_IN_SALT" "NONCE_SALT" ]; secretsScript = hostStateDir: ''

fi ''; <del> siteOpts = { lib, name, ... }: </del> <ins> siteOpts = { lib, name, config, ... }: </ins> { options = { package = mkOption {

''; }; <ins> 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. ''; }; </ins> extraConfig = mkOption { type = types.lines; default = "";

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>. <ins> **Note**: Please pass structured settings via `services.wordpress.sites.${name}.settings` instead. </ins> ''; example = '' <del> define( 'AUTOSAVE_INTERVAL', 60 ); // Seconds </del> <ins> @ini_set( 'log_errors', 'Off' ); @ini_set( 'display_errors', 'On' ); </ins> ''; }; }; config.virtualHost.hostName = mkDefault name;