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