372 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
		
		
			
		
	
	
			372 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| 
								 | 
							
								{ config, pkgs, lib, ... }:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let
							 | 
						||
| 
								 | 
							
								  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types;
							 | 
						||
| 
								 | 
							
								  inherit (lib) any attrValues concatMapStringsSep flatten literalExample;
							 | 
						||
| 
								 | 
							
								  inherit (lib) mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  eachSite = config.services.wordpress;
							 | 
						||
| 
								 | 
							
								  user = "wordpress";
							 | 
						||
| 
								 | 
							
								  group = config.services.httpd.group;
							 | 
						||
| 
								 | 
							
								  stateDir = hostName: "/var/lib/wordpress/${hostName}";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec {
							 | 
						||
| 
								 | 
							
								    pname = "wordpress-${hostName}";
							 | 
						||
| 
								 | 
							
								    version = src.version;
							 | 
						||
| 
								 | 
							
								    src = cfg.package;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    installPhase = ''
							 | 
						||
| 
								 | 
							
								      mkdir -p $out
							 | 
						||
| 
								 | 
							
								      cp -r * $out/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # symlink the wordpress config
							 | 
						||
| 
								 | 
							
								      ln -s ${wpConfig hostName cfg} $out/share/wordpress/wp-config.php
							 | 
						||
| 
								 | 
							
								      # symlink uploads directory
							 | 
						||
| 
								 | 
							
								      ln -s ${cfg.uploadsDir} $out/share/wordpress/wp-content/uploads
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # https://github.com/NixOS/nixpkgs/pull/53399
							 | 
						||
| 
								 | 
							
								      #
							 | 
						||
| 
								 | 
							
								      # Symlinking works for most plugins and themes, but Avada, for instance, fails to
							 | 
						||
| 
								 | 
							
								      # understand the symlink, causing its file path stripping to fail. This results in
							 | 
						||
| 
								 | 
							
								      # requests that look like: https://example.com/wp-content//nix/store/...plugin/path/some-file.js
							 | 
						||
| 
								 | 
							
								      # Since hard linking directories is not allowed, copying is the next best thing.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # copy additional plugin(s) and theme(s)
							 | 
						||
| 
								 | 
							
								      ${concatMapStringsSep "\n" (theme: "cp -r ${theme} $out/share/wordpress/wp-content/themes/${theme.name}") cfg.themes}
							 | 
						||
| 
								 | 
							
								      ${concatMapStringsSep "\n" (plugin: "cp -r ${plugin} $out/share/wordpress/wp-content/plugins/${plugin.name}") cfg.plugins}
							 | 
						||
| 
								 | 
							
								    '';
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  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__) . '/');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      require_once(ABSPATH . 'wp-settings.php');
							 | 
						||
| 
								 | 
							
								    ?>
							 | 
						||
| 
								 | 
							
								  '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  siteOpts = { lib, name, ... }:
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      options = {
							 | 
						||
| 
								 | 
							
								        package = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.package;
							 | 
						||
| 
								 | 
							
								          default = pkgs.wordpress;
							 | 
						||
| 
								 | 
							
								          description = "Which WordPress package to use.";
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        uploadsDir = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.path;
							 | 
						||
| 
								 | 
							
								          default = "/var/lib/wordpress/${name}/uploads";
							 | 
						||
| 
								 | 
							
								          description = ''
							 | 
						||
| 
								 | 
							
								            This directory is used for uploads of pictures. The directory passed here is automatically
							 | 
						||
| 
								 | 
							
								            created and permissions adjusted as required.
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        plugins = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.listOf types.path;
							 | 
						||
| 
								 | 
							
								          default = [];
							 | 
						||
| 
								 | 
							
								          description = ''
							 | 
						||
| 
								 | 
							
								            List of path(s) to respective plugin(s) which are copied from the 'plugins' directory.
							 | 
						||
| 
								 | 
							
								            <note><para>These plugins need to be packaged before use, see example.</para></note>
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								          example = ''
							 | 
						||
| 
								 | 
							
								            # Wordpress plugin 'embed-pdf-viewer' installation example
							 | 
						||
| 
								 | 
							
								            embedPdfViewerPlugin = pkgs.stdenv.mkDerivation {
							 | 
						||
| 
								 | 
							
								              name = "embed-pdf-viewer-plugin";
							 | 
						||
| 
								 | 
							
								              # Download the theme from the wordpress site
							 | 
						||
| 
								 | 
							
								              src = pkgs.fetchurl {
							 | 
						||
| 
								 | 
							
								                url = https://downloads.wordpress.org/plugin/embed-pdf-viewer.2.0.3.zip;
							 | 
						||
| 
								 | 
							
								                sha256 = "1rhba5h5fjlhy8p05zf0p14c9iagfh96y91r36ni0rmk6y891lyd";
							 | 
						||
| 
								 | 
							
								              };
							 | 
						||
| 
								 | 
							
								              # We need unzip to build this package
							 | 
						||
| 
								 | 
							
								              buildInputs = [ pkgs.unzip ];
							 | 
						||
| 
								 | 
							
								              # Installing simply means copying all files to the output directory
							 | 
						||
| 
								 | 
							
								              installPhase = "mkdir -p $out; cp -R * $out/";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            And then pass this theme to the themes list like this:
							 | 
						||
| 
								 | 
							
								              plugins = [ embedPdfViewerPlugin ];
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        themes = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.listOf types.path;
							 | 
						||
| 
								 | 
							
								          default = [];
							 | 
						||
| 
								 | 
							
								          description = ''
							 | 
						||
| 
								 | 
							
								            List of path(s) to respective theme(s) which are copied from the 'theme' directory.
							 | 
						||
| 
								 | 
							
								            <note><para>These themes need to be packaged before use, see example.</para></note>
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								          example = ''
							 | 
						||
| 
								 | 
							
								            # For shits and giggles, let's package the responsive theme
							 | 
						||
| 
								 | 
							
								            responsiveTheme = pkgs.stdenv.mkDerivation {
							 | 
						||
| 
								 | 
							
								              name = "responsive-theme";
							 | 
						||
| 
								 | 
							
								              # Download the theme from the wordpress site
							 | 
						||
| 
								 | 
							
								              src = pkgs.fetchurl {
							 | 
						||
| 
								 | 
							
								                url = https://downloads.wordpress.org/theme/responsive.3.14.zip;
							 | 
						||
| 
								 | 
							
								                sha256 = "0rjwm811f4aa4q43r77zxlpklyb85q08f9c8ns2akcarrvj5ydx3";
							 | 
						||
| 
								 | 
							
								              };
							 | 
						||
| 
								 | 
							
								              # We need unzip to build this package
							 | 
						||
| 
								 | 
							
								              buildInputs = [ pkgs.unzip ];
							 | 
						||
| 
								 | 
							
								              # Installing simply means copying all files to the output directory
							 | 
						||
| 
								 | 
							
								              installPhase = "mkdir -p $out; cp -R * $out/";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            And then pass this theme to the themes list like this:
							 | 
						||
| 
								 | 
							
								              themes = [ responsiveTheme ];
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        database = rec {
							 | 
						||
| 
								 | 
							
								          host = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.str;
							 | 
						||
| 
								 | 
							
								            default = "localhost";
							 | 
						||
| 
								 | 
							
								            description = "Database host address.";
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          port = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.port;
							 | 
						||
| 
								 | 
							
								            default = 3306;
							 | 
						||
| 
								 | 
							
								            description = "Database host port.";
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          name = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.str;
							 | 
						||
| 
								 | 
							
								            default = "wordpress";
							 | 
						||
| 
								 | 
							
								            description = "Database name.";
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          user = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.str;
							 | 
						||
| 
								 | 
							
								            default = "wordpress";
							 | 
						||
| 
								 | 
							
								            description = "Database user.";
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          passwordFile = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.nullOr types.path;
							 | 
						||
| 
								 | 
							
								            default = null;
							 | 
						||
| 
								 | 
							
								            example = "/run/keys/wordpress-dbpassword";
							 | 
						||
| 
								 | 
							
								            description = ''
							 | 
						||
| 
								 | 
							
								              A file containing the password corresponding to
							 | 
						||
| 
								 | 
							
								              <option>database.user</option>.
							 | 
						||
| 
								 | 
							
								            '';
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          tablePrefix = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.str;
							 | 
						||
| 
								 | 
							
								            default = "wp_";
							 | 
						||
| 
								 | 
							
								            description = ''
							 | 
						||
| 
								 | 
							
								              The $table_prefix is the value placed in the front of your database tables.
							 | 
						||
| 
								 | 
							
								              Change the value if you want to use something other than wp_ for your database
							 | 
						||
| 
								 | 
							
								              prefix. Typically this is changed if you are installing multiple WordPress blogs
							 | 
						||
| 
								 | 
							
								              in the same database.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              See <link xlink:href='https://codex.wordpress.org/Editing_wp-config.php#table_prefix'/>.
							 | 
						||
| 
								 | 
							
								            '';
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          socket = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.nullOr types.path;
							 | 
						||
| 
								 | 
							
								            default = null;
							 | 
						||
| 
								 | 
							
								            defaultText = "/run/mysqld/mysqld.sock";
							 | 
						||
| 
								 | 
							
								            description = "Path to the unix socket file to use for authentication.";
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          createLocally = mkOption {
							 | 
						||
| 
								 | 
							
								            type = types.bool;
							 | 
						||
| 
								 | 
							
								            default = true;
							 | 
						||
| 
								 | 
							
								            description = "Create the database and database user locally.";
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        virtualHost = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.submodule ({
							 | 
						||
| 
								 | 
							
								            options = import ../web-servers/apache-httpd/per-server-options.nix {
							 | 
						||
| 
								 | 
							
								              inherit lib;
							 | 
						||
| 
								 | 
							
								              forMainServer = false;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								          example = literalExample ''
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              enableSSL = true;
							 | 
						||
| 
								 | 
							
								              adminAddr = "webmaster@example.org";
							 | 
						||
| 
								 | 
							
								              sslServerCert = "/var/lib/acme/wordpress.example.org/full.pem";
							 | 
						||
| 
								 | 
							
								              sslServerKey = "/var/lib/acme/wordpress.example.org/key.pem";
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								          description = ''
							 | 
						||
| 
								 | 
							
								            Apache configuration can be done by adapting <option>services.httpd.virtualHosts</option>.
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        poolConfig = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.lines;
							 | 
						||
| 
								 | 
							
								          default = ''
							 | 
						||
| 
								 | 
							
								            pm = dynamic
							 | 
						||
| 
								 | 
							
								            pm.max_children = 32
							 | 
						||
| 
								 | 
							
								            pm.start_servers = 2
							 | 
						||
| 
								 | 
							
								            pm.min_spare_servers = 2
							 | 
						||
| 
								 | 
							
								            pm.max_spare_servers = 4
							 | 
						||
| 
								 | 
							
								            pm.max_requests = 500
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								          description = ''
							 | 
						||
| 
								 | 
							
								            Options for the WordPress PHP pool. See the documentation on <literal>php-fpm.conf</literal>
							 | 
						||
| 
								 | 
							
								            for details on configuration directives.
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        extraConfig = mkOption {
							 | 
						||
| 
								 | 
							
								          type = types.lines;
							 | 
						||
| 
								 | 
							
								          default = "";
							 | 
						||
| 
								 | 
							
								          description = ''
							 | 
						||
| 
								 | 
							
								            Any additional text to be appended to the wp-config.php
							 | 
						||
| 
								 | 
							
								            configuration file. This is a PHP script. For configuration
							 | 
						||
| 
								 | 
							
								            settings, see <link xlink:href='https://codex.wordpress.org/Editing_wp-config.php'/>.
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								          example = ''
							 | 
						||
| 
								 | 
							
								            define( 'AUTOSAVE_INTERVAL', 60 ); // Seconds
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      config.virtualHost.hostName = mkDefault name;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								in
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  # interface
							 | 
						||
| 
								 | 
							
								  options = {
							 | 
						||
| 
								 | 
							
								    services.wordpress = mkOption {
							 | 
						||
| 
								 | 
							
								      type = types.attrsOf (types.submodule siteOpts);
							 | 
						||
| 
								 | 
							
								      default = {};
							 | 
						||
| 
								 | 
							
								      description = "Specification of one or more WordPress sites to serve via Apache.";
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  # implementation
							 | 
						||
| 
								 | 
							
								  config = mkIf (eachSite != {}) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    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";
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    ) eachSite;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    services.mysql = mkIf (any (v: v.database.createLocally) (attrValues eachSite)) {
							 | 
						||
| 
								 | 
							
								      enable = true;
							 | 
						||
| 
								 | 
							
								      package = mkDefault pkgs.mariadb;
							 | 
						||
| 
								 | 
							
								      ensureDatabases = mapAttrsToList (hostName: cfg: cfg.database.name) eachSite;
							 | 
						||
| 
								 | 
							
								      ensureUsers = mapAttrsToList (hostName: cfg:
							 | 
						||
| 
								 | 
							
								        { name = cfg.database.user;
							 | 
						||
| 
								 | 
							
								          ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      ) eachSite;
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    services.phpfpm.pools = mapAttrs' (hostName: cfg: (
							 | 
						||
| 
								 | 
							
								      nameValuePair "wordpress-${hostName}" {
							 | 
						||
| 
								 | 
							
								        listen = "/run/phpfpm/wordpress-${hostName}.sock";
							 | 
						||
| 
								 | 
							
								        extraConfig = ''
							 | 
						||
| 
								 | 
							
								          listen.owner = ${config.services.httpd.user}
							 | 
						||
| 
								 | 
							
								          listen.group = ${config.services.httpd.group}
							 | 
						||
| 
								 | 
							
								          user = ${user}
							 | 
						||
| 
								 | 
							
								          group = ${group}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          ${cfg.poolConfig}
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    )) eachSite;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    services.httpd = {
							 | 
						||
| 
								 | 
							
								      enable = true;
							 | 
						||
| 
								 | 
							
								      extraModules = [ "proxy_fcgi" ];
							 | 
						||
| 
								 | 
							
								      virtualHosts = mapAttrsToList (hostName: cfg:
							 | 
						||
| 
								 | 
							
								        (mkMerge [
							 | 
						||
| 
								 | 
							
								          cfg.virtualHost {
							 | 
						||
| 
								 | 
							
								            documentRoot = mkForce "${pkg hostName cfg}/share/wordpress";
							 | 
						||
| 
								 | 
							
								            extraConfig = ''
							 | 
						||
| 
								 | 
							
								              <Directory "${pkg hostName cfg}/share/wordpress">
							 | 
						||
| 
								 | 
							
								                <FilesMatch "\.php$">
							 | 
						||
| 
								 | 
							
								                  <If "-f %{REQUEST_FILENAME}">
							 | 
						||
| 
								 | 
							
								                    SetHandler "proxy:unix:/run/phpfpm/wordpress-${hostName}.sock|fcgi://localhost/"
							 | 
						||
| 
								 | 
							
								                  </If>
							 | 
						||
| 
								 | 
							
								                </FilesMatch>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                # standard wordpress .htaccess contents
							 | 
						||
| 
								 | 
							
								                <IfModule mod_rewrite.c>
							 | 
						||
| 
								 | 
							
								                  RewriteEngine On
							 | 
						||
| 
								 | 
							
								                  RewriteBase /
							 | 
						||
| 
								 | 
							
								                  RewriteRule ^index\.php$ - [L]
							 | 
						||
| 
								 | 
							
								                  RewriteCond %{REQUEST_FILENAME} !-f
							 | 
						||
| 
								 | 
							
								                  RewriteCond %{REQUEST_FILENAME} !-d
							 | 
						||
| 
								 | 
							
								                  RewriteRule . /index.php [L]
							 | 
						||
| 
								 | 
							
								                </IfModule>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                DirectoryIndex index.php
							 | 
						||
| 
								 | 
							
								                Require all granted
							 | 
						||
| 
								 | 
							
								                Options +FollowSymLinks
							 | 
						||
| 
								 | 
							
								              </Directory>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              # https://wordpress.org/support/article/hardening-wordpress/#securing-wp-config-php
							 | 
						||
| 
								 | 
							
								              <Files wp-config.php>
							 | 
						||
| 
								 | 
							
								                Require all denied
							 | 
						||
| 
								 | 
							
								              </Files>
							 | 
						||
| 
								 | 
							
								            '';
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        ])
							 | 
						||
| 
								 | 
							
								      ) 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} - -"
							 | 
						||
| 
								 | 
							
								    ]) eachSite);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    systemd.services = mkMerge [
							 | 
						||
| 
								 | 
							
								      (mapAttrs' (hostName: cfg: (
							 | 
						||
| 
								 | 
							
								        nameValuePair "wordpress-init-${hostName}" {
							 | 
						||
| 
								 | 
							
								          wantedBy = [ "multi-user.target" ];
							 | 
						||
| 
								 | 
							
								          before = [ "phpfpm-wordpress-${hostName}.service" ];
							 | 
						||
| 
								 | 
							
								          after = optional cfg.database.createLocally "mysql.service";
							 | 
						||
| 
								 | 
							
								          script = ''
							 | 
						||
| 
								 | 
							
								            if ! test -e "${stateDir hostName}/secret-keys.php"; then
							 | 
						||
| 
								 | 
							
								              echo "<?php" >> "${stateDir hostName}/secret-keys.php"
							 | 
						||
| 
								 | 
							
								              ${pkgs.curl}/bin/curl -s https://api.wordpress.org/secret-key/1.1/salt/ >> "${stateDir hostName}/secret-keys.php"
							 | 
						||
| 
								 | 
							
								              echo "?>" >> "${stateDir hostName}/secret-keys.php"
							 | 
						||
| 
								 | 
							
								              chmod 440 "${stateDir hostName}/secret-keys.php"
							 | 
						||
| 
								 | 
							
								            fi
							 | 
						||
| 
								 | 
							
								          '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          serviceConfig = {
							 | 
						||
| 
								 | 
							
								            Type = "oneshot";
							 | 
						||
| 
								 | 
							
								            User = user;
							 | 
						||
| 
								 | 
							
								            Group = group;
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								      })) eachSite)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      (optionalAttrs (any (v: v.database.createLocally) (attrValues eachSite)) {
							 | 
						||
| 
								 | 
							
								        httpd.after = [ "mysql.service" ];
							 | 
						||
| 
								 | 
							
								      })
							 | 
						||
| 
								 | 
							
								    ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    users.users.${user}.group = group;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								}
							 |