1{ config, lib, pkgs, serverInfo, php, ... }: 2 3with lib; 4 5let 6 7 httpd = serverInfo.serverConfig.package; 8 9 version24 = !versionOlder httpd.version "2.4"; 10 11 allGranted = if version24 then '' 12 Require all granted 13 '' else '' 14 Order allow,deny 15 Allow from all 16 ''; 17 18 mediawikiConfig = pkgs.writeText "LocalSettings.php" 19 '' 20 <?php 21 # Copied verbatim from the default (generated) LocalSettings.php. 22 if( defined( 'MW_INSTALL_PATH' ) ) { 23 $IP = MW_INSTALL_PATH; 24 } else { 25 $IP = dirname( __FILE__ ); 26 } 27 28 $path = array( $IP, "$IP/includes", "$IP/languages" ); 29 set_include_path( implode( PATH_SEPARATOR, $path ) . PATH_SEPARATOR . get_include_path() ); 30 31 require_once( "$IP/includes/DefaultSettings.php" ); 32 33 if ( $wgCommandLineMode ) { 34 if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) { 35 die( "This script must be run from the command line\n" ); 36 } 37 } 38 39 $wgScriptPath = "${config.urlPrefix}"; 40 41 # We probably need to set $wgSecretKey and $wgCacheEpoch. 42 43 # Paths to external programs. 44 $wgDiff3 = "${pkgs.diffutils}/bin/diff3"; 45 $wgDiff = "${pkgs.diffutils}/bin/diff"; 46 $wgImageMagickConvertCommand = "${pkgs.imagemagick.out}/bin/convert"; 47 48 #$wgDebugLogFile = "/tmp/mediawiki_debug_log.txt"; 49 50 # Database configuration. 51 $wgDBtype = "${config.dbType}"; 52 $wgDBserver = "${config.dbServer}"; 53 $wgDBuser = "${config.dbUser}"; 54 $wgDBpassword = "${config.dbPassword}"; 55 $wgDBname = "${config.dbName}"; 56 57 # E-mail. 58 $wgEmergencyContact = "${config.emergencyContact}"; 59 $wgPasswordSender = "${config.passwordSender}"; 60 61 $wgSitename = "${config.siteName}"; 62 63 ${optionalString (config.logo != "") '' 64 $wgLogo = "${config.logo}"; 65 ''} 66 67 ${optionalString (config.articleUrlPrefix != "") '' 68 $wgArticlePath = "${config.articleUrlPrefix}/$1"; 69 ''} 70 71 ${optionalString config.enableUploads '' 72 $wgEnableUploads = true; 73 $wgUploadDirectory = "${config.uploadDir}"; 74 ''} 75 76 ${optionalString (config.defaultSkin != "") '' 77 $wgDefaultSkin = "${config.defaultSkin}"; 78 ''} 79 80 ${config.extraConfig} 81 ?> 82 ''; 83 84 # Unpack Mediawiki and put the config file in its root directory. 85 mediawikiRoot = pkgs.stdenv.mkDerivation rec { 86 name= "mediawiki-1.23.13"; 87 88 src = pkgs.fetchurl { 89 url = "http://download.wikimedia.org/mediawiki/1.23/${name}.tar.gz"; 90 sha256 = "168wpf53n4ksj2g5q5r0hxapx6238dvsfng5ff9ixk6axsn0j5d0"; 91 }; 92 93 skins = config.skins; 94 95 buildPhase = 96 '' 97 for skin in $skins; do 98 cp -prvd $skin/* skins/ 99 done 100 ''; # */ 101 102 installPhase = 103 '' 104 mkdir -p $out 105 cp -r * $out 106 cp ${mediawikiConfig} $out/LocalSettings.php 107 sed -i \ 108 -e 's|/bin/bash|${pkgs.bash}/bin/bash|g' \ 109 -e 's|/usr/bin/timeout|${pkgs.coreutils}/bin/timeout|g' \ 110 $out/includes/limit.sh \ 111 $out/includes/GlobalFunctions.php 112 ''; 113 }; 114 115 mediawikiScripts = pkgs.runCommand "mediawiki-${config.id}-scripts" 116 { buildInputs = [ pkgs.makeWrapper ]; } 117 '' 118 mkdir -p $out/bin 119 for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php update.php; do 120 makeWrapper ${php}/bin/php $out/bin/mediawiki-${config.id}-$(basename $i .php) \ 121 --add-flags ${mediawikiRoot}/maintenance/$i 122 done 123 ''; 124 125in 126 127{ 128 129 extraConfig = 130 '' 131 ${optionalString config.enableUploads '' 132 Alias ${config.urlPrefix}/images ${config.uploadDir} 133 134 <Directory ${config.uploadDir}> 135 ${allGranted} 136 Options -Indexes 137 </Directory> 138 ''} 139 140 ${if config.urlPrefix != "" then "Alias ${config.urlPrefix} ${mediawikiRoot}" else '' 141 RewriteEngine On 142 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f 143 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d 144 ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedDirs} 145 ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedFiles} 146 RewriteRule ${if config.enableUploads 147 then "!^/images" 148 else "^.*\$" 149 } %{DOCUMENT_ROOT}/${if config.articleUrlPrefix == "" 150 then "" 151 else "${config.articleUrlPrefix}/" 152 }index.php [L] 153 ''} 154 155 <Directory ${mediawikiRoot}> 156 ${allGranted} 157 DirectoryIndex index.php 158 </Directory> 159 160 ${optionalString (config.articleUrlPrefix != "") '' 161 Alias ${config.articleUrlPrefix} ${mediawikiRoot}/index.php 162 ''} 163 ''; 164 165 documentRoot = if config.urlPrefix == "" then mediawikiRoot else null; 166 167 enablePHP = true; 168 169 options = { 170 171 id = mkOption { 172 default = "main"; 173 description = '' 174 A unique identifier necessary to keep multiple MediaWiki server 175 instances on the same machine apart. This is used to 176 disambiguate the administrative scripts, which get names like 177 mediawiki-$id-change-password. 178 ''; 179 }; 180 181 dbType = mkOption { 182 default = "postgres"; 183 example = "mysql"; 184 description = "Database type."; 185 }; 186 187 dbName = mkOption { 188 default = "mediawiki"; 189 description = "Name of the database that holds the MediaWiki data."; 190 }; 191 192 dbServer = mkOption { 193 default = ""; # use a Unix domain socket 194 example = "10.0.2.2"; 195 description = '' 196 The location of the database server. Leave empty to use a 197 database server running on the same machine through a Unix 198 domain socket. 199 ''; 200 }; 201 202 dbUser = mkOption { 203 default = "mediawiki"; 204 description = "The user name for accessing the database."; 205 }; 206 207 dbPassword = mkOption { 208 default = ""; 209 example = "foobar"; 210 description = '' 211 The password of the database user. Warning: this is stored in 212 cleartext in the Nix store! 213 ''; 214 }; 215 216 emergencyContact = mkOption { 217 default = serverInfo.serverConfig.adminAddr; 218 example = "admin@example.com"; 219 description = '' 220 Emergency contact e-mail address. Defaults to the Apache 221 admin address. 222 ''; 223 }; 224 225 passwordSender = mkOption { 226 default = serverInfo.serverConfig.adminAddr; 227 example = "password@example.com"; 228 description = '' 229 E-mail address from which password confirmations originate. 230 Defaults to the Apache admin address. 231 ''; 232 }; 233 234 siteName = mkOption { 235 default = "MediaWiki"; 236 example = "Foobar Wiki"; 237 description = "Name of the wiki"; 238 }; 239 240 logo = mkOption { 241 default = ""; 242 example = "/images/logo.png"; 243 description = "The URL of the site's logo (which should be a 135x135px image)."; 244 }; 245 246 urlPrefix = mkOption { 247 default = "/w"; 248 description = '' 249 The URL prefix under which the Mediawiki service appears. 250 ''; 251 }; 252 253 articleUrlPrefix = mkOption { 254 default = "/wiki"; 255 example = ""; 256 description = '' 257 The URL prefix under which article pages appear, 258 e.g. http://server/wiki/Page. Leave empty to use the main URL 259 prefix, e.g. http://server/w/index.php?title=Page. 260 ''; 261 }; 262 263 enableUploads = mkOption { 264 default = false; 265 description = "Whether to enable file uploads."; 266 }; 267 268 uploadDir = mkOption { 269 default = throw "You must specify `uploadDir'."; 270 example = "/data/mediawiki-upload"; 271 description = "The directory that stores uploaded files."; 272 }; 273 274 defaultSkin = mkOption { 275 default = ""; 276 example = "nostalgia"; 277 description = "Set this value to change the default skin used by MediaWiki."; 278 }; 279 280 skins = mkOption { 281 default = []; 282 type = types.listOf types.path; 283 description = 284 '' 285 List of paths whose content is copied to the skins 286 subdirectory of the MediaWiki installation. 287 ''; 288 }; 289 290 extraConfig = mkOption { 291 default = ""; 292 example = 293 '' 294 $wgEnableEmail = false; 295 ''; 296 description = '' 297 Any additional text to be appended to MediaWiki's 298 configuration file. This is a PHP script. For configuration 299 settings, see <link xlink:href='http://www.mediawiki.org/wiki/Manual:Configuration_settings'/>. 300 ''; 301 }; 302 303 }; 304 305 extraPath = [ mediawikiScripts ]; 306 307 # !!! Need to specify that Apache has a dependency on PostgreSQL! 308 309 startupScript = pkgs.writeScript "mediawiki_startup.sh" 310 # Initialise the database automagically if we're using a Postgres 311 # server on localhost. 312 (optionalString (config.dbType == "postgres" && config.dbServer == "") '' 313 if ! ${pkgs.postgresql}/bin/psql -l | grep -q ' ${config.dbName} ' ; then 314 ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole "${config.dbUser}" || true 315 ${pkgs.postgresql}/bin/createdb "${config.dbName}" -O "${config.dbUser}" 316 ( echo 'CREATE LANGUAGE plpgsql;' 317 cat ${mediawikiRoot}/maintenance/postgres/tables.sql 318 echo 'CREATE TEXT SEARCH CONFIGURATION public.default ( COPY = pg_catalog.english );' 319 echo COMMIT 320 ) | ${pkgs.postgresql}/bin/psql -U "${config.dbUser}" "${config.dbName}" 321 fi 322 ${php}/bin/php ${mediawikiRoot}/maintenance/update.php 323 ''); 324 325 robotsEntries = optionalString (config.articleUrlPrefix != "") 326 '' 327 User-agent: * 328 Disallow: ${config.urlPrefix}/ 329 Disallow: ${config.articleUrlPrefix}/Special:Search 330 Disallow: ${config.articleUrlPrefix}/Special:Random 331 ''; 332 333}