at 25.11-pre 26 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7 8let 9 10 inherit (lib) 11 mkDefault 12 mkEnableOption 13 mkPackageOption 14 mkForce 15 mkIf 16 mkMerge 17 mkOption 18 ; 19 inherit (lib) 20 concatStringsSep 21 literalExpression 22 mapAttrsToList 23 optional 24 optionals 25 optionalString 26 types 27 ; 28 29 cfg = config.services.mediawiki; 30 fpm = config.services.phpfpm.pools.mediawiki; 31 user = "mediawiki"; 32 group = 33 if cfg.webserver == "apache" then 34 config.services.httpd.group 35 else if cfg.webserver == "nginx" then 36 config.services.nginx.group 37 else 38 "mediawiki"; 39 40 cacheDir = "/var/cache/mediawiki"; 41 stateDir = "/var/lib/mediawiki"; 42 43 # https://www.mediawiki.org/wiki/Compatibility 44 php = pkgs.php82; 45 46 pkg = pkgs.stdenv.mkDerivation rec { 47 pname = "mediawiki-full"; 48 inherit (src) version; 49 src = cfg.package; 50 51 installPhase = '' 52 mkdir -p $out 53 cp -r * $out/ 54 55 # try removing directories before symlinking to allow overwriting any builtin extension or skin 56 ${concatStringsSep "\n" ( 57 mapAttrsToList (k: v: '' 58 rm -rf $out/share/mediawiki/skins/${k} 59 ln -s ${v} $out/share/mediawiki/skins/${k} 60 '') cfg.skins 61 )} 62 63 ${concatStringsSep "\n" ( 64 mapAttrsToList (k: v: '' 65 rm -rf $out/share/mediawiki/extensions/${k} 66 ln -s ${ 67 if v != null then v else "$src/share/mediawiki/extensions/${k}" 68 } $out/share/mediawiki/extensions/${k} 69 '') cfg.extensions 70 )} 71 ''; 72 }; 73 74 mediawikiScripts = 75 pkgs.runCommand "mediawiki-scripts" 76 { 77 nativeBuildInputs = [ pkgs.makeWrapper ]; 78 preferLocalBuild = true; 79 } 80 '' 81 mkdir -p $out/bin 82 makeWrapper ${php}/bin/php $out/bin/mediawiki-maintenance \ 83 --set MEDIAWIKI_CONFIG ${mediawikiConfig} \ 84 --add-flags ${pkg}/share/mediawiki/maintenance/run.php 85 86 for i in changePassword createAndPromote deleteUserEmail resetUserEmail userOptions edit nukePage update importDump run; do 87 script="$out/bin/mediawiki-$i" 88 cat <<'EOF' >"$script" 89 #!${pkgs.runtimeShell} 90 become=(exec) 91 if [[ "$(id -u)" != ${user} ]]; then 92 become=(exec /run/wrappers/bin/sudo -u ${user} --) 93 fi 94 "${"$"}{become[@]}" ${placeholder "out"}/bin/mediawiki-maintenance \ 95 EOF 96 if [[ "$i" != "run" ]]; then 97 echo " ${pkg}/share/mediawiki/maintenance/$i.php \"\$@\"" >>"$script" 98 else 99 echo " ${pkg}/share/mediawiki/maintenance/\$1.php \"\''${@:2}\"" >>"$script" 100 fi 101 chmod +x "$script" 102 done 103 ''; 104 105 dbAddr = 106 if cfg.database.socket == null then 107 "${cfg.database.host}:${toString cfg.database.port}" 108 else if cfg.database.type == "mysql" then 109 "${cfg.database.host}:${cfg.database.socket}" 110 else if cfg.database.type == "postgres" then 111 "${cfg.database.socket}" 112 else 113 throw "Unsupported database type: ${cfg.database.type} for socket: ${cfg.database.socket}"; 114 115 mediawikiConfig = pkgs.writeTextFile { 116 name = "LocalSettings.php"; 117 checkPhase = '' 118 ${php}/bin/php --syntax-check "$target" 119 ''; 120 text = '' 121 <?php 122 # Protect against web entry 123 if ( !defined( 'MEDIAWIKI' ) ) { 124 exit; 125 } 126 127 $wgSitename = "${cfg.name}"; 128 $wgMetaNamespace = false; 129 130 ## The URL base path to the directory containing the wiki; 131 ## defaults for all runtime URL paths are based off of this. 132 ## For more information on customizing the URLs 133 ## (like /w/index.php/Page_title to /wiki/Page_title) please see: 134 ## https://www.mediawiki.org/wiki/Manual:Short_URL 135 $wgScriptPath = "${lib.optionalString (cfg.webserver == "nginx") "/w"}"; 136 137 ## The protocol and server name to use in fully-qualified URLs 138 $wgServer = "${cfg.url}"; 139 140 ## The URL path to static resources (images, scripts, etc.) 141 $wgResourceBasePath = $wgScriptPath; 142 143 ${lib.optionalString (cfg.webserver == "nginx") '' 144 $wgArticlePath = "/wiki/$1"; 145 $wgUsePathInfo = true; 146 ''} 147 148 ## The URL path to the logo. Make sure you change this from the default, 149 ## or else you'll overwrite your logo when you upgrade! 150 $wgLogo = "$wgResourceBasePath/resources/assets/wiki.png"; 151 152 ## UPO means: this is also a user preference option 153 154 $wgEnableEmail = true; 155 $wgEnableUserEmail = true; # UPO 156 157 $wgPasswordSender = "${cfg.passwordSender}"; 158 159 $wgEnotifUserTalk = false; # UPO 160 $wgEnotifWatchlist = false; # UPO 161 $wgEmailAuthentication = true; 162 163 ## Database settings 164 $wgDBtype = "${cfg.database.type}"; 165 $wgDBserver = "${dbAddr}"; 166 $wgDBport = "${toString cfg.database.port}"; 167 $wgDBname = "${cfg.database.name}"; 168 $wgDBuser = "${cfg.database.user}"; 169 ${optionalString ( 170 cfg.database.passwordFile != null 171 ) "$wgDBpassword = file_get_contents(\"${cfg.database.passwordFile}\");"} 172 173 ${optionalString (cfg.database.type == "mysql" && cfg.database.tablePrefix != null) '' 174 # MySQL specific settings 175 $wgDBprefix = "${cfg.database.tablePrefix}"; 176 ''} 177 178 ${optionalString (cfg.database.type == "mysql") '' 179 # MySQL table options to use during installation or update 180 $wgDBTableOptions = "ENGINE=InnoDB, DEFAULT CHARSET=binary"; 181 ''} 182 183 ## Shared memory settings 184 $wgMainCacheType = CACHE_NONE; 185 $wgMemCachedServers = []; 186 187 ${optionalString (cfg.uploadsDir != null) '' 188 $wgEnableUploads = true; 189 $wgUploadDirectory = "${cfg.uploadsDir}"; 190 ''} 191 192 $wgUseImageMagick = true; 193 $wgImageMagickConvertCommand = "${pkgs.imagemagick}/bin/convert"; 194 195 # InstantCommons allows wiki to use images from https://commons.wikimedia.org 196 $wgUseInstantCommons = false; 197 198 # Periodically send a pingback to https://www.mediawiki.org/ with basic data 199 # about this MediaWiki instance. The Wikimedia Foundation shares this data 200 # with MediaWiki developers to help guide future development efforts. 201 $wgPingback = true; 202 203 ## If you use ImageMagick (or any other shell command) on a 204 ## Linux server, this will need to be set to the name of an 205 ## available UTF-8 locale 206 $wgShellLocale = "C.UTF-8"; 207 208 ## Set $wgCacheDirectory to a writable directory on the web server 209 ## to make your wiki go slightly faster. The directory should not 210 ## be publicly accessible from the web. 211 $wgCacheDirectory = "${cacheDir}"; 212 213 # Site language code, should be one of the list in ./languages/data/Names.php 214 $wgLanguageCode = "en"; 215 216 $wgSecretKey = file_get_contents("${stateDir}/secret.key"); 217 218 # Changing this will log out all existing sessions. 219 $wgAuthenticationTokenVersion = ""; 220 221 ## For attaching licensing metadata to pages, and displaying an 222 ## appropriate copyright notice / icon. GNU Free Documentation 223 ## License and Creative Commons licenses are supported so far. 224 $wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright 225 $wgRightsUrl = ""; 226 $wgRightsText = ""; 227 $wgRightsIcon = ""; 228 229 # Path to the GNU diff3 utility. Used for conflict resolution. 230 $wgDiff = "${pkgs.diffutils}/bin/diff"; 231 $wgDiff3 = "${pkgs.diffutils}/bin/diff3"; 232 233 # Enabled skins. 234 ${concatStringsSep "\n" (mapAttrsToList (k: v: "wfLoadSkin('${k}');") cfg.skins)} 235 236 # Enabled extensions. 237 ${concatStringsSep "\n" (mapAttrsToList (k: v: "wfLoadExtension('${k}');") cfg.extensions)} 238 239 240 # End of automatically generated settings. 241 # Add more configuration options below. 242 243 ${cfg.extraConfig} 244 ''; 245 }; 246 247 withTrailingSlash = str: if lib.hasSuffix "/" str then str else "${str}/"; 248in 249{ 250 # interface 251 options = { 252 services.mediawiki = { 253 254 enable = mkEnableOption "MediaWiki"; 255 256 package = mkPackageOption pkgs "mediawiki" { }; 257 258 finalPackage = mkOption { 259 type = types.package; 260 readOnly = true; 261 default = pkg; 262 defaultText = literalExpression "pkg"; 263 description = '' 264 The final package used by the module. This is the package that will have extensions and skins installed. 265 ''; 266 }; 267 268 name = mkOption { 269 type = types.str; 270 default = "MediaWiki"; 271 example = "Foobar Wiki"; 272 description = "Name of the wiki."; 273 }; 274 275 url = mkOption { 276 type = types.str; 277 default = 278 if cfg.webserver == "apache" then 279 "${ 280 if 281 cfg.httpd.virtualHost.addSSL || cfg.httpd.virtualHost.forceSSL || cfg.httpd.virtualHost.onlySSL 282 then 283 "https" 284 else 285 "http" 286 }://${cfg.httpd.virtualHost.hostName}" 287 else if cfg.webserver == "nginx" then 288 let 289 hasSSL = host: host.forceSSL || host.addSSL; 290 in 291 "${ 292 if hasSSL config.services.nginx.virtualHosts.${cfg.nginx.hostName} then "https" else "http" 293 }://${cfg.nginx.hostName}" 294 else 295 "http://localhost"; 296 defaultText = '' 297 if "mediawiki uses ssl" then "{"https" else "http"}://''${cfg.hostName}" else "http://localhost"; 298 ''; 299 example = "https://wiki.example.org"; 300 description = "URL of the wiki."; 301 }; 302 303 uploadsDir = mkOption { 304 type = types.nullOr types.path; 305 default = "${stateDir}/uploads"; 306 description = '' 307 This directory is used for uploads of pictures. The directory passed here is automatically 308 created and permissions adjusted as required. 309 ''; 310 }; 311 312 passwordFile = mkOption { 313 type = types.path; 314 description = '' 315 A file containing the initial password for the administrator account "admin". 316 ''; 317 example = "/run/keys/mediawiki-password"; 318 }; 319 320 passwordSender = mkOption { 321 type = types.str; 322 default = 323 if cfg.webserver == "apache" then 324 if cfg.httpd.virtualHost.adminAddr != null then 325 cfg.httpd.virtualHost.adminAddr 326 else 327 config.services.httpd.adminAddr 328 else 329 "root@localhost"; 330 defaultText = literalExpression '' 331 if cfg.webserver == "apache" then 332 if cfg.httpd.virtualHost.adminAddr != null then 333 cfg.httpd.virtualHost.adminAddr 334 else 335 config.services.httpd.adminAddr else "root@localhost" 336 ''; 337 description = "Contact address for password reset."; 338 }; 339 340 skins = mkOption { 341 default = { }; 342 type = types.attrsOf types.path; 343 description = '' 344 Attribute set of paths whose content is copied to the {file}`skins` 345 subdirectory of the MediaWiki installation in addition to the default skins. 346 ''; 347 }; 348 349 extensions = mkOption { 350 default = { }; 351 type = types.attrsOf (types.nullOr types.path); 352 description = '' 353 Attribute set of paths whose content is copied to the {file}`extensions` 354 subdirectory of the MediaWiki installation and enabled in configuration. 355 356 Use `null` instead of path to enable extensions that are part of MediaWiki. 357 ''; 358 example = literalExpression '' 359 { 360 Matomo = pkgs.fetchzip { 361 url = "https://github.com/DaSchTour/matomo-mediawiki-extension/archive/v4.0.1.tar.gz"; 362 sha256 = "0g5rd3zp0avwlmqagc59cg9bbkn3r7wx7p6yr80s644mj6dlvs1b"; 363 }; 364 ParserFunctions = null; 365 } 366 ''; 367 }; 368 369 webserver = mkOption { 370 type = types.enum [ 371 "apache" 372 "none" 373 "nginx" 374 ]; 375 default = "apache"; 376 description = "Webserver to use."; 377 }; 378 379 database = { 380 type = mkOption { 381 type = types.enum [ 382 "mysql" 383 "postgres" 384 "mssql" 385 "oracle" 386 ]; 387 default = "mysql"; 388 description = "Database engine to use. MySQL/MariaDB is the database of choice by MediaWiki developers."; 389 }; 390 391 host = mkOption { 392 type = types.str; 393 default = "localhost"; 394 description = "Database host address."; 395 }; 396 397 port = mkOption { 398 type = types.port; 399 default = if cfg.database.type == "mysql" then 3306 else 5432; 400 defaultText = literalExpression "3306"; 401 description = "Database host port."; 402 }; 403 404 name = mkOption { 405 type = types.str; 406 default = "mediawiki"; 407 description = "Database name."; 408 }; 409 410 user = mkOption { 411 type = types.str; 412 default = "mediawiki"; 413 description = "Database user."; 414 }; 415 416 passwordFile = mkOption { 417 type = types.nullOr types.path; 418 default = null; 419 example = "/run/keys/mediawiki-dbpassword"; 420 description = '' 421 A file containing the password corresponding to 422 {option}`database.user`. 423 ''; 424 }; 425 426 tablePrefix = mkOption { 427 type = types.nullOr types.str; 428 default = null; 429 description = '' 430 If you only have access to a single database and wish to install more than 431 one version of MediaWiki, or have other applications that also use the 432 database, you can give the table names a unique prefix to stop any naming 433 conflicts or confusion. 434 See <https://www.mediawiki.org/wiki/Manual:$wgDBprefix>. 435 ''; 436 }; 437 438 socket = mkOption { 439 type = types.nullOr types.path; 440 default = 441 if (cfg.database.type == "mysql" && cfg.database.createLocally) then 442 "/run/mysqld/mysqld.sock" 443 else if (cfg.database.type == "postgres" && cfg.database.createLocally) then 444 "/run/postgresql" 445 else 446 null; 447 defaultText = literalExpression "/run/mysqld/mysqld.sock"; 448 description = "Path to the unix socket file to use for authentication."; 449 }; 450 451 createLocally = mkOption { 452 type = types.bool; 453 default = cfg.database.type == "mysql" || cfg.database.type == "postgres"; 454 defaultText = literalExpression "true"; 455 description = '' 456 Create the database and database user locally. 457 This currently only applies if database type "mysql" is selected. 458 ''; 459 }; 460 }; 461 462 nginx.hostName = mkOption { 463 type = types.str; 464 example = literalExpression ''wiki.example.com''; 465 default = "localhost"; 466 description = '' 467 The hostname to use for the nginx virtual host. 468 This is used to generate the nginx configuration. 469 ''; 470 }; 471 472 httpd.virtualHost = mkOption { 473 type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix); 474 example = literalExpression '' 475 { 476 hostName = "mediawiki.example.org"; 477 adminAddr = "webmaster@example.org"; 478 forceSSL = true; 479 enableACME = true; 480 } 481 ''; 482 description = '' 483 Apache configuration can be done by adapting {option}`services.httpd.virtualHosts`. 484 See [](#opt-services.httpd.virtualHosts) for further information. 485 ''; 486 }; 487 488 poolConfig = mkOption { 489 type = 490 with types; 491 attrsOf (oneOf [ 492 str 493 int 494 bool 495 ]); 496 default = { 497 "pm" = "dynamic"; 498 "pm.max_children" = 32; 499 "pm.start_servers" = 2; 500 "pm.min_spare_servers" = 2; 501 "pm.max_spare_servers" = 4; 502 "pm.max_requests" = 500; 503 }; 504 description = '' 505 Options for the MediaWiki PHP pool. See the documentation on `php-fpm.conf` 506 for details on configuration directives. 507 ''; 508 }; 509 510 extraConfig = mkOption { 511 type = types.lines; 512 description = '' 513 Any additional text to be appended to MediaWiki's 514 LocalSettings.php configuration file. For configuration 515 settings, see <https://www.mediawiki.org/wiki/Manual:Configuration_settings>. 516 ''; 517 default = ""; 518 example = '' 519 $wgEnableEmail = false; 520 ''; 521 }; 522 523 }; 524 }; 525 526 imports = [ 527 (lib.mkRenamedOptionModule 528 [ "services" "mediawiki" "virtualHost" ] 529 [ "services" "mediawiki" "httpd" "virtualHost" ] 530 ) 531 ]; 532 533 # implementation 534 config = mkIf cfg.enable { 535 536 assertions = [ 537 { 538 assertion = 539 cfg.database.createLocally -> (cfg.database.type == "mysql" || cfg.database.type == "postgres"); 540 message = "services.mediawiki.createLocally is currently only supported for database type 'mysql' and 'postgres'"; 541 } 542 { 543 assertion = 544 cfg.database.createLocally -> cfg.database.user == user && cfg.database.name == cfg.database.user; 545 message = "services.mediawiki.database.user must be set to ${user} if services.mediawiki.database.createLocally is set true"; 546 } 547 { 548 assertion = cfg.database.createLocally -> cfg.database.socket != null; 549 message = "services.mediawiki.database.socket must be set if services.mediawiki.database.createLocally is set to true"; 550 } 551 { 552 assertion = cfg.database.createLocally -> cfg.database.passwordFile == null; 553 message = "a password cannot be specified if services.mediawiki.database.createLocally is set to true"; 554 } 555 ]; 556 557 services.mediawiki.skins = { 558 MonoBook = "${cfg.package}/share/mediawiki/skins/MonoBook"; 559 Timeless = "${cfg.package}/share/mediawiki/skins/Timeless"; 560 Vector = "${cfg.package}/share/mediawiki/skins/Vector"; 561 }; 562 563 services.mysql = mkIf (cfg.database.type == "mysql" && cfg.database.createLocally) { 564 enable = true; 565 package = mkDefault pkgs.mariadb; 566 ensureDatabases = [ cfg.database.name ]; 567 ensureUsers = [ 568 { 569 name = cfg.database.user; 570 ensurePermissions = { 571 "${cfg.database.name}.*" = "ALL PRIVILEGES"; 572 }; 573 } 574 ]; 575 }; 576 577 services.postgresql = mkIf (cfg.database.type == "postgres" && cfg.database.createLocally) { 578 enable = true; 579 ensureDatabases = [ cfg.database.name ]; 580 ensureUsers = [ 581 { 582 name = cfg.database.user; 583 ensureDBOwnership = true; 584 } 585 ]; 586 }; 587 588 services.phpfpm.pools.mediawiki = { 589 inherit user group; 590 phpEnv.MEDIAWIKI_CONFIG = "${mediawikiConfig}"; 591 phpPackage = php; 592 settings = 593 ( 594 if (cfg.webserver == "apache") then 595 { 596 "listen.owner" = config.services.httpd.user; 597 "listen.group" = config.services.httpd.group; 598 } 599 else if (cfg.webserver == "nginx") then 600 { 601 "listen.owner" = config.services.nginx.user; 602 "listen.group" = config.services.nginx.group; 603 } 604 else 605 { 606 "listen.owner" = user; 607 "listen.group" = group; 608 } 609 ) 610 // cfg.poolConfig; 611 }; 612 613 services.httpd = lib.mkIf (cfg.webserver == "apache") { 614 enable = true; 615 extraModules = [ "proxy_fcgi" ]; 616 virtualHosts.${cfg.httpd.virtualHost.hostName} = mkMerge [ 617 cfg.httpd.virtualHost 618 { 619 documentRoot = mkForce "${pkg}/share/mediawiki"; 620 extraConfig = 621 '' 622 <Directory "${pkg}/share/mediawiki"> 623 <FilesMatch "\.php$"> 624 <If "-f %{REQUEST_FILENAME}"> 625 SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" 626 </If> 627 </FilesMatch> 628 629 Require all granted 630 DirectoryIndex index.php 631 AllowOverride All 632 </Directory> 633 '' 634 + optionalString (cfg.uploadsDir != null) '' 635 Alias "/images" "${cfg.uploadsDir}" 636 <Directory "${cfg.uploadsDir}"> 637 Require all granted 638 </Directory> 639 ''; 640 } 641 ]; 642 }; 643 # inspired by https://www.mediawiki.org/wiki/Manual:Short_URL/Nginx 644 services.nginx = lib.mkIf (cfg.webserver == "nginx") { 645 enable = true; 646 virtualHosts.${config.services.mediawiki.nginx.hostName} = { 647 root = "${pkg}/share/mediawiki"; 648 locations = { 649 "~ ^/w/(index|load|api|thumb|opensearch_desc|rest|img_auth)\\.php$".extraConfig = '' 650 rewrite ^/w/(.*) /$1 break; 651 include ${config.services.nginx.package}/conf/fastcgi.conf; 652 fastcgi_index index.php; 653 fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket}; 654 ''; 655 "/w/images/".alias = withTrailingSlash cfg.uploadsDir; 656 # Deny access to deleted images folder 657 "/w/images/deleted".extraConfig = '' 658 deny all; 659 ''; 660 # MediaWiki assets (usually images) 661 "~ ^/w/resources/(assets|lib|src)".extraConfig = '' 662 rewrite ^/w(/.*) $1 break; 663 add_header Cache-Control "public"; 664 expires 7d; 665 ''; 666 # Assets, scripts and styles from skins and extensions 667 "~ ^/w/(skins|extensions)/.+\\.(css|js|gif|jpg|jpeg|png|svg|wasm|ttf|woff|woff2)$".extraConfig = '' 668 rewrite ^/w(/.*) $1 break; 669 add_header Cache-Control "public"; 670 expires 7d; 671 ''; 672 673 # Handling for Mediawiki REST API, see [[mw:API:REST_API]] 674 "/w/rest.php/".tryFiles = "$uri $uri/ /w/rest.php?$query_string"; 675 676 # Handling for the article path (pretty URLs) 677 "/wiki/".extraConfig = '' 678 rewrite ^/wiki/(?<pagename>.*)$ /w/index.php; 679 ''; 680 681 # Explicit access to the root website, redirect to main page (adapt as needed) 682 "= /".extraConfig = '' 683 return 301 /wiki/; 684 ''; 685 686 # Every other entry point will be disallowed. 687 # Add specific rules for other entry points/images as needed above this 688 "/".extraConfig = '' 689 return 404; 690 ''; 691 }; 692 }; 693 }; 694 695 systemd.tmpfiles.rules = 696 [ 697 "d '${stateDir}' 0750 ${user} ${group} - -" 698 "d '${cacheDir}' 0750 ${user} ${group} - -" 699 ] 700 ++ optionals (cfg.uploadsDir != null) [ 701 "d '${cfg.uploadsDir}' 0750 ${user} ${group} - -" 702 "Z '${cfg.uploadsDir}' 0750 ${user} ${group} - -" 703 ]; 704 705 systemd.services.mediawiki-init = { 706 wantedBy = [ "multi-user.target" ]; 707 before = [ "phpfpm-mediawiki.service" ]; 708 after = 709 optional (cfg.database.type == "mysql" && cfg.database.createLocally) "mysql.service" 710 ++ optional (cfg.database.type == "postgres" && cfg.database.createLocally) "postgresql.service"; 711 script = '' 712 if ! test -e "${stateDir}/secret.key"; then 713 tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c 64 > ${stateDir}/secret.key 714 fi 715 716 echo "exit( wfGetDB( DB_PRIMARY )->tableExists( 'user' ) ? 1 : 0 );" | \ 717 ${php}/bin/php ${pkg}/share/mediawiki/maintenance/eval.php --conf ${mediawikiConfig} && \ 718 ${php}/bin/php ${pkg}/share/mediawiki/maintenance/install.php \ 719 --confpath /tmp \ 720 --scriptpath / \ 721 --dbserver ${lib.escapeShellArg dbAddr} \ 722 --dbport ${toString cfg.database.port} \ 723 --dbname ${lib.escapeShellArg cfg.database.name} \ 724 ${ 725 optionalString ( 726 cfg.database.tablePrefix != null 727 ) "--dbprefix ${lib.escapeShellArg cfg.database.tablePrefix}" 728 } \ 729 --dbuser ${lib.escapeShellArg cfg.database.user} \ 730 ${ 731 optionalString ( 732 cfg.database.passwordFile != null 733 ) "--dbpassfile ${lib.escapeShellArg cfg.database.passwordFile}" 734 } \ 735 --passfile ${lib.escapeShellArg cfg.passwordFile} \ 736 --dbtype ${cfg.database.type} \ 737 ${lib.escapeShellArg cfg.name} \ 738 admin 739 740 ${php}/bin/php ${pkg}/share/mediawiki/maintenance/update.php --conf ${mediawikiConfig} --quick --skip-external-dependencies 741 ''; 742 743 serviceConfig = { 744 Type = "oneshot"; 745 User = user; 746 Group = group; 747 PrivateTmp = true; 748 }; 749 }; 750 751 systemd.services.httpd.after = 752 optional ( 753 cfg.webserver == "apache" && cfg.database.createLocally && cfg.database.type == "mysql" 754 ) "mysql.service" 755 ++ optional ( 756 cfg.webserver == "apache" && cfg.database.createLocally && cfg.database.type == "postgres" 757 ) "postgresql.service"; 758 759 users.users.${user} = { 760 inherit group; 761 isSystemUser = true; 762 }; 763 users.groups.${group} = { }; 764 765 environment.systemPackages = [ mediawikiScripts ]; 766 }; 767}