summaryrefslogtreecommitdiffstats
path: root/nixos
diff options
context:
space:
mode:
authorJonas Heinrich <onny@project-insanity.org>2023-01-06 23:26:50 +0100
committerGitHub <noreply@github.com>2023-01-06 23:26:50 +0100
commitcff8fd9c6cfefadd5ceea6717c03c66fdee235f8 (patch)
treec3e627844278f10f9a82e4158a49c08b3a759c1d /nixos
parent2f84082de7cb5e0de57f02332c82a9dce73b1e5e (diff)
parent236d90fde0b376f00e8eea32ea6af37ec3de4766 (diff)
Merge pull request #208299 from e1mo/dokuwkiki-makeover
nixos/dokuwiki: Overhaul for structured settings
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/from_md/release-notes/rl-2305.section.xml14
-rw-r--r--nixos/doc/manual/release-notes/rl-2305.section.md4
-rw-r--r--nixos/modules/services/web-apps/dokuwiki.nix269
-rw-r--r--nixos/tests/dokuwiki.nix48
4 files changed, 260 insertions, 75 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
index 12e4d490300e..97d6a89759c8 100644
--- a/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
+++ b/nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
@@ -309,6 +309,20 @@
</listitem>
<listitem>
<para>
+ The <literal>dokuwiki</literal> service now takes
+ configuration via the
+ <literal>services.dokuwiki.sites.&lt;name&gt;.settings</literal>
+ attribute set, <literal>extraConfig</literal> is deprecated
+ and will be removed. The
+ <literal>{aclUse,superUser,disableActions}</literal>
+ attributes have been renamed, <literal>pluginsConfig</literal>
+ now also accepts an attribute set of booleans, passing plain
+ PHP is deprecated. Same applies to <literal>acl</literal>
+ which now also accepts structured settings.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
To reduce closure size in
<literal>nixos/modules/profiles/minimal.nix</literal> profile
disabled installation documentations and manuals. Also
diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md
index 07ee346c2c87..8fafe0a344c3 100644
--- a/nixos/doc/manual/release-notes/rl-2305.section.md
+++ b/nixos/doc/manual/release-notes/rl-2305.section.md
@@ -84,6 +84,10 @@ In addition to numerous new and upgraded packages, this release has the followin
`services.dnsmasq.extraConfig` will be deprecated when NixOS 22.11 reaches
end of life.
+- The `dokuwiki` service now takes configuration via the `services.dokuwiki.sites.<name>.settings` attribute set, `extraConfig` is deprecated and will be removed.
+ 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.
+
- 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.
diff --git a/nixos/modules/services/web-apps/dokuwiki.nix b/nixos/modules/services/web-apps/dokuwiki.nix
index 1c40441bb55f..d90dd8ace412 100644
--- a/nixos/modules/services/web-apps/dokuwiki.nix
+++ b/nixos/modules/services/web-apps/dokuwiki.nix
@@ -15,30 +15,64 @@ let
extraConfig = mkPhpIni cfg.phpOptions;
};
- dokuwikiAclAuthConfig = hostName: cfg: pkgs.writeText "acl.auth-${hostName}.php" ''
+ dokuwikiAclAuthConfig = hostName: cfg: let
+ inherit (cfg) acl;
+ acl_gen = concatMapStringsSep "\n" (l: "${l.page} \t ${l.actor} \t ${toString l.level}");
+ in pkgs.writeText "acl.auth-${hostName}.php" ''
# acl.auth.php
# <?php exit()?>
#
# Access Control Lists
#
- ${toString cfg.acl}
+ ${if isString acl then acl else acl_gen acl}
'';
- dokuwikiLocalConfig = hostName: cfg: pkgs.writeText "local-${hostName}.php" ''
- <?php
- $conf['savedir'] = '${cfg.stateDir}';
- $conf['superuser'] = '${toString cfg.superUser}';
- $conf['useacl'] = '${toString cfg.aclUse}';
- $conf['disableactions'] = '${cfg.disableActions}';
+ mergeConfig = cfg: {
+ useacl = false; # Dokuwiki default
+ savedir = cfg.stateDir;
+ } // cfg.settings;
+
+ writePhpFile = name: text: pkgs.writeTextFile {
+ inherit name;
+ text = "<?php\n${text}";
+ checkPhase = "${pkgs.php81}/bin/php --syntax-check $target";
+ };
+
+ 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 toString (if v then 1 else 0)
+ else if isHasAttr "_file" then "trim(file_get_contents(${lib.escapeShellArg v._file}))"
+ else if isHasAttr "_raw" then v._raw
+ else abort "The dokuwiki localConf value ${lib.generators.toPretty {} v} can not be encoded."
+ ;
+
+ mkPhpAttrVals = v: flatten (mapAttrsToList mkPhpKeyVal v);
+ mkPhpKeyVal = k: v: let
+ values = if (isAttrs v && (hasAttr "_file" v || hasAttr "_raw" v )) || !isAttrs v then
+ [" = ${mkPhpValue v};"]
+ else
+ mkPhpAttrVals v;
+ in map (e: "[${escapeShellArg k}]${e}") (flatten values);
+
+ dokuwikiLocalConfig = hostName: cfg: let
+ conf_gen = c: map (v: "$conf${v}") (mkPhpAttrVals c);
+ in writePhpFile "local-${hostName}.php" ''
+ ${concatStringsSep "\n" (conf_gen cfg.mergedConfig)}
${toString cfg.extraConfig}
'';
- dokuwikiPluginsLocalConfig = hostName: cfg: pkgs.writeText "plugins.local-${hostName}.php" ''
- <?php
- ${cfg.pluginsConfig}
+ dokuwikiPluginsLocalConfig = hostName: cfg: let
+ pc = cfg.pluginsConfig;
+ pc_gen = pc: concatStringsSep "\n" (mapAttrsToList (n: v: "$plugins['${n}'] = ${boolToString v};") pc);
+ in writePhpFile "plugins.local-${hostName}.php" ''
+ ${if isString pc then pc else pc_gen pc}
'';
-
pkg = hostName: cfg: pkgs.stdenv.mkDerivation rec {
pname = "dokuwiki-${hostName}";
version = src.version;
@@ -49,22 +83,82 @@ let
cp -r * $out/
# symlink the dokuwiki config
- ln -s ${dokuwikiLocalConfig hostName cfg} $out/share/dokuwiki/local.php
+ ln -sf ${dokuwikiLocalConfig hostName cfg} $out/share/dokuwiki/conf/local.php
# symlink plugins config
- ln -s ${dokuwikiPluginsLocalConfig hostName cfg} $out/share/dokuwiki/plugins.local.php
+ ln -sf ${dokuwikiPluginsLocalConfig hostName cfg} $out/share/dokuwiki/conf/plugins.local.php
- # symlink acl
- ln -s ${dokuwikiAclAuthConfig hostName cfg} $out/share/dokuwiki/acl.auth.php
+ # symlink acl (if needed)
+ ${optionalString (cfg.mergedConfig.useacl && cfg.acl != null) "ln -sf ${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}
- ${concatMapStringsSep "\n" (plugin: "ln -s ${plugin} $out/share/dokuwiki/lib/plugins/${plugin.name}") cfg.plugins}
+ ${concatMapStringsSep "\n" (template: "ln -sf ${template} $out/share/dokuwiki/lib/tpl/${template.name}") cfg.templates}
+ ${concatMapStringsSep "\n" (plugin: "ln -sf ${plugin} $out/share/dokuwiki/lib/plugins/${plugin.name}") cfg.plugins}
'';
};
+ aclOpts = { ... }: {
+ options = {
+
+ page = mkOption {
+ type = types.str;
+ description = "Page or namespace to restrict";
+ example = "start";
+ };
+
+ actor = mkOption {
+ type = types.str;
+ description = "User or group to restrict";
+ example = "@external";
+ };
+
+ level = let
+ available = {
+ "none" = 0;
+ "read" = 1;
+ "edit" = 2;
+ "create" = 4;
+ "upload" = 8;
+ "delete" = 16;
+ };
+ in mkOption {
+ type = types.enum ((attrValues available) ++ (attrNames available));
+ apply = x: if isInt x then x else available.${x};
+ description = ''
+ Permission level to restrict the actor(s) to.
+ See <https://www.dokuwiki.org/acl#background_info> for explanation
+ '';
+ example = "read";
+ };
+
+ };
+ };
+
siteOpts = { config, lib, name, ... }:
{
+ imports = [
+ # NOTE: These will sadly not print the absolute argument path but only the name. Related to #96006
+ (mkRenamedOptionModule [ "aclUse" ] [ "settings" "useacl" ] )
+ (mkRenamedOptionModule [ "superUser" ] [ "settings" "superuser" ] )
+ (mkRenamedOptionModule [ "disableActions" ] [ "settings" "disableactions" ] )
+ ({ config, options, name, ...}: {
+ config.warnings =
+ (optional (isString config.pluginsConfig) ''
+ Passing plain strings to services.dokuwiki.sites.${name}.pluginsConfig has been deprecated and will not be continue to be supported in the future.
+ Please pass structured settings instead.
+ '')
+ ++ (optional (isString config.acl) ''
+ Passing a plain string to services.dokuwiki.sites.${name}.acl has been deprecated and will not continue to be supported in the future.
+ Please pass structured settings instead.
+ '')
+ ++ (optional (config.extraConfig != null) ''
+ services.dokuwiki.sites.${name}.extraConfig is deprecated and will be removed in the future.
+ Please pass structured settings to services.dokuwiki.sites.${name}.settings instead.
+ '')
+ ;
+ })
+ ];
+
options = {
enable = mkEnableOption (lib.mdDoc "DokuWiki web application.");
@@ -82,9 +176,22 @@ let
};
acl = mkOption {
- type = types.nullOr types.lines;
+ type = with types; nullOr (oneOf [ lines (listOf (submodule aclOpts)) ]);
default = null;
- example = "* @ALL 8";
+ example = literalExpression ''
+ [
+ {
+ page = "start";
+ actor = "@external";
+ level = "read";
+ }
+ {
+ page = "*";
+ actor = "@users";
+ level = "upload";
+ }
+ ]
+ '';
description = lib.mdDoc ''
Access Control Lists: see <https://www.dokuwiki.org/acl>
Mutually exclusive with services.dokuwiki.aclFile
@@ -97,7 +204,7 @@ let
aclFile = mkOption {
type = with types; nullOr str;
- default = if (config.aclUse && config.acl == null) then "/var/lib/dokuwiki/${name}/acl.auth.php" else null;
+ default = if (config.mergedConfig.useacl && config.acl == null) then "/var/lib/dokuwiki/${name}/acl.auth.php" else null;
description = lib.mdDoc ''
Location of the dokuwiki acl rules. Mutually exclusive with services.dokuwiki.acl
Mutually exclusive with services.dokuwiki.acl which is preferred.
@@ -107,42 +214,22 @@ let
example = "/var/lib/dokuwiki/${name}/acl.auth.php";
};
- aclUse = mkOption {
- type = types.bool;
- default = true;
- description = lib.mdDoc ''
- 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;
- '';
+ type = with types; oneOf [lines (attrsOf bool)];
+ default = {
+ authad = false;
+ authldap = false;
+ authmysql = false;
+ authpgsql = false;
+ };
description = lib.mdDoc ''
List of the dokuwiki (un)loaded plugins.
'';
};
- superUser = mkOption {
- type = types.nullOr types.str;
- default = "@admin";
- description = lib.mdDoc ''
- 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 <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;
+ default = if config.mergedConfig.useacl then "/var/lib/dokuwiki/${name}/users.auth.php" else null;
description = lib.mdDoc ''
Location of the dokuwiki users file. List of users. Format:
@@ -157,17 +244,6 @@ let
example = "/var/lib/dokuwiki/${name}/users.auth.php";
};
- disableActions = mkOption {
- type = types.nullOr types.str;
- default = "";
- example = "search,register";
- description = lib.mdDoc ''
- Disable individual action modes. Refer to
- <https://www.dokuwiki.org/config:action_modes>
- for details on supported values.
- '';
- };
-
plugins = mkOption {
type = types.listOf types.path;
default = [];
@@ -266,7 +342,50 @@ let
'';
};
+ settings = mkOption {
+ type = types.attrsOf types.anything;
+ default = {
+ useacl = true;
+ superuser = "admin";
+ };
+ description = lib.mdDoc ''
+ Structural DokuWiki configuration.
+ Refer to <https://www.dokuwiki.org/config>
+ for details and supported values.
+ Settings can either be directly set from nix,
+ loaded from a file using `._file` or obtained from any
+ PHP function calls using `._raw`.
+ '';
+ example = literalExpression ''
+ {
+ title = "My Wiki";
+ userewrite = 1;
+ disableactions = [ "register" ]; # Will be concatenated with commas
+ plugin.smtp = {
+ smtp_pass._file = "/var/run/secrets/dokuwiki/smtp_pass";
+ smtp_user._raw = "getenv('DOKUWIKI_SMTP_USER')";
+ };
+ }
+ '';
+ };
+
+ mergedConfig = mkOption {
+ readOnly = true;
+ default = mergeConfig config;
+ defaultText = literalExpression ''
+ {
+ useacl = true;
+ }
+ '';
+ description = lib.mdDoc ''
+ Read only representation of the final configuration.
+ '';
+ };
+
extraConfig = mkOption {
+ # This Option is deprecated and only kept until sometime before 23.05 for compatibility reasons
+ # FIXME (@e1mo): Actually remember removing this before 23.05.
+ visible = false;
type = types.nullOr types.lines;
default = null;
example = ''
@@ -277,15 +396,26 @@ let
DokuWiki configuration. Refer to
<https://www.dokuwiki.org/config>
for details on supported values.
+
+ **Note**: Please pass Structured settings via
+ `services.dokuwiki.sites.${name}.settings` instead.
'';
};
+ # Required for the mkRenamedOptionModule
+ # TODO: Remove me once https://github.com/NixOS/nixpkgs/issues/96006 is fixed
+ # or the aclUse, ... options are removed.
+ warnings = mkOption {
+ type = types.listOf types.unspecified;
+ default = [ ];
+ visible = false;
+ internal = true;
};
};
+ };
in
{
- # interface
options = {
services.dokuwiki = {
@@ -315,14 +445,16 @@ in
# implementation
config = mkIf (eachSite != {}) (mkMerge [{
+ warnings = flatten (mapAttrsToList (_: cfg: cfg.warnings) eachSite);
+
assertions = flatten (mapAttrsToList (hostName: cfg:
[{
- assertion = cfg.aclUse -> (cfg.acl != null || cfg.aclFile != null);
- message = "Either services.dokuwiki.sites.${hostName}.acl or services.dokuwiki.sites.${hostName}.aclFile is mandatory if aclUse true";
+ assertion = cfg.mergedConfig.useacl -> (cfg.acl != null || cfg.aclFile != null);
+ message = "Either services.dokuwiki.sites.${hostName}.acl or services.dokuwiki.sites.${hostName}.aclFile is mandatory if settings.useacl is true";
}
{
- assertion = cfg.usersFile != null -> cfg.aclUse != false;
- message = "services.dokuwiki.sites.${hostName}.aclUse must must be true if usersFile is not null";
+ assertion = cfg.usersFile != null -> cfg.mergedConfig.useacl != false;
+ message = "services.dokuwiki.sites.${hostName}.settings.useacl must must be true if usersFile is not null";
}
]) eachSite);
@@ -332,12 +464,9 @@ in
group = webserver.group;
phpPackage = mkPhpPackage cfg;
- phpEnv = {
- DOKUWIKI_LOCAL_CONFIG = "${dokuwikiLocalConfig hostName cfg}";
- DOKUWIKI_PLUGINS_LOCAL_CONFIG = "${dokuwikiPluginsLocalConfig hostName cfg}";
- } // optionalAttrs (cfg.usersFile != null) {
+ phpEnv = optionalAttrs (cfg.usersFile != null) {
DOKUWIKI_USERS_AUTH_CONFIG = "${cfg.usersFile}";
- } //optionalAttrs (cfg.aclUse) {
+ } // optionalAttrs (cfg.mergedConfig.useacl) {
DOKUWIKI_ACL_AUTH_CONFIG = if (cfg.acl != null) then "${dokuwikiAclAuthConfig hostName cfg}" else "${toString cfg.aclFile}";
};
diff --git a/nixos/tests/dokuwiki.nix b/nixos/tests/dokuwiki.nix
index d7c9e483f690..034d6f94af29 100644
--- a/nixos/tests/dokuwiki.nix
+++ b/nixos/tests/dokuwiki.nix
@@ -41,15 +41,39 @@ let
sites = {
"site1.local" = {
- aclUse = false;
- superUser = "admin";
+ templates = [ template-bootstrap3 ];
+ settings = {
+ useacl = false;
+ userewrite = true;
+ template = "bootstrap3";
+ };
};
"site2.local" = {
package = dwWithAcronyms;
usersFile = "/var/lib/dokuwiki/site2.local/users.auth.php";
- superUser = "admin";
- templates = [ template-bootstrap3 ];
plugins = [ plugin-icalevents ];
+ settings = {
+ useacl = true;
+ superuser = "admin";
+ title._file = titleFile;
+ plugin.dummy.empty = "This is just for testing purposes";
+ };
+ acl = [
+ { page = "*";
+ actor = "@ALL";
+ level = "read"; }
+ { page = "acl-test";
+ actor = "@ALL";
+ level = "none"; }
+ ];
+ pluginsConfig = {
+ authad = false;
+ authldap = false;
+ authmysql = false;
+ authpgsql = false;
+ tag = false;
+ icalevents = true;
+ };
};
};
};
@@ -58,6 +82,7 @@ let
networking.hosts."127.0.0.1" = [ "site1.local" "site2.local" ];
};
+ titleFile = pkgs.writeText "dokuwiki-title" "DokuWiki on site2";
in {
name = "dokuwiki";
meta = with pkgs.lib; {
@@ -88,7 +113,7 @@ in {
machine.succeed("curl -sSfL http://site1.local/ | grep 'DokuWiki'")
machine.fail("curl -sSfL 'http://site1.local/doku.php?do=login' | grep 'Login'")
- machine.succeed("curl -sSfL http://site2.local/ | grep 'DokuWiki'")
+ machine.succeed("curl -sSfL http://site2.local/ | grep 'DokuWiki on site2'")
machine.succeed("curl -sSfL 'http://site2.local/doku.php?do=login' | grep 'Login'")
with subtest("ACL Operations"):
@@ -98,12 +123,25 @@ in {
"curl -sSfL --cookie cjar --cookie-jar cjar 'http://site2.local/doku.php?do=login' | grep 'Logged in as: <bdi>Admin</bdi>'",
)
+ # Ensure the generated ACL is valid
+ machine.succeed(
+ "echo 'No Hello World! for @ALL here' >> /var/lib/dokuwiki/site2.local/data/pages/acl-test.txt",
+ "curl -sSL 'http://site2.local/doku.php?id=acl-test' | grep 'Permission Denied'"
+ )
+
with subtest("Customizing Dokuwiki"):
machine.succeed(
"echo 'r13y is awesome!' >> /var/lib/dokuwiki/site2.local/data/pages/acronyms-test.txt",
"curl -sSfL 'http://site2.local/doku.php?id=acronyms-test' | grep '<abbr title=\"reproducibility\">r13y</abbr>'",
)
+ # Testing if plugins (a) be correctly loaded and (b) configuration to enable them works
+ machine.succeed(
+ "echo '~~INFO:syntaxplugins~~' >> /var/lib/dokuwiki/site2.local/data/pages/plugin-list.txt",
+ "curl -sSfL 'http://site2.local/doku.php?id=plugin-list' | grep 'plugin:icalevents'",
+ "curl -sSfL 'http://site2.local/doku.php?id=plugin-list' | (! grep 'plugin:tag')",
+ )
+
# Just to ensure both Webserver configurations are consistent in allowing that
with subtest("Rewriting"):
machine.succeed(