diff --git a/makefu/2configs/deployment/nixos.wiki/default.nix b/makefu/2configs/deployment/nixos.wiki/default.nix
new file mode 100644
index 000000000..cd738ea8b
--- /dev/null
+++ b/makefu/2configs/deployment/nixos.wiki/default.nix
@@ -0,0 +1,9 @@
+{ config, pkgs, ... }:
+
+{
+ imports =
+ [ ./mediawiki.nix
+ ./network.nix
+ ];
+
+}
diff --git a/makefu/2configs/deployment/nixos.wiki/mediawiki.module.nix b/makefu/2configs/deployment/nixos.wiki/mediawiki.module.nix
new file mode 100644
index 000000000..24715f81e
--- /dev/null
+++ b/makefu/2configs/deployment/nixos.wiki/mediawiki.module.nix
@@ -0,0 +1,481 @@
+{ config, pkgs, lib, ... }:
+
+let
+
+ inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption;
+ inherit (lib) concatStringsSep literalExample mapAttrsToList optional optionals optionalString types;
+
+ cfg = config.services.mediawiki;
+ fpm = config.services.phpfpm.pools.mediawiki;
+ user = "mediawiki";
+ group = config.services.httpd.group;
+ cacheDir = "/var/cache/mediawiki";
+ stateDir = "/var/lib/mediawiki";
+
+ pkg = pkgs.stdenv.mkDerivation rec {
+ pname = "mediawiki-full";
+ version = src.version;
+ src = cfg.package;
+
+ installPhase = ''
+ mkdir -p $out
+ cp -r * $out/
+
+ rm -rf $out/share/mediawiki/skins/*
+ rm -rf $out/share/mediawiki/extensions/*
+
+ ${concatStringsSep "\n" (mapAttrsToList (k: v: ''
+ ln -s ${v} $out/share/mediawiki/skins/${k}
+ '') cfg.skins)}
+
+ ${concatStringsSep "\n" (mapAttrsToList (k: v: ''
+ ln -s ${if v != null then v else "$src/share/mediawiki/extensions/${k}"} $out/share/mediawiki/extensions/${k}
+ '') cfg.extensions)}
+ '';
+ };
+
+ mediawikiScripts = pkgs.runCommand "mediawiki-scripts" {
+ buildInputs = [ 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 ${pkgs.php}/bin/php $out/bin/mediawiki-$(basename $i .php) \
+ --set MEDIAWIKI_CONFIG ${mediawikiConfig} \
+ --add-flags ${pkg}/share/mediawiki/maintenance/$i
+ done
+ '';
+
+ mediawikiConfig = pkgs.writeText "LocalSettings.php" ''
+ skins
+ subdirectory of the MediaWiki installation in addition to the default skins.
+ '';
+ };
+
+ extensions = mkOption {
+ default = {};
+ type = types.attrsOf (types.nullOr types.path);
+ description = ''
+ Attribute set of paths whose content is copied to the extensions
+ subdirectory of the MediaWiki installation and enabled in configuration.
+
+ Use null instead of path to enable extensions that are part of MediaWiki.
+ '';
+ example = literalExample ''
+ {
+ Matomo = pkgs.fetchzip {
+ url = "https://github.com/DaSchTour/matomo-mediawiki-extension/archive/v4.0.1.tar.gz";
+ sha256 = "0g5rd3zp0avwlmqagc59cg9bbkn3r7wx7p6yr80s644mj6dlvs1b";
+ };
+ ParserFunctions = null;
+ }
+ '';
+ };
+
+ database = {
+ type = mkOption {
+ type = types.enum [ "mysql" "postgres" "sqlite" "mssql" "oracle" ];
+ default = "mysql";
+ description = "Database engine to use. MySQL/MariaDB is the database of choice by MediaWiki developers.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = "Database host address.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 3306;
+ description = "Database host port.";
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "mediawiki";
+ description = "Database name.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "mediawiki";
+ description = "Database user.";
+ };
+
+ passwordFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/run/keys/mediawiki-dbpassword";
+ description = ''
+ A file containing the password corresponding to
+ .
+ '';
+ };
+
+ tablePrefix = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ If you only have access to a single database and wish to install more than
+ one version of MediaWiki, or have other applications that also use the
+ database, you can give the table names a unique prefix to stop any naming
+ conflicts or confusion.
+ See .
+ '';
+ };
+
+ socket = mkOption {
+ type = types.nullOr types.path;
+ default = if cfg.database.createLocally then "/run/mysqld/mysqld.sock" else null;
+ defaultText = "/run/mysqld/mysqld.sock";
+ description = "Path to the unix socket file to use for authentication.";
+ };
+
+ createLocally = mkOption {
+ type = types.bool;
+ default = cfg.database.type == "mysql";
+ defaultText = "true";
+ description = ''
+ Create the database and database user locally.
+ This currently only applies if database type "mysql" is selected.
+ '';
+ };
+ };
+
+ virtualHost = mkOption {
+ type = types.submodule (import );
+ example = literalExample ''
+ {
+ hostName = "mediawiki.example.org";
+ adminAddr = "webmaster@example.org";
+ forceSSL = true;
+ enableACME = true;
+ }
+ '';
+ description = ''
+ Apache configuration can be done by adapting .
+ See for further information.
+ '';
+ };
+
+ 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 cfg.enable {
+
+ assertions = [
+ { assertion = cfg.database.createLocally -> cfg.database.type == "mysql";
+ message = "services.mediawiki.createLocally is currently only supported for database type 'mysql'";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.user == user;
+ message = "services.mediawiki.database.user must be set to ${user} if services.mediawiki.database.createLocally is set true";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.socket != null;
+ message = "services.mediawiki.database.socket must be set if services.mediawiki.database.createLocally is set to true";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
+ message = "a password cannot be specified if services.mediawiki.database.createLocally is set to true";
+ }
+ ];
+
+ services.mediawiki.skins = {
+ MonoBook = "${cfg.package}/share/mediawiki/skins/MonoBook";
+ Timeless = "${cfg.package}/share/mediawiki/skins/Timeless";
+ Vector = "${cfg.package}/share/mediawiki/skins/Vector";
+ };
+
+ services.mysql = mkIf cfg.database.createLocally {
+ enable = true;
+ package = mkDefault pkgs.mariadb;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ { name = cfg.database.user;
+ ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ services.phpfpm.pools.mediawiki = {
+ inherit user group;
+ phpEnv.MEDIAWIKI_CONFIG = "${mediawikiConfig}";
+ settings = {
+ "listen.owner" = config.services.httpd.user;
+ "listen.group" = config.services.httpd.group;
+ } // cfg.poolConfig;
+ };
+
+ services.httpd = {
+ enable = true;
+ extraModules = [ "proxy_fcgi" ];
+ virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost {
+ documentRoot = mkForce "${pkg}/share/mediawiki";
+ extraConfig = ''
+
+
+
+ SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/"
+
+
+
+ Require all granted
+ DirectoryIndex index.php
+ AllowOverride All
+
+ '' + optionalString (cfg.uploadsDir != null) ''
+ Alias "/images" "${cfg.uploadsDir}"
+
+ Require all granted
+
+ '';
+ } ];
+ };
+
+ systemd.tmpfiles.rules = [
+ "d '${stateDir}' 0750 ${user} ${group} - -"
+ "d '${cacheDir}' 0750 ${user} ${group} - -"
+ ] ++ optionals (cfg.uploadsDir != null) [
+ "d '${cfg.uploadsDir}' 0750 ${user} ${group} - -"
+ "Z '${cfg.uploadsDir}' 0750 ${user} ${group} - -"
+ ];
+
+ systemd.services.mediawiki-init = {
+ wantedBy = [ "multi-user.target" ];
+ before = [ "phpfpm-mediawiki.service" ];
+ after = optional cfg.database.createLocally "mysql.service";
+ script = ''
+ if ! test -e "${stateDir}/secret.key"; then
+ tr -dc A-Za-z0-9 /dev/null | head -c 64 > ${stateDir}/secret.key
+ fi
+
+ echo "exit( wfGetDB( DB_MASTER )->tableExists( 'user' ) ? 1 : 0 );" | \
+ ${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/eval.php --conf ${mediawikiConfig} && \
+ ${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/install.php \
+ --confpath /tmp \
+ --scriptpath ${cfg.basePath} \
+ --dbserver ${cfg.database.host}${optionalString (cfg.database.socket != null) ":${cfg.database.socket}"} \
+ --dbport ${toString cfg.database.port} \
+ --dbname ${cfg.database.name} \
+ ${optionalString (cfg.database.tablePrefix != null) "--dbprefix ${cfg.database.tablePrefix}"} \
+ --dbuser ${cfg.database.user} \
+ ${optionalString (cfg.database.passwordFile != null) "--dbpassfile ${cfg.database.passwordFile}"} \
+ --passfile ${cfg.passwordFile} \
+ "${cfg.name}" \
+ admin
+
+ ${pkgs.php}/bin/php ${pkg}/share/mediawiki/maintenance/update.php --conf ${mediawikiConfig} --quick
+ '';
+
+ serviceConfig = {
+ Type = "oneshot";
+ User = user;
+ Group = group;
+ PrivateTmp = true;
+ };
+ };
+
+ systemd.services.httpd.after = optional (cfg.database.createLocally && cfg.database.type == "mysql") "mysql.service";
+
+ users.users.${user} = {
+ group = group;
+ isSystemUser = true;
+ };
+
+ environment.systemPackages = [ mediawikiScripts ];
+ };
+}
diff --git a/makefu/2configs/deployment/nixos.wiki/mediawiki.nix b/makefu/2configs/deployment/nixos.wiki/mediawiki.nix
new file mode 100644
index 000000000..a346b82cb
--- /dev/null
+++ b/makefu/2configs/deployment/nixos.wiki/mediawiki.nix
@@ -0,0 +1,67 @@
+{ config, pkgs, ... }:
+
+let
+ hostAddress = "192.168.48.1";
+ localAddress = "192.168.48.3";
+in
+
+{
+ containers.mediawiki =
+ { autoStart = true;
+ privateNetwork = true;
+ inherit hostAddress localAddress;
+ config = { config, pkgs, ... }:
+ {
+ # NOTE: This disabling and importing is so that the basePath can be altered
+ disabledModules = [ "services/web-apps/mediawiki.nix" ];
+ imports = [
+ ./mediawiki.module.nix
+ ];
+ time.timeZone = "America/New_York";
+ system.stateVersion = "20.09";
+ networking.defaultGateway = hostAddress;
+ # NOTE: you might want to change this namserver address
+ networking.nameservers = [ "8.8.8.8" ];
+ networking.firewall.allowedTCPPorts = [ 80 ];
+ services.mediawiki = {
+ enable = true;
+ name = "Example Containerized Wiki";
+ # NOTE: here is where the basePath is specified, which requires the imported mediawiki NixOS module
+ basePath = "/wiki";
+ passwordFile = ./mediawiki.password.txt;
+ extraConfig = ''
+ $wgRCFeeds['euerkrebsco'] = array(
+ 'formatter' => 'JSONRCFeedFormatter',
+ 'uri' => 'udp://euer.krebsco.de:5005',
+ 'add_interwiki_prefix' => false,
+ 'omit_bots' => true,
+ );
+ $wgRCFeeds['euerkrebscoIRC'] = array(
+ 'formatter' => 'IRCColourfulRCFeedFormatter',
+ 'uri' => 'udp://euer.krebsco.de:5006',
+ 'add_interwiki_prefix' => false,
+ 'omit_bots' => true,
+ );
+ '';
+ virtualHost = {
+ hostName = "localhost";
+ adminAddr = "root@localhost";
+ forceSSL = false;
+ addSSL = false;
+ onlySSL = false;
+ enableACME = false;
+ };
+ };
+ };
+ };
+
+ # Put the MediaWiki web page behind an NGINX proxy
+ services.nginx = {
+ enable = true;
+ virtualHosts.localhost.locations."/wiki" = {
+ # NOTE: the slash at the end of the URI is important. It causes the location base path to be removed when passed onto the proxy
+ proxyPass = "http://${localAddress}:80/";
+ };
+ };
+
+}
diff --git a/makefu/2configs/deployment/nixos.wiki/mediawiki.password.txt b/makefu/2configs/deployment/nixos.wiki/mediawiki.password.txt
new file mode 100644
index 000000000..b11b15f08
--- /dev/null
+++ b/makefu/2configs/deployment/nixos.wiki/mediawiki.password.txt
@@ -0,0 +1 @@
+thisisthepassword
diff --git a/makefu/2configs/deployment/nixos.wiki/network.nix b/makefu/2configs/deployment/nixos.wiki/network.nix
new file mode 100644
index 000000000..a7ffb28f1
--- /dev/null
+++ b/makefu/2configs/deployment/nixos.wiki/network.nix
@@ -0,0 +1,6 @@
+{
+ networking.networkmanager.unmanaged = [ "interface-name:ve-*" ];
+ networking.nat.enable = true;
+ networking.nat.internalInterfaces = ["ve-+"];
+ networking.nat.externalInterface = "wlan0";
+}