summary refs log tree commit diff
path: root/nixos/modules/services/web-apps/dokuwiki.nix
diff options
context:
space:
mode:
authorJonas Heinrich <onny@project-insanity.org>2021-08-03 14:50:21 +0200
committerRaphael Megzari <raphael@megzari.com>2021-09-18 23:09:21 +0900
commit0dcac759f29b5bd983f2bda424c081aa71b04875 (patch)
tree33c91b9244f8a61adf486a3881398af76cbb7062 /nixos/modules/services/web-apps/dokuwiki.nix
parent4f2ca487b24974d972eddac634514dc0c46f5a85 (diff)
downloadnixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.tar
nixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.tar.gz
nixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.tar.bz2
nixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.tar.lz
nixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.tar.xz
nixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.tar.zst
nixpkgs-0dcac759f29b5bd983f2bda424c081aa71b04875.zip
nixos/dokuwiki: Add support for Caddy web server
Diffstat (limited to 'nixos/modules/services/web-apps/dokuwiki.nix')
-rw-r--r--nixos/modules/services/web-apps/dokuwiki.nix595
1 files changed, 327 insertions, 268 deletions
diff --git a/nixos/modules/services/web-apps/dokuwiki.nix b/nixos/modules/services/web-apps/dokuwiki.nix
index 685cb496703..964fef23add 100644
--- a/nixos/modules/services/web-apps/dokuwiki.nix
+++ b/nixos/modules/services/web-apps/dokuwiki.nix
@@ -1,16 +1,21 @@
-{ config, lib, pkgs, ... }:
+{ config, pkgs, lib, ... }:
 
 let
+  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types maintainers recursiveUpdate;
+  inherit (lib) any attrValues concatMapStrings concatMapStringsSep flatten literalExample;
+  inherit (lib) filterAttrs mapAttrs mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString;
 
-  inherit (lib) mkEnableOption mkForce mkIf mkMerge mkOption optionalAttrs recursiveUpdate types maintainers;
-  inherit (lib) concatMapStringsSep flatten mapAttrs mapAttrs' mapAttrsToList nameValuePair concatMapStringSep;
-
-  eachSite = config.services.dokuwiki;
-
+  cfg = migrateOldAttrs config.services.dokuwiki;
+  eachSite = cfg.sites;
   user = "dokuwiki";
-  group = config.services.nginx.group;
+  webserver = config.services.${cfg.webserver};
+  stateDir = hostName: "/var/lib/dokuwiki/${hostName}/data";
+
+  # Migrate config.services.dokuwiki.<hostName> to config.services.dokuwiki.sites.<hostName>
+  oldSites = filterAttrs (o: _: o != "sites" && o != "webserver");
+  migrateOldAttrs = cfg: cfg // { sites = cfg.sites // oldSites cfg; };
 
-  dokuwikiAclAuthConfig = cfg: pkgs.writeText "acl.auth.php" ''
+  dokuwikiAclAuthConfig = hostName: cfg: pkgs.writeText "acl.auth-${hostName}.php" ''
     # acl.auth.php
     # <?php exit()?>
     #
@@ -19,7 +24,7 @@ let
     ${toString cfg.acl}
   '';
 
-  dokuwikiLocalConfig = cfg: pkgs.writeText "local.php" ''
+  dokuwikiLocalConfig = hostName: cfg: pkgs.writeText "local-${hostName}.php" ''
     <?php
     $conf['savedir'] = '${cfg.stateDir}';
     $conf['superuser'] = '${toString cfg.superUser}';
@@ -28,11 +33,12 @@ let
     ${toString cfg.extraConfig}
   '';
 
-  dokuwikiPluginsLocalConfig = cfg: pkgs.writeText "plugins.local.php" ''
+  dokuwikiPluginsLocalConfig = hostName: cfg: pkgs.writeText "plugins.local-${hostName}.php" ''
     <?php
     ${cfg.pluginsConfig}
   '';
 
+
   pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec {
     pname = "dokuwiki-${hostName}";
     version = src.version;
@@ -43,13 +49,13 @@ let
       cp -r * $out/
 
       # symlink the dokuwiki config
-      ln -s ${dokuwikiLocalConfig cfg} $out/share/dokuwiki/local.php
+      ln -s ${dokuwikiLocalConfig hostName cfg} $out/share/dokuwiki/local.php
 
       # symlink plugins config
-      ln -s ${dokuwikiPluginsLocalConfig cfg} $out/share/dokuwiki/plugins.local.php
+      ln -s ${dokuwikiPluginsLocalConfig hostName cfg} $out/share/dokuwiki/plugins.local.php
 
       # symlink acl
-      ln -s ${dokuwikiAclAuthConfig cfg} $out/share/dokuwiki/acl.auth.php
+      ln -s ${dokuwikiAclAuthConfig hostName cfg} $out/share/dokuwiki/acl.auth.php
 
       # symlink additional plugin(s) and templates(s)
       ${concatMapStringsSep "\n" (template: "ln -s ${template} $out/share/dokuwiki/lib/tpl/${template.name}") cfg.templates}
@@ -57,332 +63,385 @@ let
     '';
   };
 
-  siteOpts = { config, lib, name, ...}: {
-    options = {
-      enable = mkEnableOption "DokuWiki web application.";
-
-      package = mkOption {
-        type = types.package;
-        default = pkgs.dokuwiki;
-        description = "Which dokuwiki package to use.";
-      };
+  siteOpts = { config, lib, name, ... }:
+    {
+      options = {
+        package = mkOption {
+          type = types.package;
+          default = pkgs.dokuwiki;
+          description = "Which DokuWiki package to use.";
+        };
 
-      hostName = mkOption {
-        type = types.str;
-        default = "localhost";
-        description = "FQDN for the instance.";
-      };
+        stateDir = mkOption {
+          type = types.path;
+          default = "/var/lib/dokuwiki/${name}/data";
+          description = "Location of the DokuWiki state directory.";
+        };
 
-      stateDir = mkOption {
-        type = types.path;
-        default = "/var/lib/dokuwiki/${name}/data";
-        description = "Location of the dokuwiki state directory.";
-      };
+        acl = mkOption {
+          type = types.nullOr types.lines;
+          default = null;
+          example = "*               @ALL               8";
+          description = ''
+            Access Control Lists: see <link xlink:href="https://www.dokuwiki.org/acl"/>
+            Mutually exclusive with services.dokuwiki.aclFile
+            Set this to a value other than null to take precedence over aclFile option.
+
+            Warning: Consider using aclFile instead if you do not
+            want to store the ACL in the world-readable Nix store.
+          '';
+        };
 
-      acl = mkOption {
-        type = types.nullOr types.lines;
-        default = null;
-        example = "*               @ALL               8";
-        description = ''
-          Access Control Lists: see <link xlink:href="https://www.dokuwiki.org/acl"/>
-          Mutually exclusive with services.dokuwiki.aclFile
-          Set this to a value other than null to take precedence over aclFile option.
-
-          Warning: Consider using aclFile instead if you do not
-          want to store the ACL in the world-readable Nix store.
-        '';
-      };
+        aclFile = mkOption {
+          type = with types; nullOr str;
+          default = if (config.aclUse && config.acl == null) then "/var/lib/dokuwiki/${name}/acl.auth.php" else null;
+          description = ''
+            Location of the dokuwiki acl rules. Mutually exclusive with services.dokuwiki.acl
+            Mutually exclusive with services.dokuwiki.acl which is preferred.
+            Consult documentation <link xlink:href="https://www.dokuwiki.org/acl"/> for further instructions.
+            Example: <link xlink:href="https://github.com/splitbrain/dokuwiki/blob/master/conf/acl.auth.php.dist"/>
+          '';
+          example = "/var/lib/dokuwiki/${name}/acl.auth.php";
+        };
 
-      aclFile = mkOption {
-        type = with types; nullOr str;
-        default = if (config.aclUse && config.acl == null) then "/var/lib/dokuwiki/${name}/acl.auth.php" else null;
-        description = ''
-          Location of the dokuwiki acl rules. Mutually exclusive with services.dokuwiki.acl
-          Mutually exclusive with services.dokuwiki.acl which is preferred.
-          Consult documentation <link xlink:href="https://www.dokuwiki.org/acl"/> for further instructions.
-          Example: <link xlink:href="https://github.com/splitbrain/dokuwiki/blob/master/conf/acl.auth.php.dist"/>
-        '';
-        example = "/var/lib/dokuwiki/${name}/acl.auth.php";
-      };
+        aclUse = mkOption {
+          type = types.bool;
+          default = true;
+          description = ''
+            Necessary for users to log in into the system.
+            Also limits anonymous users. When disabled,
+            everyone is able to create and edit content.
+          '';
+        };
 
-      aclUse = mkOption {
-        type = types.bool;
-        default = true;
-        description = ''
-          Necessary for users to log in into the system.
-          Also limits anonymous users. When disabled,
-          everyone is able to create and edit content.
-        '';
-      };
+        pluginsConfig = mkOption {
+          type = types.lines;
+          default = ''
+            $plugins['authad'] = 0;
+            $plugins['authldap'] = 0;
+            $plugins['authmysql'] = 0;
+            $plugins['authpgsql'] = 0;
+          '';
+          description = ''
+            List of the dokuwiki (un)loaded plugins.
+          '';
+        };
 
-      pluginsConfig = mkOption {
-        type = types.lines;
-        default = ''
-          $plugins['authad'] = 0;
-          $plugins['authldap'] = 0;
-          $plugins['authmysql'] = 0;
-          $plugins['authpgsql'] = 0;
-        '';
-        description = ''
-          List of the dokuwiki (un)loaded plugins.
-        '';
-      };
+        superUser = mkOption {
+          type = types.nullOr types.str;
+          default = "@admin";
+          description = ''
+            You can set either a username, a list of usernames (“admin1,admin2”),
+            or the name of a group by prepending an @ char to the groupname
+            Consult documentation <link xlink:href="https://www.dokuwiki.org/config:superuser"/> for further instructions.
+          '';
+        };
 
-      superUser = mkOption {
-        type = types.nullOr types.str;
-        default = "@admin";
-        description = ''
-          You can set either a username, a list of usernames (“admin1,admin2”),
-          or the name of a group by prepending an @ char to the groupname
-          Consult documentation <link xlink:href="https://www.dokuwiki.org/config:superuser"/> for further instructions.
-        '';
-      };
+        usersFile = mkOption {
+          type = with types; nullOr str;
+          default = if config.aclUse then "/var/lib/dokuwiki/${name}/users.auth.php" else null;
+          description = ''
+            Location of the dokuwiki users file. List of users. Format:
+            login:passwordhash:Real Name:email:groups,comma,separated
+            Create passwordHash easily by using:$ mkpasswd -5 password `pwgen 8 1`
+            Example: <link xlink:href="https://github.com/splitbrain/dokuwiki/blob/master/conf/users.auth.php.dist"/>
+            '';
+          example = "/var/lib/dokuwiki/${name}/users.auth.php";
+        };
 
-      usersFile = mkOption {
-        type = with types; nullOr str;
-        default = if config.aclUse then "/var/lib/dokuwiki/${name}/users.auth.php" else null;
-        description = ''
-          Location of the dokuwiki users file. List of users. Format:
-          login:passwordhash:Real Name:email:groups,comma,separated
-          Create passwordHash easily by using:$ mkpasswd -5 password `pwgen 8 1`
-          Example: <link xlink:href="https://github.com/splitbrain/dokuwiki/blob/master/conf/users.auth.php.dist"/>
+        disableActions = mkOption {
+          type = types.nullOr types.str;
+          default = "";
+          example = "search,register";
+          description = ''
+            Disable individual action modes. Refer to
+            <link xlink:href="https://www.dokuwiki.org/config:action_modes"/>
+            for details on supported values.
           '';
-        example = "/var/lib/dokuwiki/${name}/users.auth.php";
-      };
+        };
 
-      disableActions = mkOption {
-        type = types.nullOr types.str;
-        default = "";
-        example = "search,register";
-        description = ''
-          Disable individual action modes. Refer to
-          <link xlink:href="https://www.dokuwiki.org/config:action_modes"/>
-          for details on supported values.
-        '';
-      };
+        plugins = mkOption {
+          type = types.listOf types.path;
+          default = [];
+          description = ''
+                List of path(s) to respective plugin(s) which are copied from the 'plugin' directory.
+                <note><para>These plugins need to be packaged before use, see example.</para></note>
+          '';
+          example = ''
+                # Let's package the icalevents plugin
+                plugin-icalevents = pkgs.stdenv.mkDerivation {
+                  name = "icalevents";
+                  # Download the plugin from the dokuwiki site
+                  src = pkgs.fetchurl {
+                    url = "https://github.com/real-or-random/dokuwiki-plugin-icalevents/releases/download/2017-06-16/dokuwiki-plugin-icalevents-2017-06-16.zip";
+                    sha256 = "e40ed7dd6bbe7fe3363bbbecb4de481d5e42385b5a0f62f6a6ce6bf3a1f9dfa8";
+                  };
+                  sourceRoot = ".";
+                  # 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/";
+                };
 
-      extraConfig = mkOption {
-        type = types.nullOr types.lines;
-        default = null;
-        example = ''
-          $conf['title'] = 'My Wiki';
-          $conf['userewrite'] = 1;
-        '';
-        description = ''
-          DokuWiki configuration. Refer to
-          <link xlink:href="https://www.dokuwiki.org/config"/>
-          for details on supported values.
-        '';
-      };
+                # And then pass this theme to the plugin list like this:
+                plugins = [ plugin-icalevents ];
+          '';
+        };
 
-      plugins = mkOption {
-        type = types.listOf types.path;
-        default = [];
-        description = ''
-              List of path(s) to respective plugin(s) which are copied from the 'plugin' directory.
-              <note><para>These plugins need to be packaged before use, see example.</para></note>
-        '';
-        example = ''
-              # Let's package the icalevents plugin
-              plugin-icalevents = pkgs.stdenv.mkDerivation {
-                name = "icalevents";
-                # Download the plugin from the dokuwiki site
-                src = pkgs.fetchurl {
-                  url = "https://github.com/real-or-random/dokuwiki-plugin-icalevents/releases/download/2017-06-16/dokuwiki-plugin-icalevents-2017-06-16.zip";
-                  sha256 = "e40ed7dd6bbe7fe3363bbbecb4de481d5e42385b5a0f62f6a6ce6bf3a1f9dfa8";
+        templates = mkOption {
+          type = types.listOf types.path;
+          default = [];
+          description = ''
+                List of path(s) to respective template(s) which are copied from the 'tpl' directory.
+                <note><para>These templates need to be packaged before use, see example.</para></note>
+          '';
+          example = ''
+                # Let's package the bootstrap3 theme
+                template-bootstrap3 = pkgs.stdenv.mkDerivation {
+                  name = "bootstrap3";
+                  # Download the theme from the dokuwiki site
+                  src = pkgs.fetchurl {
+                    url = "https://github.com/giterlizzi/dokuwiki-template-bootstrap3/archive/v2019-05-22.zip";
+                    sha256 = "4de5ff31d54dd61bbccaf092c9e74c1af3a4c53e07aa59f60457a8f00cfb23a6";
+                  };
+                  # 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/";
                 };
-                sourceRoot = ".";
-                # We need unzip to build this package
-                nativeBuildInputs = [ 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 plugin list like this:
-              plugins = [ plugin-icalevents ];
-        '';
-      };
 
-      templates = mkOption {
-        type = types.listOf types.path;
-        default = [];
-        description = ''
-              List of path(s) to respective template(s) which are copied from the 'tpl' directory.
-              <note><para>These templates need to be packaged before use, see example.</para></note>
-        '';
-        example = ''
-              # Let's package the bootstrap3 theme
-              template-bootstrap3 = pkgs.stdenv.mkDerivation {
-                name = "bootstrap3";
-                # Download the theme from the dokuwiki site
-                src = pkgs.fetchurl {
-                  url = "https://github.com/giterlizzi/dokuwiki-template-bootstrap3/archive/v2019-05-22.zip";
-                  sha256 = "4de5ff31d54dd61bbccaf092c9e74c1af3a4c53e07aa59f60457a8f00cfb23a6";
-                };
-                # We need unzip to build this package
-                nativeBuildInputs = [ 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 template list like this:
-              templates = [ template-bootstrap3 ];
-        '';
-      };
+                # And then pass this theme to the template list like this:
+                templates = [ template-bootstrap3 ];
+          '';
+        };
 
-      poolConfig = mkOption {
-        type = with types; attrsOf (oneOf [ str int bool ]);
-        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;
+        poolConfig = mkOption {
+          type = with types; attrsOf (oneOf [ str int bool ]);
+          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 DokuWiki PHP pool. See the documentation on <literal>php-fpm.conf</literal>
+            for details on configuration directives.
+          '';
         };
-        description = ''
-          Options for the dokuwiki PHP pool. See the documentation on <literal>php-fpm.conf</literal>
-          for details on configuration directives.
-        '';
-      };
 
-      nginx = mkOption {
-        type = types.submodule (
-          recursiveUpdate
-            (import ../web-servers/nginx/vhost-options.nix { inherit config lib; }) {}
-        );
-        default = {};
-        example = {
-          serverAliases = [
-            "wiki.\${config.networking.domain}"
-          ];
-          # To enable encryption and let let's encrypt take care of certificate
-          forceSSL = true;
-          enableACME = true;
+        extraConfig = mkOption {
+          type = types.nullOr types.lines;
+          default = null;
+          example = ''
+            $conf['title'] = 'My Wiki';
+            $conf['userewrite'] = 1;
+          '';
+          description = ''
+            DokuWiki configuration. Refer to
+            <link xlink:href="https://www.dokuwiki.org/config"/>
+            for details on supported values.
+          '';
         };
-        description = ''
-          With this option, you can customize the nginx virtualHost settings.
-        '';
+
       };
+
     };
-  };
 in
 {
   # interface
   options = {
     services.dokuwiki = mkOption {
-      type = types.attrsOf (types.submodule siteOpts);
+      type = types.submodule {
+        # Used to support old interface
+        freeformType = types.attrsOf (types.submodule siteOpts);
+
+        # New interface
+        options.sites = mkOption {
+          type = types.attrsOf (types.submodule siteOpts);
+          default = {};
+          description = "Specification of one or more DokuWiki sites to serve";
+        };
+
+        options.webserver = mkOption {
+          type = types.enum [ "nginx" "caddy" ];
+          default = "nginx";
+          description = ''
+            Whether to use nginx or caddy for virtual host management.
+
+            Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.&lt;name&gt;</literal>.
+            See <xref linkend="opt-services.nginx.virtualHosts"/> for further information.
+
+            Further apache2 configuration can be done by adapting <literal>services.httpd.virtualHosts.&lt;name&gt;</literal>.
+            See <xref linkend="opt-services.httpd.virtualHosts"/> for further information.
+          '';
+        };
+      };
       default = {};
-      description = "Sepcification of one or more dokuwiki sites to serve.";
+      description = "DokuWiki configuration";
     };
+
   };
 
   # implementation
-
-  config = mkIf (eachSite != {}) {
-
-    warnings = mapAttrsToList (hostName: cfg: mkIf (cfg.superUser == null) "Not setting services.dokuwiki.${hostName} superUser will impair your ability to administer DokuWiki") eachSite;
+  config = mkIf (eachSite != {}) (mkMerge [{
 
     assertions = flatten (mapAttrsToList (hostName: cfg:
     [{
       assertion = cfg.aclUse -> (cfg.acl != null || cfg.aclFile != null);
-      message = "Either services.dokuwiki.${hostName}.acl or services.dokuwiki.${hostName}.aclFile is mandatory if aclUse true";
+      message = "Either services.dokuwiki.sites.${hostName}.acl or services.dokuwiki.sites.${hostName}.aclFile is mandatory if aclUse true";
     }
     {
       assertion = cfg.usersFile != null -> cfg.aclUse != false;
-      message = "services.dokuwiki.${hostName}.aclUse must must be true if usersFile is not null";
+      message = "services.dokuwiki.sites.${hostName}.aclUse must must be true if usersFile is not null";
     }
     ]) eachSite);
 
+    warnings = mapAttrsToList (hostName: _: ''services.dokuwiki."${hostName}" is deprecated use services.dokuwiki.sites."${hostName}"'') (oldSites cfg);
+
     services.phpfpm.pools = mapAttrs' (hostName: cfg: (
       nameValuePair "dokuwiki-${hostName}" {
         inherit user;
-        inherit group;
+        group = webserver.group;
+
         phpEnv = {
-          DOKUWIKI_LOCAL_CONFIG = "${dokuwikiLocalConfig cfg}";
-          DOKUWIKI_PLUGINS_LOCAL_CONFIG = "${dokuwikiPluginsLocalConfig cfg}";
+          DOKUWIKI_LOCAL_CONFIG = "${dokuwikiLocalConfig hostName cfg}";
+          DOKUWIKI_PLUGINS_LOCAL_CONFIG = "${dokuwikiPluginsLocalConfig hostName cfg}";
         } // optionalAttrs (cfg.usersFile != null) {
           DOKUWIKI_USERS_AUTH_CONFIG = "${cfg.usersFile}";
         } //optionalAttrs (cfg.aclUse) {
-          DOKUWIKI_ACL_AUTH_CONFIG = if (cfg.acl != null) then "${dokuwikiAclAuthConfig cfg}" else "${toString cfg.aclFile}";
+          DOKUWIKI_ACL_AUTH_CONFIG = if (cfg.acl != null) then "${dokuwikiAclAuthConfig hostName cfg}" else "${toString cfg.aclFile}";
         };
 
         settings = {
-          "listen.mode" = "0660";
-          "listen.owner" = user;
-          "listen.group" = group;
+          "listen.owner" = webserver.user;
+          "listen.group" = webserver.group;
         } // cfg.poolConfig;
-      })) eachSite;
-
-    services.nginx = {
-      enable = true;
-      virtualHosts = mapAttrs (hostName: cfg:  mkMerge [ cfg.nginx {
-        root = mkForce "${pkg hostName cfg}/share/dokuwiki";
-        extraConfig = lib.optionalString (cfg.nginx.addSSL || cfg.nginx.forceSSL || cfg.nginx.onlySSL || cfg.nginx.enableACME) "fastcgi_param HTTPS on;";
-
-        locations."~ /(conf/|bin/|inc/|install.php)" = {
-          extraConfig = "deny all;";
-        };
+      }
+    )) eachSite;
 
-        locations."~ ^/data/" = {
-          root = "${cfg.stateDir}";
-          extraConfig = "internal;";
-        };
+  }
 
-        locations."~ ^/lib.*\\.(js|css|gif|png|ico|jpg|jpeg)$" = {
-          extraConfig = "expires 365d;";
-        };
+  {
+    systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [
+      "d ${stateDir hostName}/attic 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/cache 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/index 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/locks 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/media 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/media_attic 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/media_meta 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/meta 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/pages 0750 ${user} ${webserver.group} - -"
+      "d ${stateDir hostName}/tmp 0750 ${user} ${webserver.group} - -"
+    ] ++ lib.optional (cfg.aclFile != null) "C ${cfg.aclFile} 0640 ${user} ${webserver.group} - ${pkg hostName cfg}/share/dokuwiki/conf/acl.auth.php.dist"
+    ++ lib.optional (cfg.usersFile != null) "C ${cfg.usersFile} 0640 ${user} ${webserver.group} - ${pkg hostName cfg}/share/dokuwiki/conf/users.auth.php.dist"
+    ) eachSite);
 
-        locations."/" = {
-          priority = 1;
-          index = "doku.php";
-          extraConfig = "try_files $uri $uri/ @dokuwiki;";
-        };
+    users.users.${user} = {
+      group = webserver.group;
+      isSystemUser = true;
+    };
+  }
 
-        locations."@dokuwiki" = {
-          extraConfig = ''
+  (mkIf (cfg.webserver == "nginx") {
+    services.nginx = {
+      enable = true;
+      virtualHosts = mapAttrs (hostName: cfg: {
+        serverName = mkDefault hostName;
+        root = "${pkg hostName cfg}/share/dokuwiki";
+
+        locations = {
+          "~ /(conf/|bin/|inc/|install.php)" = {
+            extraConfig = "deny all;";
+          };
+
+          "~ ^/data/" = {
+            root = "${stateDir hostName}";
+            extraConfig = "internal;";
+          };
+
+          "~ ^/lib.*\.(js|css|gif|png|ico|jpg|jpeg)$" = {
+            extraConfig = "expires 365d;";
+          };
+
+          "/" = {
+            priority = 1;
+            index = "doku.php";
+            extraConfig = ''try_files $uri $uri/ @dokuwiki;'';
+          };
+
+          "@dokuwiki" = {
+            extraConfig = ''
               # rewrites "doku.php/" out of the URLs if you set the userwrite setting to .htaccess in dokuwiki config page
               rewrite ^/_media/(.*) /lib/exe/fetch.php?media=$1 last;
               rewrite ^/_detail/(.*) /lib/exe/detail.php?media=$1 last;
               rewrite ^/_export/([^/]+)/(.*) /doku.php?do=export_$1&id=$2 last;
               rewrite ^/(.*) /doku.php?id=$1&$args last;
-          '';
-        };
+            '';
+          };
 
-        locations."~ \\.php$" = {
-          extraConfig = ''
+          "~ \\.php$" = {
+            extraConfig = ''
               try_files $uri $uri/ /doku.php;
               include ${pkgs.nginx}/conf/fastcgi_params;
               fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
               fastcgi_param REDIRECT_STATUS 200;
               fastcgi_pass unix:${config.services.phpfpm.pools."dokuwiki-${hostName}".socket};
-              ${lib.optionalString (cfg.nginx.addSSL || cfg.nginx.forceSSL || cfg.nginx.onlySSL || cfg.nginx.enableACME) "fastcgi_param HTTPS on;"}
-          '';
+              '';
+          };
+
         };
-      }]) eachSite;
+      }) eachSite;
     };
+  })
 
-    systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [
-      "d ${cfg.stateDir}/attic 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/cache 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/index 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/locks 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/media 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/media_attic 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/media_meta 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/meta 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/pages 0750 ${user} ${group} - -"
-      "d ${cfg.stateDir}/tmp 0750 ${user} ${group} - -"
-    ] ++ lib.optional (cfg.aclFile != null) "C ${cfg.aclFile} 0640 ${user} ${group} - ${pkg hostName cfg}/share/dokuwiki/conf/acl.auth.php.dist"
-    ++ lib.optional (cfg.usersFile != null) "C ${cfg.usersFile} 0640 ${user} ${group} - ${pkg hostName cfg}/share/dokuwiki/conf/users.auth.php.dist"
-    ) eachSite);
+  (mkIf (cfg.webserver == "caddy") {
+    services.caddy = {
+      enable = true;
+      virtualHosts = mapAttrs' (hostName: cfg: (
+        nameValuePair "http://${hostName}" {
+          extraConfig = ''
+            root * ${pkg hostName cfg}/share/dokuwiki
+            file_server
 
-    users.users.${user} = {
-      group = group;
-      isSystemUser = true;
+            encode zstd gzip
+            php_fastcgi unix/${config.services.phpfpm.pools."dokuwiki-${hostName}".socket}
+
+            @restrict_files {
+              path /data/* /conf/* /bin/* /inc/* /vendor/* /install.php
+            }
+
+            respond @restrict_files 404
+
+            @allow_media {
+              path_regexp path ^/_media/(.*)$
+            }
+            rewrite @allow_media /lib/exe/fetch.php?media=/{http.regexp.path.1}
+
+            @allow_detail   {
+              path /_detail*
+            }
+            rewrite @allow_detail /lib/exe/detail.php?media={path}
+
+            @allow_export   {
+              path /_export*
+              path_regexp export /([^/]+)/(.*)
+            }
+            rewrite @allow_export /doku.php?do=export_{http.regexp.export.1}&id={http.regexp.export.2}
+
+            try_files {path} {path}/ /doku.php?id={path}&{query}
+          '';
+        }
+      )) eachSite;
     };
-  };
+  })
 
-  meta.maintainers = with maintainers; [ _1000101 ];
+  ]);
 
+  meta.maintainers = with maintainers; [
+    _1000101
+    onny
+  ];
 }