From 11fdc3a0ab2b8e9392e65d91135dffdd7bea75b3 Mon Sep 17 00:00:00 2001 From: Alexander Sieg Date: Tue, 25 Jun 2024 08:16:11 +0200 Subject: [PATCH 1/2] hosts: init web01 --- hosts/web01/default.nix | 33 +++++++++++++++++++++++++++++++++ hosts/web01/disko.nix | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 hosts/web01/default.nix create mode 100644 hosts/web01/disko.nix diff --git a/hosts/web01/default.nix b/hosts/web01/default.nix new file mode 100644 index 0000000..87b524e --- /dev/null +++ b/hosts/web01/default.nix @@ -0,0 +1,33 @@ +{ inputs, config, ... }: { + + imports = [ + ./disko.nix + inputs.disko.nixosModules.disko + ../../profiles/entropia-cluster-vm + ]; + + networking.hostName = "web01"; + networking.domain = "entropia.de"; + deployment.targetHost = config.networking.fqdn; + + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + system.stateVersion = "24.11"; + + networking.useNetworkd = true; + systemd.network.wait-online.anyInterface = true; + systemd.network.networks."10-eth" = { + enable = true; + name = "en*"; + dns = [ "1.1.1.1" ]; + address = [ + "45.140.180.57/27" + "2a0e:c5c0:0:201::18/64" + ]; + routes = [ + { routeConfig = { Destination = "0.0.0.0/0"; Gateway = "45.140.180.33"; }; } + { routeConfig = { Destination = "::/0"; Gateway = "2a0e:c5c0:0:201::1"; }; } + ]; + }; + services.resolved.enable = true; +} diff --git a/hosts/web01/disko.nix b/hosts/web01/disko.nix new file mode 100644 index 0000000..588a5d7 --- /dev/null +++ b/hosts/web01/disko.nix @@ -0,0 +1,36 @@ +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/vda"; + content = { + type = "gpt"; + partitions = { + boot = { + size = "1M"; + type = "EF02"; # for grub MBR + }; + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + root = { + size = "100%"; + content = { + type = "filesystem"; + format = "xfs"; + mountpoint = "/"; + }; + }; + }; + }; + }; + }; + }; +} From 7cf0cf8c87d1885b0757c0cf786c91ab25b82b7c Mon Sep 17 00:00:00 2001 From: Alexander Sieg Date: Wed, 26 Jun 2024 10:45:47 +0200 Subject: [PATCH 2/2] modules/mediawiki: adapt upstream module for multiple wikis on one host --- hosts/web01/default.nix | 5 + modules/default.nix | 8 +- modules/mediawiki/default.nix | 551 ++++++++++++++++++++++++++++++++++ modules/mediawiki/non-default | 0 4 files changed, 562 insertions(+), 2 deletions(-) create mode 100644 modules/mediawiki/default.nix create mode 100644 modules/mediawiki/non-default diff --git a/hosts/web01/default.nix b/hosts/web01/default.nix index 87b524e..d6c444b 100644 --- a/hosts/web01/default.nix +++ b/hosts/web01/default.nix @@ -4,6 +4,11 @@ ./disko.nix inputs.disko.nixosModules.disko ../../profiles/entropia-cluster-vm + inputs.self.nixosModules.mediawiki + ]; + + disabledModules = [ + "services/web-apps/mediawiki.nix" ]; networking.hostName = "web01"; diff --git a/modules/default.nix b/modules/default.nix index c218835..7f5c8cd 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -7,7 +7,9 @@ genAttrs filterAttrs attrNames - attrValues; + attrValues + pathIsRegularFile + ; isDir = _name: type: type == "directory"; @@ -23,9 +25,11 @@ }; modules = genAttrs moduleFolders buildModule; + + defaultModules = filterAttrs (name: _: ! pathIsRegularFile (./. + "/${name}/non-default")) modules; in { - default.imports = attrValues modules; + default.imports = attrValues defaultModules; } // modules; } diff --git a/modules/mediawiki/default.nix b/modules/mediawiki/default.nix new file mode 100644 index 0000000..362ad2f --- /dev/null +++ b/modules/mediawiki/default.nix @@ -0,0 +1,551 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + + inherit (lib) + mkDefault + mkEnableOption + mkPackageOption + mkForce + mkIf + mkMerge + mkOption + ; + inherit (lib) + concatStringsSep + literalExpression + mapAttrsToList + optional + optionals + optionalString + types + filterAttrs + ; + + mediawikiName = name: "mediawiki-${name}"; + + cacheDir = name: "/var/cache/mediawiki-${name}"; + stateDir = name: "/var/lib/mediawiki-${name}"; + + # https://www.mediawiki.org/wiki/Compatibility + php = pkgs.php81; + + pkg = name: conf: pkgs.stdenv.mkDerivation rec { + pname = "${mediawikiName name}-full"; + inherit (src) version; + src = conf.package; + + installPhase = '' + mkdir -p $out + cp -r * $out/ + + # try removing directories before symlinking to allow overwriting any builtin extension or skin + ${concatStringsSep "\n" ( + mapAttrsToList (k: v: '' + rm -rf $out/share/mediawiki/skins/${k} + ln -s ${v} $out/share/mediawiki/skins/${k} + '') conf.skins + )} + + ${concatStringsSep "\n" ( + mapAttrsToList (k: v: '' + rm -rf $out/share/mediawiki/extensions/${k} + ln -s ${ + if v != null then v else "$src/share/mediawiki/extensions/${k}" + } $out/share/mediawiki/extensions/${k} + '') conf.extensions + )} + ''; + }; + + mediawikiScripts = name: conf: + pkgs.runCommand "${mediawikiName name}-scripts" + { + nativeBuildInputs = [ pkgs.makeWrapper ]; + preferLocalBuild = true; + } + '' + mkdir -p $out/bin + for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php update.php; do + makeWrapper ${php}/bin/php $out/bin/${mediawikiName name}-$(basename $i .php) \ + --set MEDIAWIKI_CONFIG ${mediawikiConfig name conf} \ + --add-flags ${pkg name conf}/share/mediawiki/maintenance/$i + done + ''; + + mediawikiConfig = name: conf: pkgs.writeText "LocalSettings.php" '' + . + ''; + }; + + socket = mkOption { + type = types.nullOr types.path; + default = "/run/mysqld/mysqld.sock"; + defaultText = literalExpression "/run/mysqld/mysqld.sock"; + description = "Path to the unix socket file to use for authentication."; + }; + + createLocally = mkOption { + type = types.bool; + default = config.database.type == "mysql"; + defaultText = literalExpression "true"; + description = '' + Create the database and database user locally. + This currently only applies if database type "mysql" is selected. + ''; + }; + }; + + 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 MediaWiki PHP pool. See the documentation on `php-fpm.conf` + for details on configuration directives. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + description = '' + Any additional text to be appended to MediaWiki's + LocalSettings.php configuration file. For configuration + settings, see . + ''; + default = ""; + example = '' + $wgEnableEmail = false; + ''; + }; + }; + } + ) + ); + }; + + }; + }; + + # implementation + config = mkIf (enabledServers != { }) { + + assertions = lib.attrValues ( + lib.mapAttrs (name: conf: [ + { + assertion = + conf.database.createLocally -> (conf.database.type == "mysql"); + message = "services.mediawiki.${name}.createLocally is currently only supported for database type 'mysql'"; + } + { + assertion = + conf.database.createLocally + -> conf.database.user == (mediawikiName name) && conf.database.name == conf.database.user; + message = "services.mediawiki.${name}.database.user must be set to ${mediawikiName name} if services.mediawiki.${mediawikiName name}.database.createLocally is set true"; + } + { + assertion = conf.database.createLocally -> conf.database.socket != null; + message = "services.mediawiki.${name}.database.socket must be set if services.mediawiki.${name}.database.createLocally is set to true"; + } + { + assertion = conf.database.createLocally -> conf.database.passwordFile == null; + message = "a password cannot be specified if services.mediawiki.${name}.database.createLocally is set to true"; + } + ]) enabledServers + ); + + services.mysql = lib.concatMapAttrs (name: conf: { + enable = true; + package = mkDefault pkgs.mariadb; + ensureDatabases = [ conf.database.name ]; + ensureUsers = [ + { + name = conf.database.user; + ensurePermissions = { + "${conf.database.name}.*" = "ALL PRIVILEGES"; + }; + } + ]; + }) enabledServers; + + services.phpfpm.pools = lib.concatMapAttrs (name: conf: { + "${mediawikiName name}" = { + user = mediawikiName name; + group = mediawikiName name; + phpEnv.MEDIAWIKI_CONFIG = "${mediawikiConfig name conf}"; + phpPackage = php; + settings = + { + "listen.owner" = mediawikiName name; + "listen.group" = mediawikiName name; + } + // conf.poolConfig; + }; + }) enabledServers; + + systemd.tmpfiles.rules = lib.mapAttrsToList (name: conf: + [ + "d '${stateDir name}' 0750 ${mediawikiName name} ${mediawikiName name} - -" + "d '${cacheDir name}' 0750 ${mediawikiName name} ${mediawikiName name} - -" + ] + ++ optionals (conf.uploadsDir != null) [ + "d '${conf.uploadsDir}' 0750 ${mediawikiName name} ${mediawikiName name} - -" + "Z '${conf.uploadsDir}' 0750 ${mediawikiName name} ${mediawikiName name} - -" + ]) enabledServers; + + systemd.services = lib.concatMapAttrs (name: conf: + { + "${mediawikiName name}-init" = { + wantedBy = [ "multi-user.target" ]; + before = [ "phpfpm-mediawiki.service" ]; + after = "mysql.service"; + script = '' + if ! test -e "${stateDir name}/secret.key"; then + tr -dc A-Za-z0-9 /dev/null | head -c 64 > ${stateDir name}/secret.key + fi + + echo "exit( wfGetDB( DB_MASTER )->tableExists( 'user' ) ? 1 : 0 );" | \ + ${php}/bin/php ${pkg name conf}/share/mediawiki/maintenance/eval.php --conf ${mediawikiConfig name conf} && \ + ${php}/bin/php ${pkg name conf}/share/mediawiki/maintenance/install.php \ + --confpath /tmp \ + --scriptpath / \ + --dbserver ${lib.escapeShellArg "${conf.database.host}:${conf.database.socket}"} \ + --dbport ${toString conf.database.port} \ + --dbname ${lib.escapeShellArg conf.database.name} \ + ${ + optionalString ( + conf.database.tablePrefix != null + ) "--dbprefix ${lib.escapeShellArg conf.database.tablePrefix}" + } \ + --dbuser ${lib.escapeShellArg conf.database.user} \ + ${ + optionalString ( + conf.database.passwordFile != null + ) "--dbpassfile ${lib.escapeShellArg conf.database.passwordFile}" + } \ + --passfile ${lib.escapeShellArg conf.passwordFile} \ + --dbtype ${conf.database.type} \ + ${lib.escapeShellArg conf.name} \ + admin + + ${php}/bin/php ${pkg name conf}/share/mediawiki/maintenance/update.php --conf ${mediawikiConfig name conf} --quick + ''; + + serviceConfig = { + Type = "oneshot"; + User = mediawikiName name; + Group = mediawikiName name; + PrivateTmp = true; + }; + }; + }) enabledServers; + + users = lib.concatMapAttrs (name: conf: { + users.${mediawikiName name} = { + group = mediawikiName name; + isSystemUser = true; + }; + users.groups.${mediawikiName name} = { }; + }) enabledServers; + + environment.systemPackages = lib.mapAttrsToList mediawikiScripts enabledServers; + }; +} diff --git a/modules/mediawiki/non-default b/modules/mediawiki/non-default new file mode 100644 index 0000000..e69de29