81f4d62dba3c76fa4b9d577331ebd4355f3ee661
[mediawiki-setup] / Mediawiki_Setup_Guide
1 == Introduction ==
2
3 '''tldr''': For GNU/Linux (with a bit of Debian bias), a more concise, holistic and automated install than the official Mediawiki docs. Do some initial configuration then download this page and run it, or execute it as you read.
4
5 ''' Goals / Why use this guide? '''
6
7 * Good recommendations. Official docs mostly avoid recommendations among a myriad of possibilities
8 * Closely references & supplements official documentation
9 * Automatic security updates
10 * Explicit automation support wherever practical
11 * Used to setup this site (style is optional)
12 * Support for multiple gnu/linux distros
13 * Holistic scope (backups, server setup), but sections are independent
14 * Code blocks are [https://en.wikipedia.org/wiki/Idempotent idempotent]
15 * Edits to this page are tested on this site and reviewed by the main author.
16
17 '''Assumptions'''
18
19 * Self hosting, single GNU/Linux system with root Bash shell
20
21
22 '''Version Support'''
23
24 Very minor adjustments needed for other distros. Help expand this list.
25 * Mediawiki 1.28, updated as new versions are released
26 * Debian 8 + backports
27 * Debian 8
28 * Debian testing (last tested Aug 7, 2016)
29
30 Pre 5/2016 revisions ran Mediawiki 1.23, tested on Fedora 20 and Ubuntu 14.04.
31
32 == Prerequisites ==
33
34 '''Getting a Server & a Domain'''
35
36 The most common route and the one taken by this site is buying a domain name from a site like namecheap, and a cheap vps from companies like linode or digital ocean. They have good getting started guides which mostly apply beyond their own sites.
37
38 '''Install Certbot'''
39
40 For debian jessie with backports:
41 <source lang="bash">
42 apt-get install --install-suggests jessie-backports certbot
43 </source>
44 For other distros, follow instructions at [https://certbot.eff.org/ certbot.eff.org].
45
46 '''Email Setup'''
47
48 Setting up email can be an involved process, and this guide assumes that a some program (usually postfix or exim) is implementing a functional sendmail interface. Mediawiki uses email with to send password reminders or notifications, and this guide includes cronjobs for updating mediawiki and doing backups which will send mail in the case of an error. Email is also the recommended way to get notifications of package updates which require manual steps such as restarting of services.
49
50 If you are not setting up your server to send mail with a program that uses the default sendmail interface, see these pages when you are configuring mediawiki: [[mediawikiwiki:Manual:$wgEnableEmail|Manual:$wgEnableEmail]], [https://www.mediawiki.org/wiki/Configuration_settings#Email_settings Manual:Email_settings], [[mediawikiwiki:Manual:$wgSMTP|Manual:$wgSMTP]]
51
52 == Setup Guide Configuration ==
53
54 # Set variables below
55 # Save the code in this section to a file (~/mw_vars is suggested)
56 # Source it at the beginning of scripts containing later commands
57 # Source it from your .bashrc file while you are setting up Mediawiki
58
59 '''Requires customization:'''
60 <source lang="bash" type="example">
61 # Replace REPLACE_ME as appropriate
62
63 export mwdescription="REPLACE_ME" # eg. Opinionated Free Software Wiki
64
65 # username/pass of the first wiki admin user
66 export wikiuser="REPLACE_ME"
67 export wikipass=REPLACE_ME
68
69 # root & user password for the mysql database
70 export dbpass=REPLACE_ME
71
72 export mwdomain=REPLACE_ME # domain name. for this site, it's ofswiki.org
73
74 # customize these questions. Try not to have the answer be a word in the question.
75 captchaArray() {
76 if ! grep -Fx '$localSettingsQuestyQuestions = array (' $mwc; then
77 tee -a $mwc <<'EOF'
78 $localSettingsQuestyQuestions = array (
79 "What is the name of the wiki software this site (and wikipedia) uses?" => "Mediawiki",
80 "REPLACE_ME with a question" => "REPLACE_ME with an answer"
81 );
82 EOF
83 fi
84 }
85
86 # The rest of this section will work fine with no changes.
87
88 # git branch for mediawiki + extensions. See intro for supported versions.
89 # branch names: https://git.wikimedia.org/branches/mediawiki%2Fcore.git
90 export mw_branch=REL1_28
91
92 # As set by gui installer when choosing cc by sa.
93 export mw_RightsUrl='https://creativecommons.org/licenses/by-sa/4.0/'
94 export mw_RightsText='Creative Commons Attribution-ShareAlike'
95 export mw_RightsIcon='$wgScriptPath/resources/assets/licenses/cc-by-sa.png'
96
97 # Alphanumeric site name for pywikibot.
98 # Here we use the domain minus the dots, which should work fine without changing.
99 export mwfamily=${mwdomain//./}
100 # install path for mediawiki. This should work fine.
101 export mw=/var/www/$mwdomain/html/w
102
103
104 # wiki sender address / wiki & wiki server contact email.
105 # see email section for more info on email
106 export mw_email="admin@$mwdomain"
107
108 # Leave as is:
109 mwc="$mw/LocalSettings.php"
110 </source>
111
112 == Download this page and run it ==
113
114 This is an option to do automated setup. Optional code blocks are skipped (they have a bold warning just before them and a tag on the source block). The only important things left after running this are running the automated backup setup code on another machine.
115
116 ''' Requires manual step: inspect output file: /tmp/mw-setup, then run it'''
117 <source lang="bash" type="example">
118 start=' *<source lang="bash"> *'
119 end=' *<\/source> *'
120 ruby <<'EOF' | sed -rn "/^$start$/,/^$end$/{s/^$start|$end$/# \0/;p} > /tmp/mw-setup"
121 require 'json'
122 puts JSON.parse(`curl 'https://ofswiki.org/w/api.php?\
123 action=query&titles=Mediawiki_Setup_Guide&prop=revisions&rvprop=content&\
124 format=json'`.chomp)['query']['pages'].values[0]['revisions'][0]['*']
125 EOF
126 chmod +x /tmp/mw-setup
127 </source>
128
129 == Required Bash Functions ==
130
131 Here we define some small useful bash functions. This should be part of the same ~/mw_vars file if you are running the code step by step.
132
133 <source lang="bash">
134 # identify if this is a debian based distro
135 isdeb() { command -v apt &>/dev/null; }
136 # tee unique. append each stdin line if it does not exist in the file
137 teeu () {
138 local MAPFILE
139 mapfile -t
140 for line in "${MAPFILE[@]}"; do
141 grep -xFq "$line" "$1" &>/dev/null || tee -a "$1" <<<"$line"
142 done
143 }
144
145 # get and reset an extension/skin repository, and enable it
146 mw-clone() {
147 local url=$1
148 local original_pwd="$PWD"
149 local name
150 local re='[^/]*/[^/]*$' # last 2 parts of path
151 [[ $url =~ $re ]] ||:
152 target=$mw/${BASH_REMATCH[0]}
153 if [[ ! -e $target/.git ]]; then
154 git clone $url $target
155 fi
156 if ! cd $target; then
157 echo "mw-ext error: failed cd $target";
158 exit 1
159 fi
160 git fetch
161 git checkout -qf origin/$mw_branch || git checkout -qf origin/master
162 git clean -xffd
163 cd "$original_pwd"
164
165 }
166 mw-ext () {
167 local ext
168 for ext; do
169 mw-clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/$ext
170 if [[ -e $mw/extensions/$ext/extension.json ]]; then
171 # new style extension
172 teeu $mwc <<EOF
173 wfLoadExtension( '$ext' );
174 EOF
175 else
176 teeu $mwc <<EOF
177 require_once( "\$IP/extensions/$ext/$ext.php" );
178 EOF
179 fi
180 done
181 # --quick is quicker than default flags,
182 # but still add a sleep to make sure everything works right
183 sudo -u $apache_user php $mw/maintenance/update.php -q --quick; sleep 1
184 }
185 mw-skin() {
186 local skin=$1
187 mw-clone https://gerrit.wikimedia.org/r/p/mediawiki/skins/$skin
188 sed -i --follow-symlinks '/^wfLoadSkin/d' $mwc
189 sed -i --follow-symlinks '/^\$wgDefaultSkin/d' $mwc
190 teeu $mwc <<EOF
191 \$wgDefaultSkin = "${skin,,*}";
192 wfLoadSkin( '$skin' );
193 EOF
194 sudo -u $apache_user php $mw/maintenance/update.php -q --quick; sleep 1
195 }
196
197 if command -v apt &>/dev/null; then
198 apache_user=www-data
199 else
200 apache_user=apache
201 fi
202
203 </source>
204
205 == Install Mediawiki Dependencies ==
206
207 The best way to get core dependencies is to install the mediawiki package itself. Nothing about it will get in the way of using a version from upstream.
208
209 [[mediawikiwiki:Main Page|Mediawiki Main Page]]: the beginning of the official docs.
210
211 [[mediawikiwiki:Manual:Installation_requirements|Manual:Installation_requirements]]: Overview of installation requirements.
212
213 Note, this guide needs a little adjustment before it will work with php7.0: make sure settings are still valid, update ini path.
214
215
216
217 <source lang="bash">
218 # From here on out, exit if a command fails.
219 # This will prevent us from not noticing an important failure.
220 # We recommend setting this for the entire installation session.
221 # If you are running commands interactively, it might be best to
222 # put it in your ~/.bashrc temporarily.
223 set -eE -o pipefail
224 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
225 source ~/mw_vars
226
227 if isdeb; then
228 # main reference:
229 # https://www.mediawiki.org/wiki/Manual:Running_MediaWiki_on_Ubuntu
230 apt-get update
231 DEBIAN_FRONTEND=noninteractive apt-get install -y imagemagick curl
232 if apt-get install -s mediawiki &>/dev/null; then
233 # mediawiki is packaged in jessie backports.
234 DEBIAN_FRONTEND=noninteractive apt-get -y install php5-apcu mediawiki
235 else
236 # https://www.mediawiki.org/wiki/Manual:Installation_requirements
237 if apt-get install -s php7.0 &>/dev/null; then
238 # note, 7.0 is untested by the editor here, since it's not
239 # available in debian 8. it's listed as supported
240 # in the mediawiki page.
241 # noninteractive to avoid mysql password prompt.
242 DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 \
243 default-mysql-server \
244 php7.0 php7.0-mysql libapache2-mod-php7.0 php7.0-xml \
245 php7.0-apcu php7.0-mbstring
246 else
247 # note: mbstring is recommended, but it's not available for php5 in
248 # debian jessie.
249 DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 \
250 default-mysql-server \
251 php5 php5-mysql libapache2-mod-php5 php5-apcu
252 fi
253 fi
254 service apache2 restart
255 else
256 # note
257 # fedora deps are missing a database, so some is translated from debian packages
258 yum -y install mediawiki ImageMagick php-mysqlnd php-pecl-apcu mariadb-server
259
260 systemctl restart mariadb.service
261 systemctl enable mariadb.service
262 systemctl enable httpd.service
263 systemctl restart httpd.service
264 fi
265
266
267 # skip if we already set the root pass and are on pre-debian 9.
268 if ! echo exit|mysql -uroot "-p$dbpass"; then
269 # Note: we set a root password here, but in debian 9+, it is ignored;
270 # only the local user root can login, and any password is accepted.
271 # We answer these interactive prompts:
272 # Enter current password for root (enter for none):
273 # Set root password? [Y/n]
274 # New password:
275 # Re-enter new password:
276 # Remove anonymous users? [Y/n]
277 # Disallow root login remotely? [Y/n]
278 # Remove test database and access to it? [Y/n]
279 # Reload privilege tables now? [Y/n]
280 # Note, I had 1 less newline at the start when doing ubuntu 14.04,
281 # compared to debian 8, so can't say this is especially portable.
282 echo -e "\n\n$dbpass\n$dbpass\n\n\n\n\n" | mysql_secure_installation
283 fi
284 mysql -uroot "-p$dbpass" <<EOF
285 GRANT ALL PRIVILEGES ON my_wiki.* TO 'wikiuser'@'localhost' IDENTIFIED BY '$dbpass';
286 EOF
287 </source>
288
289
290 '''Skippable notes'''
291
292
293 php[5]-mysqlnd is a faster mysql driver package, but the default in debian php-mysql, appparently because some non-mediawiki packages are not compatible with it. If you run into this issue, simply use the php-mysql package.
294
295
296 Additional packages rational
297 * ImageMagick is [https://www.mediawiki.org/wiki/Manual:Image_administration#Image_thumbnailing recommended].
298 * Gui install and [[mediawikiwiki:Manual:Cache]] recomend the apc package.
299 * Clamav for virus scanning of uploads is mentioned in the mediawiki manual. However, wikipedia doesn't seem to do it, so it doesn't seem like it's worth bothering. It also makes uploading a set of images take twice as long on broadband.
300
301 == Install Mediawiki ==
302
303
304 Here, we [[mediawikiwiki:Download_from_Git]], or reset our installation if it is already there, and create the wiki database. [[mediawikiwiki:Manual:Installing_MediaWiki]]
305
306 <source lang="bash">
307 mkdir -p $mw
308 cd $mw
309 # this will just fail if it already exists which is fine
310 if [[ ! -e .git ]]; then
311 git clone https://gerrit.wikimedia.org/r/p/mediawiki/core.git .
312 fi
313 # to see available branches: https://www.mediawiki.org/wiki/Version_lifecycle
314 # and
315 # git branch -r
316 git checkout -f origin/$mw_branch
317 git clean -ffxd
318 # apply librejs patch
319 curl "https://iankelling.org/git/?p=mediawiki-librejs-patch;a=blob_plain;f=mediawiki-1.28-librejs.patch;hb=HEAD" | patch -r - -N -p1
320 # Get the php libraries wmf uses. Based on:
321 # https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries
322 if [[ ! -e vendor/.git ]]; then
323 git clone https://gerrit.wikimedia.org/r/p/mediawiki/vendor.git
324 fi
325 cd vendor
326 git checkout -f origin/$mw_branch
327 cd ..
328
329 # Drop any previous database which may have been installed while testing.
330 # If upgrading, we should have a db backup which will get restored.
331 # https://www.mediawiki.org/wiki/Manual:Upgrading
332 mysql -uroot "-p$dbpass" <<'EOF' ||:
333 drop database my_wiki;
334 exit
335 EOF
336 php $mw/maintenance/install.php --pass $wikipass --scriptpath /w \
337 --dbuser wikiuser --dbpass $dbpass "$mwdescription" "$wikiuser"
338 teeu $mwc <<'EOF'
339 # lock down the wiki to only the initial owner until anti-spam measures are put in place
340 # limit edits to registered users
341 $wgGroupPermissions['*']['edit'] = false;
342 # don't allow any account creation
343 $wgGroupPermissions['*']['createaccount'] = false;
344 EOF
345 </source>
346
347
348 Note: When testing, you may need to clear the apc cache to see changes take effect in the browser. Simplest solution is
349 just restart apache. http://stackoverflow.com/questions/911158/how-to-clear-apc-cache-entries
350
351 ''' Skippable Notes'''
352
353 If we wanted to reset our installation, but leave the extension repositories alone, alter the command above to be <code>git clean -fxd</code>
354
355 '''Rational for choosing git sources'''
356
357 Upstream vs distro packages. Upstream is responsive, and it's distributed within a single directory, so packaging does not integrate with the distro's filesystem. The only potential value would be less bugs by using stable versions, but we choose not to make that tradeoff.
358
359 Why use git over zip file releases? Mediawiki supports git usage through release branches which get post-release fixes. This means we can auto-update, get more granular fixes, easier to manage updates, and rollbacks.
360
361 == Configure Apache ==
362
363 Note, non-debian based installs: modify instructions below to use /etc/httpd/conf.d/$mwdomain.conf, and don't run a2ensite.
364
365 I use scripts I maintains separately to setup Let's Encrypt certificates and apache config: (url pending).
366
367 If you are doing a test setup on your local machine, you can make your domain resolve to your local test installation, then remove it later when you are done. Note, you will need non-local site to get Let's Encrypt certificates, and then transfer them locally, or disable ssl from the apache config (neither is covered here) and replace all instances of https in these instructions with http. Another option is to get a cheap 2 dollar domain for your test site.
368
369 '''Not for production:'''
370 <source lang="bash" type="example">
371 teeu /etc/hosts<<<"127.0.0.1 $mwdomain"
372 </source>
373
374 To not use my scripts, and still use Let's Encrypt: follow this doc page: https://letsencrypt.org/getting-started/. It's a little long winded, so I would boil it down to this:
375
376 '''Optional & requires additional steps:'''
377 <source lang="bash" type="example">
378 git clone https://github.com/certbot/certbot
379 cd certbot
380 ./certbot-auto apache
381 cd /etc/apache/sites-available
382 mv 000-default-le-ssl.conf $mwdomain.conf
383 rm ../sites-enabled/000-default-le-ssl.conf
384 # edit $mwdomain.conf, so documentroot is /var/www/$mwdomain/html
385 # and ServerName is $mwdomain
386 a2ensite $mwdomain.conf
387 </source>
388 Then, copy the input to apache-site below and insert it into the apache config.
389
390 Here, we use some scripts automate setting up the Let 's Encrypt cert and
391 the apache config.
392
393 <source lang="bash">
394 l=$mw/../../logs
395 mkdir -p $l
396 temp=$(mktemp -d)
397 cd $temp
398 git clone https://iankelling.org/git/basic-https-conf
399 { cat <<EOF
400 ServerAdmin $mw_email
401 RewriteEngine On
402 # make the site's root url go to our main page
403 RewriteRule ^/?wiki(/.*)?\$ %{DOCUMENT_ROOT}/w/index.php [L]
404 # use short urls https://www.mediawiki.org/wiki/Manual:Short_URL
405 RewriteRule ^/*\$ %{DOCUMENT_ROOT}/w/index.php [L]
406 EOF
407 find -L $(readlink -f $mw) -name .htaccess \
408 | while read line; do
409 echo -e "<Directory ${line%/.htaccess}>\n $(< $line)\n</Directory>";
410 done
411 } | basic-https-conf/web-conf -r ${mw%/*} - apache2 $mwdomain
412 cd
413 rm -rf $temp
414 </source>
415
416 Now mediawiki should load in your browser at $mwdomain .
417
418 Allow proper search bots and internet archiver bots, via [[Mediawiki:Robots.txt]],
419 and install the default skin.
420
421 <source lang="bash">
422 dd of=$mw/../robots.txt <<'EOF'
423 User-agent: *
424 Disallow: /w/
425 User-agent: ia_archiver
426 Allow: /*&action=raw
427 EOF
428 mw-skin Vector
429 </source>
430
431 '''Skippable Notes'''
432
433 This section assumes we are redirecting www to a url without www.
434
435 [http://httpd.apache.org/docs/current/howto/htaccess.html Apache recommends] moving .htaccess rules into it's config for performance. So we look for .htaccess files from mediawiki and copy their contents into this config. In modern apache versions, we would have to explicitly set options like AllowOverride to allow .htaccess files to take effect.
436
437 == Mediawiki Settings ==
438
439 Overall reference: [[mediawikiwiki:Manual:Configuration_settings]].
440
441 Settings which the gui setup prompts for but aren't set by the automated install script.
442 <source lang="bash">
443 teeu $mwc<<EOF
444 \$wgServer = "https://$mwdomain";
445 \$wgDBserver = "localhost";
446 \$wgRightsUrl = "$mw_RightsUrl";
447 \$wgRightsText = "$mw_RightsText";
448 \$wgRightsIcon = "$mw_RightsIcon";
449 EOF
450 </source>
451 Settings asked by the gui setup which are different than the install script defaults. They different because the defaults are the most compatible and unobtrusive.
452 <source lang="bash">
453 teeu $mwc<<EOF
454 \$wgPasswordSender = "$mw_email";
455 \$wgEmergencyContact = "$mw_email";
456 \$wgEnotifUserTalk = true; # UPO
457 \$wgEnotifWatchlist = true; # UPO
458 \$wgMainCacheType = CACHE_ACCEL;
459 \$wgEnableUploads = true;
460 \$wgUseInstantCommons = true;
461 \$wgPingback = true;
462 EOF
463 </source>
464
465 Other misc settings
466 <source lang="bash">
467 teeu $mwc <<'EOF'
468 # from https://www.mediawiki.org/wiki/Manual:Short_URL
469 $wgArticlePath = "/wiki/$1";
470
471 # https://www.mediawiki.org/wiki/Manual:Combating_spam
472 # check that url if our precautions don't work
473 # not using nofollow is good practice, as long as we avoid spam.
474 $wgNoFollowLinks = false;
475 # Allow user customization.
476 $wgAllowUserCss = true;
477 # use imagemagick over GD
478 $wgUseImageMagick = true;
479 # manual says this is not production ready, I think that is mostly
480 # because they are using MobileFrontend extension instead, which gives
481 # an even cleaner more minimal view, I plan to try setting it up
482 # sometime but this seems like a very nice improvement for now.
483 $wgVectorResponsive = true;
484 EOF
485
486
487 # https://www.mediawiki.org/wiki/Manual:Configuring_file_uploads
488 # Increase from default of 2M to 100M.
489 # This will at least allow high res pics etc.
490 php_ini=$(php -r 'echo(php_ini_loaded_file());')
491 sed -i --follow-symlinks 's/^\(upload_max_filesize\|post_max_size\)\b.*/\1 = 100M/' $php_ini
492 if isdeb; then
493 service apache2 restart
494 else
495 systemctl restart httpd.service
496 fi
497
498 # if you were to install as a normal user, you would need this for images
499 # sudo usermod -aG $apache_user $USER
500
501 # this doesn't propogate right away
502 chgrp -R $apache_user $mw/images
503 chmod -R g+w $mw/images
504 </source>
505
506 Style settings. Omit to use a different style.
507 <source lang="bash">
508 teeu $mwc <<'EOF'
509 $wgLogo = null;
510 #$wgFooterIcons = null;
511 EOF
512 # Make the toolbox go into the drop down.
513 cd $mw/skins/Vector
514 if ! git remote show ian-kelling &>/dev/null; then
515 git remote add ian-kelling https://iankelling.org/git/forks/Vector
516 fi
517 git fetch ian-kelling
518 git checkout ian-kelling/${mw_branch}-toolbox-in-dropdown
519 </source>
520
521 == Install and Configure Mediawiki Extensions ==
522
523 When installing extensions on a wiki with important content, backup first as a precaution.
524
525 ''' Extensions with no configuration needed '''
526
527 {| class="writable"
528 ! Name
529 ! Description
530 |-
531 | [[mediawikiwiki:Extension:Cite|Extension:Cite]]
532 | Have references in footnotes*
533 |-
534 | [[mediawikiwiki:Extension:CiteThisPage|Extension:CiteThisPage]]
535 | Ability to generate citations to pages in a variety of styles*
536 |-
537 | [[mediawikiwiki:CheckUser|Extension:CheckUser]]
538 | Get ip addresses from inside mediawiki so you can ban users''
539 |-
540 | [[mediawikiwiki:Extension:CSS|Extension:CSS]]
541 | Allows CSS stylesheets to be included in specific articles
542 |-
543 | [[mediawikiwiki:Extension:Echo|Extension:Echo]]
544 | Notification subsystem for usage by other extensions
545 |-
546 | [[mediawikiwiki:Extension:Gadgets|Extension:Gadgets]]
547 | UI extension system for users*
548 |-
549 | [[mediawikiwiki:Extension:ImageMap|Extension:ImageMap]]
550 | Links for a region of an image*
551 |-
552 | [[mediawikiwiki:Extension:Interwiki|Extension:Interwiki]]
553 | Tool for nice links to other wikis*
554 |-
555 | [[mediawikiwiki:Extension:News|Extension:News]]
556 | Embed or rss recent changes
557 |-
558 | [[mediawikiwiki:Extension:Nuke|Extension:Nuke]]
559 | Mass delete of pages, in the case of spam*
560 |-
561 | [[mediawikiwiki:Extension:ParserFunctions|Extension:ParserFunctions]]
562 | Useful for templates*
563 |-
564 | [[mediawikiwiki:Extension:Poem|Extension:Poem]]
565 | Useful for formatting things various ways*
566 |-
567 | [[mediawikiwiki:Extension:Renameuser|Extension:Renameuser]]
568 | Allows bureaucrats to rename user accounts*
569 |-
570 | [[mediawikiwiki:Extension:SyntaxHighlight_GeSHi|Extension:SyntaxHighlight_GeSHi]]
571 | Source code highlighting*
572 |-
573 | [[mediawikiwiki:Extension:Variables|Extension:Variables]]
574 | Define per-page variables
575 |}
576
577 <nowiki>*</nowiki> = Comes with the MediaWiki default download.
578
579 <source lang="bash">
580 mw-ext Cite CiteThisPage CheckUser CSS Echo Gadgets ImageMap Interwiki News \
581 Nuke ParserFunctions Poem Renameuser SyntaxHighlight_GeSHi Variables
582 </source>
583
584
585 ''' [[mediawikiwiki:Extension:AntiSpoof|Extension:AntiSpoof]]: Disallow usernames with unicode trickery to look like existing names'''
586
587 <source lang="bash">
588 mw-ext AntiSpoof
589 # recommended setup script to account for existing users
590 sudo -u $apache_user php $mw/extensions/AntiSpoof/maintenance/batchAntiSpoof.php
591 </source>
592
593
594 '''[[mediawikiwiki:Extension:Wikidiff2|Extension:Wikidiff2]]: Faster and international character supported page diffs'''
595
596 I used packaged version since this is a c++ and probably not very tied to the Mediawiki version. This isn't packaged in fedora, haven't gotten around to testing and adding the code to compile it for fedora.
597 <source lang="bash">
598 if isdeb; then
599 apt-get -y install php-wikidiff2
600 teeu $mwc <<'EOF'
601 $wgExternalDiffEngine = 'wikidiff2';
602 EOF
603 dir=$(dirname $(php -r 'echo(php_ini_loaded_file());'))/../apache2/conf.d
604 ln -sf ../../mods-available/wikidiff2.ini $dir
605 service apache2 restart
606 fi
607 </source>
608
609
610 ''' [[mediawikiwiki:Extension:Math|Extension:Math]] Display equations'''
611
612 <source lang="bash">
613 mw-ext Math
614 # php5-curl according to Math readme
615 if isdeb; then
616 curl_pkg=php7.0-curl
617 if ! apt-get -s install $curl_pkg &>/dev/null; then
618 curl_pkg=php5-curl
619 fi
620 apt-get -y install latex-cjk-all texlive-latex-extra texlive-latex-base \
621 ghostscript imagemagick ocaml $curl_pkg make
622 else
623 # todo, php5-curl equivalent on fedora
624 yum -y install texlive-cjk ghostscript ImageMagick texlive ocaml
625 fi
626 service apache2 restart
627
628 cd $mw/extensions/Math/math; make # makes texvc
629 cd $mw/extensions/Math/texvccheck; make
630
631 teeu $mwc <<'EOF'
632 # Enable MathJax as rendering option
633 $wgUseMathJax = true;
634 # Enable LaTeXML as rendering option
635 $wgMathValidModes[] = 'latexml';
636 # Set LaTeXML as default rendering option, because it is nicest
637 $wgDefaultUserOptions['math'] = 'latexml';
638 EOF
639 </source>
640
641 '''Skippable notes'''
642
643 There is no current list of package depencies so I took dependencies from mediawiki-math package in Debian 7. Fedora didn't have a mediawik math package, so I just translated from debian. Ocaml is for math png rendering, as backup option to the nicer looking LatexML and MathJax. Debian has texvc package, but it didn't work right for me, plus it required additional configuration in mediawiki settings.
644
645
646 ''' [[mediawikiwiki:Extension:SpamBlacklist|Extension:SpamBlacklist]]: Import/create IP blacklists, mainly for spam'''
647
648 Comes with MediaWiki.
649
650 <source lang="bash">
651 mw-ext SpamBlacklist
652 if ! grep -F '$wgSpamBlacklistFiles = array(' $mwc &>/dev/null; then
653 tee -a $mwc <<'EOF'
654 $wgEnableDnsBlacklist = true;
655 $wgDnsBlacklistUrls = array( 'xbl.spamhaus.org', 'dnsbl.tornevall.org' );
656
657 ini_set( 'pcre.backtrack_limit', '10M' );
658 $wgSpamBlacklistFiles = array(
659 "[[m:Spam blacklist]]",
660 "http://en.wikipedia.org/wiki/MediaWiki:Spam-blacklist"
661 );
662 EOF
663 fi
664 </source>
665
666 ''' [[mediawikiwiki:Extension:TitleBlacklist|Extension:TitleBlacklist]]: Anti-spam '''
667
668 Comes with Mediawiki.
669
670 <source lang="bash">
671 mw-ext TitleBlacklist
672 if ! grep -F '$wgTitleBlacklistSources = array(' $mwc &>/dev/null; then
673 tee -a $mwc <<'EOF'
674 $wgTitleBlacklistSources = array(
675 array(
676 'type' => 'local',
677 'src' => 'MediaWiki:Titleblacklist',
678 ),
679 array(
680 'type' => 'url',
681 'src' => 'http://meta.wikimedia.org/w/index.php?title=Title_blacklist&action=raw',
682 ),
683 );
684 EOF
685 fi
686 </source>
687
688 ''' [[mediawikiwiki:Extension:WikiEditor|Extension:WikiEditor]]: Editing box extras and a fast preview tab '''
689
690 Comes with MediaWiki.
691
692 <source lang="bash">
693 mw-ext WikiEditor
694 teeu $mwc <<'EOF'
695 # Enable Wikieditor by default
696 $wgDefaultUserOptions['usebetatoolbar'] = 1;
697 $wgDefaultUserOptions['usebetatoolbar-cgd'] = 1;
698
699 # Display the Preview and Changes tabs
700 $wgDefaultUserOptions['wikieditor-preview'] = 1;
701 EOF
702 </source>
703
704 ''' [[mediawikiwiki:CategoryTree|Extension:CategoryTree]]: Enables making nice outlines of pages in a category'''
705 <source lang="bash">
706 mw-ext CategoryTree
707 teeu $mwc <<'EOF'
708 # Mediawiki setting dependency for CategoryTree
709 $wgUseAjax = true;
710 EOF
711 </source>
712
713 ''' [[mediawikiwiki:Extension:AbuseFilter|Extension:AbuseFilter]]: Complex abilities to stop abuse '''
714
715 Used by big wiki sites. As a smaller site, we won't use it much, but it's good to have. It's page suggests a few defaults:
716 <source lang="bash">
717 mw-ext AbuseFilter
718 teeu $mwc<<'EOF'
719 $wgGroupPermissions['sysop']['abusefilter-modify'] = true;
720 $wgGroupPermissions['*']['abusefilter-log-detail'] = true;
721 $wgGroupPermissions['*']['abusefilter-view'] = true;
722 $wgGroupPermissions['*']['abusefilter-log'] = true;
723 $wgGroupPermissions['sysop']['abusefilter-private'] = true;
724 $wgGroupPermissions['sysop']['abusefilter-modify-restricted'] = true;
725 $wgGroupPermissions['sysop']['abusefilter-revert'] = true;
726 EOF
727 </source>
728
729 '''[[mediawikiwiki:Extension:ConfirmEdit|Extension:ConfirmEdit]]: Custom Captcha.'''
730
731 Uses captchaArray defined in mw_vars. Comes with MediaWiki.
732
733 <source lang="bash">
734 mw-ext ConfirmEdit
735 captchaArray
736 teeu $mwc <<'EOF'
737 wfLoadExtension( 'ConfirmEdit/QuestyCaptcha' );
738 $wgCaptchaClass = 'QuestyCaptcha';
739 # only captcha on registration
740 $wgGroupPermissions['user' ]['skipcaptcha'] = true;
741 $wgGroupPermissions['autoconfirmed']['skipcaptcha'] = true;
742 EOF
743 if ! grep -Fx 'foreach ( $localSettingsQuestyQuestions as $key => $value ) {' $mwc; then
744 tee -a $mwc <<'EOF'
745 foreach ( $localSettingsQuestyQuestions as $key => $value ) {
746 $wgCaptchaQuestions[] = array( 'question' => $key, 'answer' => $value );
747 }
748 EOF
749 fi
750 </source>
751
752 Enable account creation that we initially disabled.
753 <source lang="bash">
754 sed -i --follow-symlinks "/\\\$wgGroupPermissions\\['\\*'\\]\\['createaccount'\\] = false;/d" $mwc
755 </source>
756
757 == Additional Configuration with Pywikibot ==
758
759 There are quite a few [[mediawikiwiki:Help:Namespaces|special pages]] which act like variables to configure special wiki content and style. A big part of this wiki's style is configured in this section. We use Pywikibot to automate editing those pages.
760
761
762 '''Pywikibot Install'''
763
764 [[mediawikiwiki:Manual:Pywikibot/Installation|Manual:Pywikibot/Installation]]
765
766 <source lang="bash">
767 # get repo
768 if [[ ! -e ~/pywikibot/.git ]]; then
769 git clone --recursive \
770 https://gerrit.wikimedia.org/r/pywikibot/core.git ~/pywikibot
771 fi
772 cd ~/pywikibot
773 #updating
774 git pull --all
775 git submodule update
776 </source>
777
778
779 '''Pywikibot Configuration'''
780
781 Relevent docs: [[mediawikiwiki:Manual:Pywikibot/Use_on_non-WMF_wikis|Manual:Pywikibot/Use_on_non-WMF_wikis]], [[mediawikiwiki:Manual:Pywikibot/Quick_Start_Guide|Manual:Pywikibot/Quick_Start_Guide]]
782
783
784 <source lang="bash">
785 cd $HOME/pywikibot
786 dd of=user-config.py <<EOF
787 mylang = 'en'
788 usernames["$mwfamily"]['en'] = u'$wikiuser'
789 family = "$mwfamily"
790 console_encoding = 'utf-8'
791 password_file = "secretsfile"
792 EOF
793
794 dd of=secretsfile <<EOF
795 ("$wikiuser", "$wikipass")
796 EOF
797
798 # it won't overrwrite an existing file. Remove if if one exists
799 rm -f pywikibot/families/${mwfamily}_family.py
800 if isdeb; then
801 apt-get install -y python-requests
802 else
803 yum -y install python-requests
804 fi
805
806 python generate_family_file.py https://$mwdomain/wiki/Main_Page "$mwfamily"
807
808 # Note, this needed only for ssl site
809 tee -a pywikibot/families/${mwfamily}_family.py<<'EOF'
810 def protocol(self, code):
811 return 'https'
812 EOF
813 </source>
814
815
816 '''Pywikibot Script'''
817
818 This will take a full minute or so because the bot waits a few seconds between edits. Useful doc: [[mediawikiwiki:Pywikipediabot/Create_your_own_script]].
819
820 <source lang="bash">
821 cd "$HOME/pywikibot"
822
823 dd of=scripts/${mwfamily}_setup.py<<EOF
824 import pywikibot
825 import time
826 import sys
827 site = pywikibot.Site()
828 def x(p, t=""):
829 page = pywikibot.Page(site, p)
830 page.text = t
831 #force is for some anti-bot thing, not necessary in my testing, but might as well include it
832 page.save(force=True)
833
834 # Small/medium noncommercial wiki should be fine with no privacy policy
835 # based on https://www.mediawiki.org/wiki/Manual:Footer
836 x("MediaWiki:Privacy")
837
838 # licenses for uploads. Modified from the mediawiki's wiki
839 x("MediaWiki:Licenses", u"""* Same as this wiki's text (preferred)
840 ** CC BY-SA or GFDL| Creative Commons Attribution ShareAlike or GNU Free Documentation License
841 * Others:
842 ** Unknown_copyright|I don't know exactly
843 ** PD|PD: public domain
844 ** CC BY|Creative Commons Attribution
845 ** CC BY-SA|Creative Commons Attribution ShareAlike
846 ** GFDL|GFDL: GNU Free Documentation License
847 ** GPL|GPL: GNU General Public License
848 ** LGPL|LGPL: GNU Lesser General Public License""")
849 x("MediaWiki:Copyright", '$mw_license')
850 x("MediaWiki:Mainpage-description", "$mwdescription")
851
852
853
854 # The rest of the settings are for the site style
855
856 # Remove various clutter
857 x("MediaWiki:Lastmodifiedat")
858 x("MediaWiki:Disclaimers")
859 x("MediaWiki:Viewcount")
860 x("MediaWiki:Aboutsite")
861 # remove these lines from sidebar
862 # ** recentchanges-url|recentchanges
863 # ** randompage-url|randompage
864 # ** helppage|help
865 x("MediaWiki:Sidebar", """* navigation
866 ** mainpage|mainpage-description
867 * SEARCH
868 * TOOLBOX
869 * LANGUAGES""")
870
871 # remove side panel
872 # helpfull doc: https://www.mediawiki.org/wiki/Manual:Interface/Sidebar
873 x("mediawiki:Common.css", """/* adjust sidebar to just be home link and up top */
874 /* adjust sidebar to just be home link and up top */
875 /* panel width increased to fit full wiki name. */
876 /* selectors other than final id are for increasing priority of rule */
877 div#mw-panel { top: 10px; padding-top: 0em; width: 20em }
878 div#footer, #mw-head-base, div#content { margin-left: 1em; }
879 #left-navigation { margin-left: 1em; }
880
881
882 /* logo, and toolbar hidden */
883 #p-logo, div#mw-navigation div#mw-panel #p-tb {
884 display:none;
885 }
886
887 div#mw-content-text {
888 max-width: 720px;
889 }
890 """)
891 EOF
892
893 # this can spam a warning, so uniq it
894 python pwb.py ${mwfamily}_setup |& uniq
895 </source>
896
897
898 ''' Skippable Notes '''
899
900 The docs suggest manually entering the pass with python pwb.py login.py, then it should stay logged in. That didn't work for me, and anyways, we automation, so we use secrets file method.
901
902 Family name, and all its duplicattions documented as supposed to be $wgSitename, but it works fine using any name.
903
904 == Automatic Backups ==
905
906 Here we will have a daily cronjob where a backup host sshs to the mediawiki host, makes a backup then copies it back. Copy ~/mw_vars to the backup host at /root/mw_vars. Setup passwordless ssh from the backup host to the mediawiki host. Then run this code on the backup host. This will make a versioned backup of the wiki to ~/backup.
907
908 <source lang="bash" type="backup">
909 backup_script=/etc/cron.daily/mediawiki_backup
910 sudo dd of=$backup_script <<'EOFOUTER'
911 #!/bin/bash
912 # if we get an error, keep going but return it at the end
913 last_error=0
914 trap 'last_error=$?' ERR
915 source ~/mw_vars
916 # No strict because the host is likely not named the same as
917 # the domain.
918 ssh="ssh -oStrictHostKeyChecking=no"
919 logfile=/var/log/${mwdomain}_backup.log
920 {
921 echo "#### starting backup at $(date) ####"
922 $ssh root@$mwdomain <<ENDSSH
923 set -x
924 tee -a $mwc<<'EOF'
925 \$wgReadOnly = 'Dumping Database, Access will be restored shortly';
926 EOF
927 mkdir -p ~/wiki_backups
928 mysqldump -p$dbpass --default-character-set=binary my_wiki > ~/wiki_backups/wiki_db_backup
929 sed -i '\$ d' $mwc # delete read only setting
930 ENDSSH
931 # add no strict option to the defaults
932
933 rdiff() { rdiff-backup --remote-schema "$ssh -C %s rdiff-backup --server" "$@"; }
934 set -x
935 rdiff root@$mwdomain::/root/wiki_backups ~/backup/${mwdomain}_wiki_db_backup
936 rdiff root@$mwdomain::$mw ~/backup/${mwdomain}_wiki_file_backup
937 set +x
938 echo "=== ending backup at $(date) ===="
939 } &>>$logfile
940 if [[ $last_error != 0 ]]; then
941 echo "backup for $mwdomain failed. See $logfile"
942 fi
943 exit $last_error
944 EOFOUTER
945
946 sudo chmod +x $backup_script
947 </source>
948
949 '''Optional & requires additional steps'''
950
951 If you are like most people and don't use the old-school mail spool, setup the backup system to send mail externally so you are notified if it fails. For examples of how to do this, [http://unix.stackexchange.com/questions/36982/can-i-set-up-system-mail-to-use-an-external-smtp-server stackoverflow], [https://iankelling.org/git/?p=ian-specific/distro-setup;a=blob;f=mail-setup;hb=HEAD script I use].
952
953 == Restoring Backups ==
954
955 '''Whenever you implement a backup system, you should test that restoring the backup works.'''
956
957 You ''should'' be able to restore your wiki to a new machine by repeating all install steps, then restoring the database and the images directory. I've done this many times. However, we backup the entire Mediawiki directory in case you forget to record a step or some corner case happens. Since most people don't record the steps they took to setup Mediawiki, this is also the officially recommended method. In the code below we restore only the database and images folder from the full backup. You can try this after setting up a wiki from scratch. If it doesn't work, you know your fresh setup is not replicating your backed up wiki correctly. In that case, you can fall back to doing a full restore by copying the full directory instead of just the images. See [[mediawikiwiki:Manual:Restoring a wiki from backup]] if you run into any problems.
958
959 To test a backup restore:
960 # Do a backup of your wiki with some content in it, as described in the previous section
961 # Move your mediawiki install directory, or setup Mediawiki on a new machine
962 # Re-execute the mediawiki install steps
963 # Change REPLACE_ME in the code below (as in the backup section so you get the right variables),
964 # Execute the code on the backup machine.
965
966 '''Optional'''
967 <source lang="bash" type="example">
968 #!/bin/bash
969 source ~/mw_vars
970 restore="rdiff-backup --force -r now"
971 $restore ~/backup/${mwdomain}_wiki_file_backup /tmp/wiki_file_restore
972 $restore ~/backup/${mwdomain}_wiki_db_backup /tmp/wiki_db_restore
973 o=-oStrictHostKeyChecking=no
974 scp $o -r /tmp/wiki_file_restore/images/* root@$mwdomain:$mw/images
975 scp $o -r /tmp/wiki_db_restore root@$mwdomain:/tmp
976 ssh $o root@$mwdomain <<EOF
977 set -e
978 chmod -R g+w $mw/images
979 chgrp -R www-data $mw/images
980 mysql -uroot "-p$dbpass" my_wiki < /tmp/wiki_db_restore/wiki_db_backup
981 php $mw/maintenance/update.php
982 EOF
983 </source>
984
985 Then browse to your wiki and see if everything appears to work.
986
987 == Updates ==
988
989 Subscribe to get release and security announcements [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki-announce].
990
991 For updates, we simply git pull all the repos, then run the maintenance script. This should be done after a backup. We recommend automatic updates to get security fixes and since not much is changing on the release branch. In this example, we update at 5 am daily (1 hour after the automatic backup example).
992
993 Major version upgrades should be done manually, and it is recommended to use a new installation directory and the same procedure as for backup & restore. Official reference: [[mediawikiwiki:Manual:Upgrading|Manual:Upgrading]]
994
995 Minor updates script:
996 <source lang="bash">
997 s=/etc/cron.daily/mediawiki_update
998 dd of=$s<<'EOF'
999 #!/bin/bash
1000 source ~/mw_vars
1001 update() {
1002 dir=$1
1003 cd $mw
1004 [[ -d $dir ]] || return 1
1005 cd $dir
1006 branch=$(git describe --all)
1007 branch=${branch#remotes/}
1008 git fetch --all -q
1009 new_head=$(git rev-parse $branch)
1010 log=$(git log HEAD..$new_head)
1011 if [[ ! $log ]]; then
1012 return 1
1013 fi
1014 pwd
1015 echo "$log"
1016 git checkout -qf $new_head
1017 cd $mw
1018 return 0
1019 }
1020 for dir in extensions/* skins/* vendor; do
1021 update "$dir" ||:
1022 done
1023 if update .; then
1024 curl "https://iankelling.org/git/?p=mediawiki-librejs-patch;a=blob_plain;f=mediawiki-1.28-librejs.patch;hb=HEAD" | patch -r - -N -p1
1025 fi
1026 php $mw/maintenance/update.php -q --quick
1027 EOF
1028
1029 </source>
1030
1031 == Upgrading Major Versions ==
1032
1033 Reference documentation is at [[mediawikiwiki:Manual:Upgrading]]
1034
1035 My strategy is:
1036
1037 # Read the "Upgrade notices for MediaWiki administrators" on the upgrade version and any skipped versions at [[mediawikiwiki:Version_lifecycle]].
1038 # Setup a blank test wiki with the new version.
1039 # Backup the old database, restore it to the new wiki, run php maintenance/update.php.
1040 # If everything looks good, repeat and replace the old wiki with the new one.
1041
1042 == Stopping Spam ==
1043
1044 There is a balance between effective anti-spam measures and blocking/annoying contributors. Mediawiki documentation on how to combat spam, is not very good, but it has improved over time: [https://www.mediawiki.org/wiki/Manual:Combating_spam manual: Combating Spam]. It's possible for a spammer to quickly make thousands of edits, and there is no good documentation on purging lots of spam, so you should have a good strategy up front. My current strategy is 3 fold, and is limited to small/medium wiki's:
1045
1046 * Find new spam quickly, revert it & ban the user.
1047 ** Watch, and get notified of changes on all primary content pages: Special:Preferences, Bottom of the page, set an email address, then turn on "Email me also for minor edits of pages and files."
1048 ** Use a rss/atom feed reader, and subscribe to recent changes across the wiki. Newer browsers have an rss feed subscribe button, you can click after going to Special:RecentChanges. If that is not available, you can construct the proper url based on [https://meta.wikimedia.org/wiki/Help:Recent_changes#Web_feed these instructions].
1049 * Require registration to edit, and a custom captcha question on registration.
1050 * Install all non-user inhibiting anti-spam extensions / settings that take a reasonable amount of time to figure out.
1051
1052 == Choosing Extensions ==
1053
1054 Mediawiki.org has pages for ~5200 extensions. Mediawiki maintains ~700 extensions [http://git.wikimedia.org/tree/mediawiki%2Fextensions.git in it's git repo]. Wikipedia uses [https://en.wikipedia.org/wiki/Special:Version over 100 extensions]. Major distributors package [[mediawikiwiki:Comparison_of_extensions_in_distributions| ~36 extensions]]. We looked closely at the distributor's and briefly at the Mediawiki repo extensions. We haven't found any other useful list or recommendations.
1055
1056 Here are brief descriptions of extensions that are part of distributions and why they were rejected for this wiki.
1057
1058 {| class="wikitable"
1059 |+
1060 | '''Footnote''' || deprecated in newer versions
1061 |+
1062 | '''InputBox''' || Add html forms to pages. Can't imagine using it. Would install if I did.
1063 |+
1064 | '''LocalisationUpdate'''|| update localization only. I'm fine updating all of mediawiki, there aren't many updates.
1065 |+
1066 | '''NewestPages''' || A page creation history that doesn't expire like recent-changes. Meh
1067 |+
1068 | '''NewUserNotif''' || Send me a notification when a user registers. Seems like an excessive notification.
1069 |+
1070 | '''Openid''' || Poor UI. 2 pages & 2 links <login> <login with openid> which is confusing & ugly.
1071 |+
1072 | '''Pdfhandler''' || Gallery of pages from a pdf file. Can't imagine using it. Would install if I did.
1073 |+
1074 | '''RSSReader''' || Embed an rss feed. Can't imagine using it. Would install if I did.
1075 |+
1076 | '''Semantic''' || Seems like a lot of trouble around analyzing kinds of data which my wiki will not have.
1077 |+
1078 | '''Validator''' || dependency of of semantic
1079 |+
1080 |}
1081
1082 == Misc Notes ==
1083
1084 ''' Web Analytics Software '''
1085
1086 I do not recommend using google analytics: it's proprietary software and gives private information of your website visitors to google for them to make money. Piwik has the best features and I recommend it, but I use goaccess because it is simpler to manage and good enough.
1087
1088 ''' Mediawiki Documentation Quality '''
1089
1090 Overall the documentation is good, but like wikipedia, it depends.
1091
1092 The closer a topic is to core functionality and commonly used features, the better the documentation is likely to be. Wikimedia Foundation (WMF) has a competing priority of being a good upstream to mediawiki users and being good for their own sites. That, plus the multitude of unconnected extension developers, and official documentation is sometimes neglected in favor of bug reports, readme files, comments, code, and unpublished knowledge. User's documentation edits vary in quality, and often aren't reviewed by anyone. If you run into an issue, try viewing/diffing the most recent version of a page by the last few editors.
1093
1094 One issue is that mediawiki.org needs a lot of organizing, deleting, and verifying of material, and that is relatively unpopular, tedious, and sometimes difficult work. The discussion pages of mediawiki.org are a wasteland of unanswered questions and outdated conversations, which is [https://www.mediawiki.org/wiki/Help:Talk_pages poor form] for a wiki. However, if you communicate well, you can get great help from their [https://www.mediawiki.org/wiki/Communication support forum, irc, and mailing list].
1095
1096
1097 '''Bash here documents, EOF vs 'EOF' '''
1098
1099 Here documents are used throughout this page, some people may not be aware of a small but important syntax. When the delimiter is quoted, as in <<'EOF', then the contents of the here document are exactly verbatim. Otherwise $ and ` are expanded as in bash, and must be escaped by prefixing them with \, which itself must then also be escaped to be used literally.
1100
1101
1102 ''' Mediawiki automation tools survey 7/2014 '''
1103
1104 Barely maintained:
1105 * https://github.com/ianweller/mw
1106 * http://search.cpan.org/~markj/WWW-Mediawiki-Client/bin/mvs
1107 * https://github.com/alexz-enwp/wikitools 3000 lines of code, no response to a bug reports in 2/2014
1108
1109 Getting basic maintenance
1110 * https://github.com/mwclient/mwclient 2000 lines of code
1111
1112 Actively developed, used by wikimedia foundation a lot.
1113 * [[mediawikiwiki:Manual:Pywikibot]]
1114
1115
1116 ''' Troubleshooting Errors '''
1117
1118 If mediawiki fails to load, or shows an error in the browser, enable some settings and it will print much more useful information. [[mediawikiwiki:Manual:How to debug]]
1119
1120 ''' License '''
1121
1122 This page and this wiki is licensed under cc-by-sa 4.0.
1123 This means the code is compatible with gplv3.
1124
1125 == todo list for this page ==
1126
1127 * Get Visual editor extension.
1128 * Don't require registration for edits
1129 * Take a look at the new debian mediawiki package's apache conf
1130 * For perf, translate extensions allow/deny directives, and set AllowOverride None in apache.conf