{ ... }: { _class = "clan.service"; manifest.name = "wordpress"; manifest.description = "wordpress with multi-tenant support and state of plugins and themes are allowed"; manifest.readme = "wordpress with multi-tenant support and state of plugins and themes are allowed"; manifest.categories = [ "System" ]; roles.server = { description = "A default server role"; interface = { lib, ... }: { options = { tenants = lib.mkOption { type = with lib.types; listOf str; default = [ "localhost" ]; description = "List of tenants website to host on the instance"; example = [ "example.com" ]; }; }; }; perInstance = { settings, ... }: { nixosModule = { pkgs, lib, config, ... }: let user = "wordpress"; mkSafeDBName = domain: "wp_${builtins.replaceStrings [ "." ] [ "_" ] domain}"; mkWordpressSite = domain: { database = { name = mkSafeDBName domain; user = user; }; package = wp-pkg domain; extraConfig = '' define('FS_METHOD', 'direct'); ''; themes = { }; }; stateDir = hostName: "/var/lib/wordpress/${hostName}"; wp-pkg = hostName: let upStreamSrc = pkgs.wordpress; in pkgs.stdenv.mkDerivation { pname = "wordpress-custom"; version = upStreamSrc.version; src = upStreamSrc; installPhase = '' mkdir -p $out cp -r * $out/ rm -rf $out/share/wordpress/wp-content/plugins rm -rf $out/share/wordpress/wp-content/themes # symlink uploads directory ln -s "${stateDir hostName}"/wp-content/themes $out/share/wordpress/wp-content/themes ln -s "${stateDir hostName}"/wp-content/plugins $out/share/wordpress/wp-content/plugins ln -s "${stateDir hostName}"/wp-content/upgrade $out/share/wordpress/wp-content/upgrade ''; }; webserver = config.services.${config.services.wordpress.webserver}; in { services.wordpress.webserver = "nginx"; services.wordpress.sites = builtins.listToAttrs ( map (tenant: { name = tenant; value = mkWordpressSite tenant; }) settings.tenants ); systemd.tmpfiles.rules = lib.flatten ( map (tenant: [ "d '${stateDir tenant}/wp-content' 0750 ${user} ${webserver.group} - -" "d '${stateDir tenant}/wp-content/themes' 0750 ${user} ${webserver.group} - -" "Z '${stateDir tenant}/wp-content/themes' 0750 ${user} ${webserver.group} - -" "d '${stateDir tenant}/wp-content/plugins' 0750 ${user} ${webserver.group} - -" "Z '${stateDir tenant}/wp-content/plugins' 0750 ${user} ${webserver.group} - -" "d '${stateDir tenant}/wp-content/upgrade' 0750 ${user} ${webserver.group} - -" "Z '${stateDir tenant}/wp-content/upgrade' 0750 ${user} ${webserver.group} - -" ]) settings.tenants ); networking.firewall.allowedTCPPorts = [ 80 443 ]; security.acme.certs = lib.listToAttrs ( map ( tenant: (lib.nameValuePair tenant { email = config.clan.core.vars.generators.acme.files.email.value; webroot = "/var/lib/acme/acme-challenge/${tenant}"; }) ) settings.tenants ); services.nginx.virtualHosts = lib.listToAttrs ( map ( tenant: (lib.nameValuePair tenant { forceSSL = true; useACMEHost = tenant; acmeRoot = config.security.acme.certs.${tenant}.webroot; }) ) settings.tenants ); clan.core.vars.generators.acme = { share = true; files.email.secret = false; prompts.email = { type = "line"; description = "Email for ACME registeration"; }; script = '' cat $prompts/email > $out/email ''; }; }; }; }; }