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.27.3"; 87 88 src = pkgs.fetchurl { 89 url = "http://download.wikimedia.org/mediawiki/1.27/${name}.tar.gz"; 90 sha256 = "08x8mvc0y1gwq8rg0zm98wc6hc5j8imb6dcpx6s7392j5dc71m0i"; 91 }; 92 93 skins = config.skins; 94 extensions = config.extensions; 95 96 buildPhase = 97 '' 98 for skin in $skins; do 99 cp -prvd $skin/* skins/ 100 done 101 for extension in $extensions; do 102 cp -prvd $extension/* extensions/ 103 done 104 ''; # */ 105 106 installPhase = 107 '' 108 mkdir -p $out 109 cp -r * $out 110 cp ${mediawikiConfig} $out/LocalSettings.php 111 sed -i \ 112 -e 's|/bin/bash|${pkgs.bash}/bin/bash|g' \ 113 -e 's|/usr/bin/timeout|${pkgs.coreutils}/bin/timeout|g' \ 114 $out/includes/limit.sh \ 115 $out/includes/GlobalFunctions.php 116 ''; 117 }; 118 119 mediawikiScripts = pkgs.runCommand "mediawiki-${config.id}-scripts" 120 { buildInputs = [ pkgs.makeWrapper ]; } 121 '' 122 mkdir -p $out/bin 123 for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php update.php; do 124 makeWrapper ${php}/bin/php $out/bin/mediawiki-${config.id}-$(basename $i .php) \ 125 --add-flags ${mediawikiRoot}/maintenance/$i 126 done 127 ''; 128 129in 130 131{ 132 133 extraConfig = 134 '' 135 ${optionalString config.enableUploads '' 136 Alias ${config.urlPrefix}/images ${config.uploadDir} 137 138 <Directory ${config.uploadDir}> 139 ${allGranted} 140 Options -Indexes 141 </Directory> 142 ''} 143 144 ${if config.urlPrefix != "" then "Alias ${config.urlPrefix} ${mediawikiRoot}" else '' 145 RewriteEngine On 146 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f 147 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d 148 ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedDirs} 149 ${concatMapStringsSep "\n" (u: "RewriteCond %{REQUEST_URI} !^${u.urlPath}") serverInfo.vhostConfig.servedFiles} 150 RewriteRule ${if config.enableUploads 151 then "!^/images" 152 else "^.*\$" 153 } %{DOCUMENT_ROOT}/${if config.articleUrlPrefix == "" 154 then "" 155 else "${config.articleUrlPrefix}/" 156 }index.php [L] 157 ''} 158 159 <Directory ${mediawikiRoot}> 160 ${allGranted} 161 DirectoryIndex index.php 162 </Directory> 163 164 ${optionalString (config.articleUrlPrefix != "") '' 165 Alias ${config.articleUrlPrefix} ${mediawikiRoot}/index.php 166 ''} 167 ''; 168 169 documentRoot = if config.urlPrefix == "" then mediawikiRoot else null; 170 171 enablePHP = true; 172 173 options = { 174 175 id = mkOption { 176 default = "main"; 177 description = '' 178 A unique identifier necessary to keep multiple MediaWiki server 179 instances on the same machine apart. This is used to 180 disambiguate the administrative scripts, which get names like 181 mediawiki-$id-change-password. 182 ''; 183 }; 184 185 dbType = mkOption { 186 default = "postgres"; 187 example = "mysql"; 188 description = "Database type."; 189 }; 190 191 dbName = mkOption { 192 default = "mediawiki"; 193 description = "Name of the database that holds the MediaWiki data."; 194 }; 195 196 dbServer = mkOption { 197 default = ""; # use a Unix domain socket 198 example = "10.0.2.2"; 199 description = '' 200 The location of the database server. Leave empty to use a 201 database server running on the same machine through a Unix 202 domain socket. 203 ''; 204 }; 205 206 dbUser = mkOption { 207 default = "mediawiki"; 208 description = "The user name for accessing the database."; 209 }; 210 211 dbPassword = mkOption { 212 default = ""; 213 example = "foobar"; 214 description = '' 215 The password of the database user. Warning: this is stored in 216 cleartext in the Nix store! 217 ''; 218 }; 219 220 emergencyContact = mkOption { 221 default = serverInfo.serverConfig.adminAddr; 222 example = "admin@example.com"; 223 description = '' 224 Emergency contact e-mail address. Defaults to the Apache 225 admin address. 226 ''; 227 }; 228 229 passwordSender = mkOption { 230 default = serverInfo.serverConfig.adminAddr; 231 example = "password@example.com"; 232 description = '' 233 E-mail address from which password confirmations originate. 234 Defaults to the Apache admin address. 235 ''; 236 }; 237 238 siteName = mkOption { 239 default = "MediaWiki"; 240 example = "Foobar Wiki"; 241 description = "Name of the wiki"; 242 }; 243 244 logo = mkOption { 245 default = ""; 246 example = "/images/logo.png"; 247 description = "The URL of the site's logo (which should be a 135x135px image)."; 248 }; 249 250 urlPrefix = mkOption { 251 default = "/w"; 252 description = '' 253 The URL prefix under which the Mediawiki service appears. 254 ''; 255 }; 256 257 articleUrlPrefix = mkOption { 258 default = "/wiki"; 259 example = ""; 260 description = '' 261 The URL prefix under which article pages appear, 262 e.g. http://server/wiki/Page. Leave empty to use the main URL 263 prefix, e.g. http://server/w/index.php?title=Page. 264 ''; 265 }; 266 267 enableUploads = mkOption { 268 default = false; 269 description = "Whether to enable file uploads."; 270 }; 271 272 uploadDir = mkOption { 273 default = throw "You must specify `uploadDir'."; 274 example = "/data/mediawiki-upload"; 275 description = "The directory that stores uploaded files."; 276 }; 277 278 defaultSkin = mkOption { 279 default = ""; 280 example = "nostalgia"; 281 description = "Set this value to change the default skin used by MediaWiki."; 282 }; 283 284 skins = mkOption { 285 default = []; 286 type = types.listOf types.path; 287 description = 288 '' 289 List of paths whose content is copied to the skins 290 subdirectory of the MediaWiki installation. 291 ''; 292 }; 293 294 extensions = mkOption { 295 default = []; 296 type = types.listOf types.path; 297 description = 298 '' 299 List of paths whose content is copied to the 'extensions' 300 subdirectory of the MediaWiki installation. 301 ''; 302 }; 303 304 extraConfig = mkOption { 305 type = types.lines; 306 default = ""; 307 example = 308 '' 309 $wgEnableEmail = false; 310 ''; 311 description = '' 312 Any additional text to be appended to MediaWiki's 313 configuration file. This is a PHP script. For configuration 314 settings, see <link xlink:href='http://www.mediawiki.org/wiki/Manual:Configuration_settings'/>. 315 ''; 316 }; 317 318 }; 319 320 extraPath = [ mediawikiScripts ]; 321 322 # !!! Need to specify that Apache has a dependency on PostgreSQL! 323 324 startupScript = pkgs.writeScript "mediawiki_startup.sh" 325 # Initialise the database automagically if we're using a Postgres 326 # server on localhost. 327 (optionalString (config.dbType == "postgres" && config.dbServer == "") '' 328 if ! ${pkgs.postgresql}/bin/psql -l | grep -q ' ${config.dbName} ' ; then 329 ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole "${config.dbUser}" || true 330 ${pkgs.postgresql}/bin/createdb "${config.dbName}" -O "${config.dbUser}" 331 ( echo 'CREATE LANGUAGE plpgsql;' 332 cat ${mediawikiRoot}/maintenance/postgres/tables.sql 333 echo 'CREATE TEXT SEARCH CONFIGURATION public.default ( COPY = pg_catalog.english );' 334 echo COMMIT 335 ) | ${pkgs.postgresql}/bin/psql -U "${config.dbUser}" "${config.dbName}" 336 fi 337 ${php}/bin/php ${mediawikiRoot}/maintenance/update.php 338 ''); 339 340 robotsEntries = optionalString (config.articleUrlPrefix != "") 341 '' 342 User-agent: * 343 Disallow: ${config.urlPrefix}/ 344 Disallow: ${config.articleUrlPrefix}/Special:Search 345 Disallow: ${config.articleUrlPrefix}/Special:Random 346 ''; 347 348}