{ ... }:
{
  _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" ];
          };
          phpfpmOptions = lib.mkOption {
            type = with lib.types; lines;
            default = "";
            description = "options appended to the PHP configuration file";
          };
          wpExtraConfig = lib.mkOption {
            type = with lib.types; lines;
            default = "";
            description = "Any additional text to be appended to the wp-config.php";
          };
        };
      };

    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');
              ''
              + settings.wpExtraConfig;
              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
            ];

            services.phpfpm.pools = builtins.listToAttrs (
              map (
                tenant: lib.nameValuePair "wordpress-${tenant}" { phpOptions = settings.phpfpmOptions; }
              ) settings.tenants
            );

            security.acme.acceptTerms = true;

            users.users.nginx.extraGroups = [ "acme" ];

            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.clientMaxBodySize = "128m";

            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
              '';
            };

          };
      };
  };
}
