new snapshot, url update
[mediawiki-setup] / Mediawiki_Setup_Guide
index b410697bc76cfb83b43480228e918de4af9f7037..d17fa35edaa7b0d74bb3fcae8eae9906f3b4d6c6 100644 (file)
@@ -1,9 +1,6 @@
 == Introduction ==
 
-'''Currently undergoing revisions to upgrade from mediawiki version 1.23 to 1.27.
-Should be done on 5/30/2016'''
-
-'''tldr''': Automated setup on gnu/linux after you set options in [[#Dependent Variables and Functions]], except email. Any code which is not ready to be run has bold text saying so immediately before it.
+'''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.
 
 ''' Goals / Why use this guide? '''
 
@@ -11,27 +8,28 @@ Should be done on 5/30/2016'''
 * Closely references & supplements official documentation
 * Explicit automation support wherever practical
 * Used to setup this site (style optional)
-* Contributions welcome. This site will be updated/tested with changes to this document!
-* Support for multiple linux distros
+* Contributions welcome and will be updated/tested on this very site!
+* Support for multiple gnu/linux distros
 * Holistic scope (backups, server setup), but sections stand on their own
 * Explicit support for production & local testing instance. Additions for production like https and web analytics.
 * Edits to this page are closely monitored by the original author.
 
 '''Assumptions'''
 
-* Self hosting, single Linux system with Bash shell
+* Self hosting, single GNU/Linux system with Bash shell
 * Root shell is assumed throughout
-* Code blocks are [https://en.wikipedia.org/wiki/Idempotent idempotent] unless stated otherwise
+* Code blocks are [https://en.wikipedia.org/wiki/Idempotent idempotent]
 
 '''Version Support'''
 
 Very minor adjustments needed for other distros. Help expand this list.
-* Mediawiki 1.23
-* Fedora 20 (tested)
-* Ubuntu 14.04 (tested)
-* Debian 7
+* Mediawiki 1.27
+* Debian 8 (tested)
+* Debian testing (tested Aug 7, 2016)
+
+Pre 5/2016 revisions ran Mediawiki 1.23, tested on Fedora 20 and Ubuntu 14.04.
 
-== Production Server Prerequisites ==
+== Prerequisites ==
 
 '''Getting a Server & a Domain'''
 
@@ -39,36 +37,11 @@ The most common route and the one taken by this site is buying a domain name fro
 
 '''Email Setup'''
 
-Setting up email can be an involved process. Mediawiki is perfectly happy to disable email with 1 setting (no password reminders or notifications), but it is a nice feature to have. You could run your own mail server (on the mediawiki server, or elsewhere), or use one of many services which sends mail for very cheap, or free within limits (popular examples [http://www.mailgun.com/ mailgun], [https://mandrillapp.com/ mandrill], [http://www.mailjet.com/pricing mailjet], [https://aws.amazon.com/ses/ aws]), or connect  to a full featured send/receive mail provider like [https://fastmail.com fastmail] (this server is setup that way). How we did that is for a future wiki page.
+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.
 
 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]]
 
-== Stopping Spam ==
-
-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:
-
-* Find new spam quickly, revert it & ban the user.
-** 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."
-** 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].
-* Require registration to edit, and a custom captcha question on registration.
-* Install all non-user inhibiting anti-spam extensions / settings that take a reasonable amount of time to figure out.
-
-== Download all ready to use source code blocks into a single script ==
-
-Source block that are not ready to use have a bold warning just before them (and a tag on the block) and are skipped.
-''' Requires customization: outputs to stdout'''
-<source lang="bash" type="example">
-start=' *<source lang="bash"> *'
-end=' *<\/source> *'
-ruby <<'EOF' | sed -rn "/^$start$/,/^$end$/{s/^$start|$end$/# \0/;p}"
-require 'json'
-puts JSON.parse(`curl 'https://ofswiki.org/w/api.php?\
-action=query&titles=Mediawiki_Setup_Guide&prop=revisions&rvprop=content&\
-format=json'`.chomp)['query']['pages'].values[0]['revisions'][0]['*']
-EOF
-</source>
-
-== Dependent Variables and Functions ==
+== Setup Guide Configuration ==
 
 # Set variables below
 # Save the code in this section to a file (~/mw_vars is suggested)
@@ -77,122 +50,150 @@ EOF
 
 '''Requires customization:'''
 <source lang="bash" type="example">
-# Replease REPLACE_ME as appropriate
+# Replace REPLACE_ME as appropriate
 
-export mwdescription="Opinionated Free Software Wiki"
+export mwdescription="REPLACE_ME" # eg. Opinionated Free Software Wiki
 
 # username/pass of the first wiki admin user
-export wikiuser="Ian Kelling"
+export wikiuser="REPLACE_ME"
 export wikipass=REPLACE_ME
 
 # root password for the mysql database
 export dbpass=REPLACE_ME
 
-# password for piwik web analytics admin
-export piwik_pass=REPLACE_ME
-
-# git branch for mediawiki + extensions
-# branch names: https://git.wikimedia.org/branches/mediawiki%2Fcore.git
-export mw_branch=REL1_27
+export mwdomain=REPLACE_ME # domain name. for this site, it's ofswiki.org
 
-# customize these questions to something your contributors would know,
-# is not super common / scriptable, and doesn't have the answer in the question
+# customize these questions. Try not to have the answer be a word in the question.
 captchaArray() {
-    if ! grep -Fx '$localSettingsQuestyQuestions = array (' $mwc
-    tee -a $mwc <<'EOF'
+    if ! grep -Fx '$localSettingsQuestyQuestions = array (' $mwc; then
+       tee -a $mwc <<'EOF'
 $localSettingsQuestyQuestions = array (
     "What is the name of the wiki software this site (and wikipedia) uses?" => "Mediawiki",
-    "What does f in ofswiki.org stand for?" => "Free"
+    "REPLACE_ME with a question" => "REPLACE_ME with an answer"
 );
 EOF
+    fi
 }
 
-# As set by gui installer when choosing cc by sa.
-export mw_RightsUrl="https://creativecommons.org/licenses/by-sa/4.0/";
-export mw_RightsText="Creative Commons Attribution-ShareAlike";
-export mw_RightsIcon="$wgResourceBasePath/resources/assets/licenses/cc-by-sa.png";
+# The rest of this section will work fine with no changes.
 
+# git branch for mediawiki + extensions.
+# This guide has only been tested with 1_27.
+# branch names: https://git.wikimedia.org/branches/mediawiki%2Fcore.git
+export mw_branch=REL1_27
 
-# domain name and install paths. These are examples, change as needed.
-export mwfamily=ofswiki # short alphanumeric name for pywikibot
-export mwdomain=ofswiki.org
+# As set by gui installer when choosing cc by sa.
+export mw_RightsUrl='https://creativecommons.org/licenses/by-sa/4.0/'
+export mw_RightsText='Creative Commons Attribution-ShareAlike'
+export mw_RightsIcon='$wgScriptPath/resources/assets/licenses/cc-by-sa.png'
+
+# Alphanumeric site name for pywikibot.
+# Here we use the domain minus the dots, which should work fine without changing.
+export mwfamily=${mwdomain//./}
+# install path for mediawiki. This should work fine.
 export mw=/var/www/$mwdomain/html/w
 
 
 # wiki sender address / wiki & wiki server contact email.
 # see email section for more info on email
 export mw_email="admin@$mwdomain"
+
+# Leave as is:
+mwc="$mw/LocalSettings.php"
 </source>
 
-Here we define some small useful bash functions. This should be part of the same file.
+== Download this page and run it ==
 
-<source lang="bash">
-# for convenience, Mediawiki config file
-mwc="$mw/LocalSettings.php"
+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.
 
-if isdeb; then
-    apache_user=www-data
-else
-    apache_user=apache
-fi
+''' Requires manual step: inspect output file: /tmp/mw-setup, then run it'''
+<source lang="bash" type="example">
+start=' *<source lang="bash"> *'
+end=' *<\/source> *'
+ruby <<'EOF' | sed -rn "/^$start$/,/^$end$/{s/^$start|$end$/# \0/;p} > /tmp/mw-setup"
+require 'json'
+puts JSON.parse(`curl 'https://ofswiki.org/w/api.php?\
+action=query&titles=Mediawiki_Setup_Guide&prop=revisions&rvprop=content&\
+format=json'`.chomp)['query']['pages'].values[0]['revisions'][0]['*']
+EOF
+chmod +x /tmp/mw-setup
+</source>
+
+== Required Bash Functions ==
+
+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.
+
+<source lang="bash">
+# identify if this is a debian based distro
+isdeb() { command -v apt &>/dev/null; }
+# tee unique. append each stdin line if it does not exist in the file
+teeu () {
+    local MAPFILE
+    mapfile -t
+    for line in "${MAPFILE[@]}"; do
+        grep -xFq "$line" "$1" &>/dev/null || tee -a "$1" <<<"$line"
+    done
+}
 
 # get and reset an extension/skin repository, and enable it
-mw-ext () { mw-extra extension $@; }
-mw-skin() { mw-extra skin $@; }
-
-mw-extra() {
-    local type=${1}s # extension or skin
-    shift
-    local clone=true
-    if [[ $1 == -g ]]; then
-        clone=false
-        shift
+mw-clone() {
+    local url=$1
+    local original_pwd="$PWD"
+    local name
+    local re='[^/]*/[^/]*$'
+    [[ $url =~ $re ]] ||:
+    target=$mw/${BASH_REMATCH[0]}
+    if [[ ! -e $target/.git ]]; then
+        git clone $url $target
+    fi
+    if ! cd $target; then
+        echo "mw-ext error: failed cd $target";
+        exit 1
     fi
+    git fetch
+    git checkout -qf origin/$mw_branch || git checkout -qf origin/master
+    git clean -xffd
+    cd "$original_pwd"
+
+}
+mw-ext () {
     local ext
     for ext in "$@"; do
-        if $clone; then
-            local original_pwd="$PWD"
-            # it's ok that this fails if we already have it
-            url=https://git.wikimedia.org/git/mediawiki
-            target=$mw/$type/$ext
-            git clone $url/$type/$ext.git $target
-            if ! cd $target; then
-                echo "mw-ext error: failed cd $mw/extensions/$ext";
-                exit 1
-            fi
-            git fetch
-            git checkout -qf origin/$mw_branch || git checkout -qf origin/master
-            git clean -xffd
-            cd "$original_pwd"
-        fi
-        case $type in
-            extensions)
-                if [[ -e $target/extension.json ]]; then
-                    # new style extension. remove old style declaration
-                    sed -i '#^require_once( "\\\$IP/extensions/\$ext/\$ext\.php" );#d' $mwc
-                    teeu $mwc <<EOF
+        mw-clone https://gerrit.wikimedia.org/r/p/mediawiki/extensions/$ext
+        if [[ -e $mw/ext/$ext/extension.json ]]; then
+            # new style extension. remove old style declaration
+            sed -i --follow-symlinks '#^require_once( "\\\$IP/extensions/\$ext/\$ext\.php" );#d' $mwc
+            teeu $mwc <<EOF
 wfLoadExtension( '$ext' );
 EOF
-                else
-                    teeu $mwc <<EOF
+        else
+            teeu $mwc <<EOF
 require_once( "\$IP/extensions/$ext/$ext.php" );
 EOF
-                fi
-                ;;
-            skins)
-                sed -i '/^wfLoadSkin/d' $mwc
-                sed -i '/^\$wgDefaultSkin/d' $mwc
-                teeu $mwc <<EOF
-$wgDefaultSkin = "${ext,,*}";
-wfLoadSkin( 'Vector' );
-EOF
-                ;;
-        esac
+        fi
     done
     # --quick is quicker than default flags,
     # but still add a sleep to make sure everything works right
     sudo -u $apache_user php $mw/maintenance/update.php -q --quick; sleep 1
 }
+mw-skin() {
+    local skin=$1
+    mw-clone https://gerrit.wikimedia.org/r/p/mediawiki/skins/$skin
+    sed -i --follow-symlinks '/^wfLoadSkin/d' $mwc
+    sed -i --follow-symlinks '/^\$wgDefaultSkin/d' $mwc
+    teeu $mwc <<EOF
+\$wgDefaultSkin = "${skin,,*}";
+wfLoadSkin( '$skin' );
+EOF
+    sudo -u $apache_user php $mw/maintenance/update.php -q --quick; sleep 1
+}
+
+if command -v apt &>/dev/null; then
+    apache_user=www-data
+else
+    apache_user=apache
+fi
+
 </source>
 
 == Install Mediawiki Dependencies ==
@@ -203,15 +204,48 @@ The best way to get core dependencies is to install the mediawiki package itself
 
 [[mediawikiwiki:Manual:Installation_requirements|Manual:Installation_requirements]]: Overview of installation requirements.
 
+Note, this guide needs a little adjustment before it will work with php7.0: make sure settings are still valid, update ini path.
+
 
 
 <source lang="bash">
+# From here on out, exit if a command fails.
+# This will prevent us from not noticing an important failure.
+# We recommend setting this for the entire installation session.
+# If you are running commands interactively, it might be best to
+# put it in your ~/.bashrc temporarily.
+set -eE -o pipefail
+trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
+source ~/mw_vars
+
 if isdeb; then
+    # main reference:
+    # https://www.mediawiki.org/wiki/Manual:Running_MediaWiki_on_Ubuntu
     apt-get update
-    # noninteractive to avoid mysql password prompt
-    DEBIAN_FRONTEND=noninteractive apt-get -y install mediawiki ImageMagick php5-mysqlnd php-apc
+    apt-get install -y imagemagick
+    if apt-get install -s mediawiki &>/dev/null; then
+        # in debian wheezy time-frame distros, mediawiki was packaged.
+        apt-get -y install php-apc mediawiki php-mbstring
+    else
+        # https://www.mediawiki.org/wiki/Manual:Installation_requirements
+        if apt-get install -s php7.0 &>/dev/null; then
+            # note, 7.0 is untested by the editor here, since it's not
+            # available in debian 8. it's listed as supported
+            # in the mediawiki page.
+            # noninteractive to avoid mysql password prompt.
+            DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 mysql-server \
+                           php7.0 php7.0-mysql libapache2-mod-php7.0 php7.0-xml \
+                           php7.0-apcu php7.0-mbstring
+        else
+            # note: mbstring is recommended, but it's not available for php5 in
+            # debian jessie.
+            DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 mysql-server \
+                           php5 php5-mysql libapache2-mod-php5 php5-apcu
+        fi
+    fi
     service apache2 restart
 else
+    # note
     # fedora deps are missing a database, so some is translated from debian packages
     yum -y install mediawiki ImageMagick php-mysqlnd php-pecl-apcu mariadb-server
 
@@ -257,7 +291,9 @@ Here, we [[mediawikiwiki:Download_from_Git]], or reset our installation if it is
 mkdir -p $mw
 cd $mw
 # this will just fail if it already exists which is fine
-git clone https://gerrit.wikimedia.org/r/p/mediawiki/core.git .
+if [[ ! -e .git ]]; then
+    git clone https://gerrit.wikimedia.org/r/p/mediawiki/core.git .
+fi
 # to see available branches: https://www.mediawiki.org/wiki/Version_lifecycle
 # and
 # git branch -r
@@ -265,7 +301,9 @@ git checkout -f origin/$mw_branch
 git clean -ffxd
 # Get the php libraries wmf uses. Based on:
 # https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries
-git clone https://gerrit.wikimedia.org/r/p/mediawiki/vendor.git
+if [[ ! -e vendor/.git ]]; then
+    git clone  https://gerrit.wikimedia.org/r/p/mediawiki/vendor.git
+fi
 cd vendor
 git checkout -f origin/$mw_branch
 cd ..
@@ -273,7 +311,7 @@ cd ..
 # Drop any previous database which may have been installed while testing.
 # If upgrading, we should have a db backup which will get restored.
 # https://www.mediawiki.org/wiki/Manual:Upgrading
-mysql -u root -p$dbpass <<'EOF'
+mysql -u root -p$dbpass <<'EOF' ||:
 drop database my_wiki;
 exit
 EOF
@@ -302,31 +340,6 @@ Upstream vs distro packages. Upstream is responsive, and it's distributed within
 
 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.
 
-== Get Piwik Files ==
-
-Because it's really fun to look at your traffic stats. This is only needed for a production site. We get these files now so that we can take them into account when configuring apache in the next section.
-
-[http://piwik.org/docs/installation-maintenance/ Overall installation guide]
-
-<source lang="bash">
-tmpdir="$(mktemp -d)"
-cd $tmpdir
-wget http://builds.piwik.org/piwik.zip
-if isdeb; then apt-get -y install unzip; else yum -y install unzip; fi
-unzip -q piwik.zip
-# gui installer suggested command
-if isdeb; then
-    chown -R www-data:www-data piwik
-else
-    chown -R apache:apache piwik
-fi
-# remove any existing directory
-rm -rf $mw/../analytics
-mv piwik $mw/../analytics
-rm -rf $tmpdir
-
-</source>
-
 == Configure Apache ==
 
 Note, non-debian based installs: modify instructions below to use /etc/httpd/conf.d/$mwdomain.conf, and don't run a2ensite.
@@ -356,48 +369,41 @@ a2ensite $mwdomain.conf
 </source>
 Then, copy the input to apache-site below and insert it into the apache config.
 
-Here, I use my scripts to setup apache. It's behind nginx because the same server hosts other sites which are not convenient to use the same apache instance.
+Here, we use some scripts automate setting up the Let 's Encrypt cert and
+the apache config.
+
 <source lang="bash">
+temp=$(mktemp -d)
+cd $temp
+git_site=https://iankelling.org/git
+git clone $git_site/acme-tiny-wrapper
 l=$mw/../../logs
-mkdir $l
+mkdir -p $l
 
-acme-tiny-wrapper $mwdomain
-dd of=/etc/apache2/ports.conf <<'EOF'
-Listen 8082
-EOF
+acme-tiny-wrapper/acme-tiny-wrapper -t $mwdomain
+
+git clone $git_site/basic-https-conf
 { cat <<EOF
-  ServerAdmin $mw_email
-  RewriteEngine On
-  # make the site's root url go to our main page
-  RewriteRule ^/?wiki(/.*)?\$ %{DOCUMENT_ROOT}/w/index.php [L]
-  # use short urls https://www.mediawiki.org/wiki/Manual:Short_URL
-  RewriteRule ^/*\$ %{DOCUMENT_ROOT}/w/index.php [L]
+ServerAdmin $mw_email
+RewriteEngine On
+# make the site's root url go to our main page
+RewriteRule ^/?wiki(/.*)?\$ %{DOCUMENT_ROOT}/w/index.php [L]
+# use short urls https://www.mediawiki.org/wiki/Manual:Short_URL
+RewriteRule ^/*\$ %{DOCUMENT_ROOT}/w/index.php [L]
 EOF
-  find -L $(readlink -f $mw/..) -name .htaccess \
-      | while read line; do
-      echo -e "<Directory ${line%/.htaccess}>\n $(< $line)\n</Directory>";
-  done
-} | apache-site -i -p 127.0.0.1:8082 -- - $mwdomain
-nginx-site -p 8082 $mwdomain
-</source>
-
-
-Turn on the new configuration
-<source lang="bash">
-if isdeb; then
-    a2ensite $mwdomain.conf
-    # for short urls
-    a2enmod rewrite
-    # We restart rather than reload because of the module
-    service apache2 restart
-else
-    systemctl reload httpd.service
-fi
+find -L $(readlink -f $mw) -name .htaccess \
+    | while read line; do
+    echo -e "<Directory ${line%/.htaccess}>\n $(< $line)\n</Directory>";
+done
+} | basic-https-conf/apache-site -r ${mw%/*} - $mwdomain
+cd
+rm -rf $temp
 </source>
 
 Now mediawiki should load in your browser at $mwdomain .
 
-Allow proper search bots and internet archiver bots, via [[Mediawiki:Robots.txt]]
+Allow proper search bots and internet archiver bots, via [[Mediawiki:Robots.txt]],
+and install the default skin.
 
 <source lang="bash">
 dd of=$mw/../robots.txt <<'EOF'
@@ -406,13 +412,14 @@ Disallow: /w/
         User-agent: ia_archiver
 Allow: /*&action=raw
 EOF
+mw-skin Vector
 </source>
 
 '''Skippable Notes'''
 
 This section assumes we are redirecting www to a url without www.
 
-[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 piwik 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.
+[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.
 
 == Mediawiki Settings ==
 
@@ -426,7 +433,6 @@ teeu $mwc<<EOF
 \$wgRightsUrl = "$mw_RightsUrl";
 \$wgRightsText = "$mw_RightsText";
 \$wgRightsIcon = "$mw_RightsIcon";
-wfLoadSkin( 'Vector' );
 EOF
 </source>
 Settings I recommend which are different than the defaults.
@@ -464,9 +470,8 @@ EOF
 # https://www.mediawiki.org/wiki/Manual:Configuring_file_uploads
 # Increase from default of 2M to 100M.
 # This will at least allow high res pics etc.
-php_ini=$(isdeb && echo /etc/php5/apache2/php.ini || echo /etc/php.ini)
-sed -i 's/^\(upload_max_filesize\)\b.*/\1 = 100M/'
-sed -i 's/^\(post_max_size\)\b.*/\1 = 100M/'
+php_ini=$(php -r 'echo(php_ini_loaded_file());')
+sed -i --follow-symlinks 's/^\(upload_max_filesize\|post_max_size\)\b.*/\1 = 100M/' $php_ini
 if isdeb; then
     service apache2 restart
 else
@@ -485,14 +490,15 @@ Style settings. Omit to use a different style.
 <source lang="bash">
 teeu $mwc <<'EOF'
 $wgLogo = null;
-$wgShowIPinHeader = false;
-$wgFooterIcons = null;
+#$wgFooterIcons = null;
 EOF
 # Make the toolbox go into the drop down.
-cd $mw
-git remote add ian git@gitorious.org:mediawiki-toolbox-patch/mediawiki-toolbox-patch.git
-git fetch ian
-git rebase ian/REL1_23-toolbox-in-dropdown
+cd $mw/skins/Vector
+if ! git remote show ian-kelling &>/dev/null; then
+    git remote add ian-kelling https://iankelling.org/git/forks/Vector
+fi
+git fetch ian-kelling
+git checkout ian-kelling/REL1_27-toolbox-in-dropdown
 </source>
 
 == Install and Configure Mediawiki Extensions ==
@@ -502,54 +508,51 @@ When installing extensions on a wiki with important content, backup first as a p
 ''' Extensions with no configuration needed '''
 
 {| class="wikitable"
-! Name
-! Description
-|-
-| [[mediawikiwiki:Extension:Cite|Extension:Cite]]
-| Have references in footnotes.
-|-
-| [[mediawikiwiki:Extension:CiteThisPage|Extension:CiteThisPage]]
-| Ability to generate citations to pages in a variety of styles.
-|-
-| [[mediawikiwiki:Extension:CSS|Extension:CSS]]
-| Allows CSS stylesheets to be included in specific articles
-|-
-| [[mediawikiwiki:Extension:DynamicPageList|Extension:DynamicPageList]]
-| Embed page lists from categories & combinations of categories
-|-
-| [[mediawikiwiki:Extension:Echo|Extension:Echo]]
-| Notification subsystem for usage by other extensions
-|-
-| [[mediawikiwiki:Extension:Gadgets|Extension:Gadgets]]
-| UI extension system for users
-|-
-| [[mediawikiwiki:Extension:ImageMap|Extension:ImageMap]]
-| Links for a region of an image
-|-
-| [[mediawikiwiki:Extension:Interwiki|Extension:Interwiki]]
-| Tool for nice links to other wikis
-|-
-| [[mediawikiwiki:Extension:News|Extension:News]]
-| Embed or rss recent changes
-|-
-| [[mediawikiwiki:Extension:Nuke|Extension:Nuke]]
-| Mass delete of pages, in the case of spam
-|-
-| [[mediawikiwiki:Extension:ParserFunctions|Extension:ParserFunctions]]
-| Useful for templates
-|-
-| [[mediawikiwiki:Extension:Poem|Extension:Poem]]
-| Useful for formatting things various ways
-|-
-| [[mediawikiwiki:Extension:SyntaxHighlight_GeSHi|Extension:SyntaxHighlight_GeSHi]]
-| Source code highlighting
-|-
-| [[mediawikiwiki:Extension:Variables|Extension:Variables]]
-| Define per-page variables
-|}
+ ! Name
+ ! Description
+    |-
+    | [[mediawikiwiki:Extension:Cite|Extension:Cite]]
+    | Have references in footnotes.
+    |-
+    | [[mediawikiwiki:Extension:CiteThisPage|Extension:CiteThisPage]]
+    | Ability to generate citations to pages in a variety of styles.
+    |-
+    | [[mediawikiwiki:Extension:CSS|Extension:CSS]]
+    | Allows CSS stylesheets to be included in specific articles
+    |-
+    | [[mediawikiwiki:Extension:Echo|Extension:Echo]]
+    | Notification subsystem for usage by other extensions
+    |-
+    | [[mediawikiwiki:Extension:Gadgets|Extension:Gadgets]]
+    | UI extension system for users
+    |-
+    | [[mediawikiwiki:Extension:ImageMap|Extension:ImageMap]]
+    | Links for a region of an image
+    |-
+    | [[mediawikiwiki:Extension:Interwiki|Extension:Interwiki]]
+    | Tool for nice links to other wikis
+    |-
+    | [[mediawikiwiki:Extension:News|Extension:News]]
+    | Embed or rss recent changes
+    |-
+    | [[mediawikiwiki:Extension:Nuke|Extension:Nuke]]
+    | Mass delete of pages, in the case of spam
+    |-
+    | [[mediawikiwiki:Extension:ParserFunctions|Extension:ParserFunctions]]
+    | Useful for templates
+    |-
+    | [[mediawikiwiki:Extension:Poem|Extension:Poem]]
+    | Useful for formatting things various ways
+    |-
+    | [[mediawikiwiki:Extension:SyntaxHighlight_GeSHi|Extension:SyntaxHighlight_GeSHi]]
+    | Source code highlighting
+    |-
+    | [[mediawikiwiki:Extension:Variables|Extension:Variables]]
+    | Define per-page variables
+    |}
 
 <source lang="bash">
-mw-ext Cite CiteThisPage CSS DynamicPageList Echo Gadgets ImageMap Interwiki News \
+mw-ext Cite CiteThisPage CSS Echo Gadgets ImageMap Interwiki News \
        Nuke ParserFunctions Poem SyntaxHighlight_GeSHi Variables
 </source>
 
@@ -581,7 +584,8 @@ if isdeb; then
     teeu $mwc <<'EOF'
 $wgExternalDiffEngine = 'wikidiff2';
 EOF
-    ln -sf ../../mods-available/wikidiff2.ini /etc/php5/apache2/conf.d
+    dir=$(dirname $(php -r 'echo(php_ini_loaded_file());'))/../apache2/conf.d
+    ln -sf ../../mods-available/wikidiff2.ini $dir
     service apache2 restart
 fi
 </source>
@@ -593,12 +597,16 @@ fi
 mw-ext Math
 # php5-curl according to Math readme
 if isdeb; then
-    apt-get -y install latex-cjk-all texlive-latex-extra texlive-latex-base ghostscript imagemagick ocaml php5-curl
+    curl_pkg=php7.0-curl
+    if ! apt-get -s install $curl_pkg &>/dev/null; then
+        curl_pkg=php5-curl
+    fi
+    apt-get -y install latex-cjk-all texlive-latex-extra texlive-latex-base \
+            ghostscript imagemagick ocaml $curl_pkg make
 else
     # todo, php5-curl equivalent on fedora
     yum -y install texlive-cjk ghostscript ImageMagick texlive ocaml
 fi
-ln -sf ../../mods-available/curl.ini /etc/php5/apache2/conf.d
 service apache2 restart
 
 cd $mw/extensions/Math/math; make # makes texvc
@@ -721,7 +729,7 @@ fi
 
 Enable account creation that we initially disabled.
 <source lang="bash">
-sed -i "/\\\$wgGroupPermissions\\['\\*'\\]\\['createaccount'\\] = false;/d" $mwc
+sed -i --follow-symlinks "/\\\$wgGroupPermissions\\['\\*'\\]\\['createaccount'\\] = false;/d" $mwc
 </source>
 
 == Additional Configuration with Pywikibot ==
@@ -735,9 +743,11 @@ There are quite a few [[mediawikiwiki:Help:Namespaces|special pages]] which act
 
 <source lang="bash">
 # get repo
-mkdir ~/opt
-git clone --recursive https://gerrit.wikimedia.org/r/pywikibot/core.git ~/opt/pywikibot
-cd ~/opt/pywikibot
+if [[ ! -e ~/pywikibot/.git ]]; then
+    git clone --recursive \
+        https://gerrit.wikimedia.org/r/pywikibot/core.git ~/pywikibot
+fi
+cd ~/pywikibot
 #updating
 git pull --all
 git submodule update
@@ -750,7 +760,7 @@ Relevent docs: [[mediawikiwiki:Manual:Pywikibot/Use_on_non-WMF_wikis|Manual:Pywi
 
 
 <source lang="bash">
-cd $HOME/opt/pywikibot
+cd $HOME/pywikibot
 dd of=user-config.py <<EOF
 mylang = 'en'
 usernames["$mwfamily"]['en'] = u'$wikiuser'
@@ -765,6 +775,12 @@ EOF
 
 # it won't overrwrite an existing file. Remove if if one exists
 rm -f  pywikibot/families/${mwfamily}_family.py
+if isdeb; then
+    apt-get install -y python-requests
+else
+    yum -y install python-requests
+fi
+
 python generate_family_file.py https://$mwdomain/wiki/Main_Page "$mwfamily"
 
 # Note, this needed only for ssl site
@@ -780,9 +796,9 @@ EOF
 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]].
 
 <source lang="bash">
-pw="$HOME/opt/pywikibot"
+cd "$HOME/pywikibot"
 
-dd of=$pw/scripts/${mwfamily}_setup.py<<EOF
+dd of=scripts/${mwfamily}_setup.py<<EOF
 import pywikibot
 import time
 import sys
@@ -858,8 +874,8 @@ div#mw-content-text {
 """)
 EOF
 
-cd $pw
-python pwb.py ${mwfamily}_setup
+# this can spam a warning, so uniq it
+python pwb.py ${mwfamily}_setup |& uniq
 </source>
 
 
@@ -871,46 +887,54 @@ Family name, and all its duplicattions documented as supposed to be $wgSitename,
 
 == Automatic Backups ==
 
-Copy this to a file (the next block assumes ~/bin/remote_wiki_backup) on a different machine than the one hosting mediawiki. Also copy ~/mw_vars to the same machine. Setup passwordless sudo to the mediawiki host (specifically, name the host $mwdomain). This will make a versioned backup of the wiki to ~/backup/wiki_file_backup and ~/backup/wiki_db_backup.
+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.
 
-<source lang="bash">
+<source lang="bash" type="backup">
+backup_script=/etc/cron.daily/mediawiki_backup
+sudo dd of=$backup_script <<'EOFOUTER'
 #!/bin/bash
-source ~/mw_vars
-
 # if we get an error, keep going but return it at the end
 last_error=0
 trap 'last_error=$?' ERR
-
-ssh root@$mwdomain <<ENDSSH
+source ~/mw_vars
+# No strict because the host is likely not named the same as
+# the domain.
+ssh="ssh -oStrictHostKeyChecking=no"
+logfile=/var/log/${mwdomain}_backup.log
+{
+echo "#### starting backup at $(date) ####"
+$ssh root@$mwdomain <<ENDSSH
+set -x
 tee -a $mwc<<'EOF'
-$wgReadOnly = 'Dumping Database, Access will be restored shortly';
+\$wgReadOnly = 'Dumping Database, Access will be restored shortly';
 EOF
-mysqldump -p$dbpass --default-character-set=binary my_wiki  > ~/wiki_backup/wikidump
-sed -i '$ d' $mwc # delete last line
+mkdir -p ~/wiki_backups
+mysqldump -p$dbpass --default-character-set=binary my_wiki  > ~/wiki_backups/wiki_db_backup
+sed -i '\$ d' $mwc # delete read only setting
 ENDSSH
-rdiff-backup root@$mwdomain::/root/wiki_db_backup ~/backup/wiki_db_backup
-rdiff-backup root@$mwdomain::$mw ~/backup/wiki_file_backup
-
+# add no strict option to the defaults
+
+rdiff() { rdiff-backup --remote-schema "$ssh -C  %s rdiff-backup --server" "$@"; }
+set -x
+rdiff root@$mwdomain::/root/wiki_backups ~/backup/${mwdomain}_wiki_db_backup
+rdiff root@$mwdomain::$mw ~/backup/${mwdomain}_wiki_file_backup
+set +x
+echo "=== ending backup at $(date) ===="
+}  &>>$logfile
+if [[ $last_error != 0 ]]; then
+    echo "backup for $mwdomain failed. See $logfile"
+fi
 exit $last_error
-</source>
-
-Run this script on the backup machine to setup daily backups at 4 am.
+EOFOUTER
 
-<source lang="bash">
-chmod +x $HOME/bin/remote_wiki_backup
-x="$(mktemp)"
-crontab -l > "$x"
-teeu "$x" <<'EOF'
-0 4 * * * x=$($HOME/bin/remote_wiki_backup 2>&1); [[ $? != 0 ]] && echo "$x"
-EOF
-crontab "$x"
+sudo chmod +x $backup_script
 </source>
 
 If you are like most people and don't use the old-school mail spool, setup the backup system to send mail externally. Some ways to do that are on this [http://unix.stackexchange.com/questions/36982/can-i-set-up-system-mail-to-use-an-external-smtp-server stackoverflow answer]. Then make local mail to your user get forwarded to an address you will read:
 
 '''Optional & requires additional steps'''
 <source lang="bash" type="example">
-sed -i "/^root:/d" /etc/aliases
+sed -i --follow-symlinks "/^root:/d" /etc/aliases
 echo "root: EXAMPLE_ONLY_REPLACE_ME@gmail.com" >> /etc/aliases
 newaliases
 </source>
@@ -919,7 +943,7 @@ newaliases
 
 '''Whenever you implement a backup system, you should test that restoring the backup works.'''
 
-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. However, we backup the entire Mediawiki directory in case you forget to record a step, or some misbehaving code stores some state in a file. Since most people don't record the steps they took to setup Mediawiki, this is also the officially recommended method. Here we restore only the database and images folder, which should help identify any of those aforementioned issues. See [[mediawikiwiki:Manual:Restoring a wiki from backup]] if you run into any problems.
+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.
 
 To test a backup restore:
 # Do a backup of your wiki with some content in it, as described in the previous section
@@ -928,14 +952,23 @@ To test a backup restore:
 # Change REPLACE_ME in the code below (as in the backup section so you get the right variables),
 # Execute the code on the backup machine.
 
-<source lang="bash">
+'''Optional'''
+<source lang="bash" type="example">
+#!/bin/bash
 source ~/mw_vars
-HOSTNAME=REPLACE_ME source ~/mw_vars
-rdiff-backup -r now ~/backup/wiki_file_backup /tmp/wiki_file_restore
-scp -r /tmp/wiki_file_restore/images root@$mwdomain:$mw/images
-rdiff-backup -r now ~/backup/wiki_db_backup /tmp/wiki_db_restore
-scp -r /tmp/wiki_db_restore root@$mwdomain:/tmp
-ssh root@$mwdomain "mysql -u root -p$dbpass my_wiki < /tmp/wiki_db_restore/wiki_db_dump"
+restore="rdiff-backup --force -r now"
+$restore ~/backup/${mwdomain}_wiki_file_backup /tmp/wiki_file_restore
+$restore ~/backup/${mwdomain}_wiki_db_backup /tmp/wiki_db_restore
+o=-oStrictHostKeyChecking=no
+scp $o -r /tmp/wiki_file_restore/images/* root@$mwdomain:$mw/images
+scp $o -r /tmp/wiki_db_restore root@$mwdomain:/tmp
+ssh $o root@$mwdomain <<EOF
+set -e
+chmod -R g+w $mw/images
+chgrp -R www-data $mw/images
+mysql -u root -p$dbpass my_wiki < /tmp/wiki_db_restore/wiki_db_backup
+php $mw/maintenance/update.php
+EOF
 </source>
 
 Then browse to your wiki and see if everything appears to work.
@@ -950,33 +983,29 @@ Major version upgrades should be done manually, and it is recommended to use a n
 
 Minor updates script:
 <source lang="bash">
-s=$HOME/bin/mediawiki_update
+s=/etc/cron.daily/mediawiki_update
 dd of=$s<<'EOF'
 #!/bin/bash
 source ~/mw_vars
 cd $mw
-git fetch --all
-git checkout origin/$mw_branch
-git rebase ian/REL1_23-toolbox-in-dropdown
-cd extensions
-for x in *; do
-    if [[ -d $x ]]; then
-        cd $x
-        git fetch --all
-        git checkout origin/$mw_branch || git checkout -qf origin/master
-        cd ..
+for dir in extensions/* skins/* $mw; do
+    [[ -d $dir ]] || continue
+    cd $dir
+    branch=$(git describe --all)
+    branch=${branch#remotes/}
+    git fetch --all -q
+    new_head=$(git rev-parse $branch)
+    log=$(git log HEAD..$new_head)
+    if [[ $log ]]; then
+        pwd
+        echo "$log"
     fi
+    git checkout -q $new_head
+    cd $mw
 done
 php $mw/maintenance/update.php -q
 EOF
-chmod +x $s
 
-x="$(mktemp)"
-crontab -l > "$x"
-teeu "$x" <<EOF
-0 5 * * * $s
-EOF
-crontab "$x"
 </source>
 
 == Upgrading Major Versions ==
@@ -990,88 +1019,15 @@ My strategy is:
 # Backup the old database, restore it to the new wiki, run php maintenance/update.php.
 # If everything looks good, repeat and replace the old wiki with the new one.
 
-== Setup Piwik ==
-
-<source lang="bash">
-# docs suggests using separate database user, google lead me here for how
-# https://www.digitalocean.com/community/tutorials/how-to-create-a-new-user-and-grant-permissions-in-mysql
-mysql -u root -p$dbpass <<EOF
-CREATE USER 'piwik'@'localhost' IDENTIFIED BY '$piwik_pass';
-GRANT ALL PRIVILEGES ON piwik . * TO 'piwik'@'localhost';
-FLUSH PRIVILEGES;
-exit
-EOF
-</source>
-
-
-''' Manual Steps'''
-
-Unfortunately, Piwik does not document how to do a fully automated install, and although it certainly seems possible, my first glance at the config file after doing manual steps showed a lot of noise, so we are sticking with the manual steps for now.
-
-In a browser, navigate to your_domain/analytics. Follow these steps [http://piwik.org/docs/installation/#the-5-minute-piwik-installation the-5-minute-piwik-installation], using the database password from the previous section.
-
-
-We are going to use an extension to handle the javaScript tracking tag part.
-
-Under settings -> user settings, click the cookie to exclude your current browser.
-
-
-''' [[mediawikiwiki:Extension:Piwik Integration|Extension:Piwik Integration]] '''
-
-<source lang="bash">
-git clone https://github.com/DaSchTour/piwik-mediawiki-extension.git $mw/extensions/Piwik
-mw-ext -g Piwik
-teeu $mwc <<EOF
-\$wgPiwikURL = '$mwdomain/analytics/';
-\$wgPiwikIDSite = '1';
-EOF
-</source>
-
-
-'''If this is not the first site you setup'''
-
-You will need to adjust the previous $wgPiwikIDSite variable. The correct value can be found in the Piwik javaScript tracking tag code, in the line that looks like <code>_paq.push(['setSiteId', 2]);</code>
-
-'''Automatic Updates'''
-
-Automatically update on tuesday, 3 am server time. This code will create an update script at ~/bin/piwik-remote-update. Based on [http://piwik.org/docs/update/ piwik.org/docs/update].
-
-<source lang="bash">
-s=~/bin/piwik-update
-mkdir -p ${s%/*}
-dd of=$s <<EOF
-#!/bin/bash
-piwik_path=$mw/../analytics
-cd "\$(mktemp -d)"
-wget -q http://builds.piwik.org/piwik.zip
-unzip -q piwik.zip
-rm -f piwik.zip
-cp \$piwik_path/config/config.ini.php piwik/config
-cp -rf piwik/* \$piwik_path
-# prevent making an email out of the standard success response
-x="\$( \$piwik_path/console core:update )"
-if [[ \$x != "Everything is already up to date." ]]; then
-echo "\$x"
-fi
-EOF
-chmod +x $s
-
-x="$(mktemp)"
-crontab -l > "$x"
-teeu "$x" <<< "0 3 * * tue $s"
-crontab "$x"
-</source>
-
-
-''' Skippable Notes '''
-
-Piwik docs say use a subdir or a subdomain. googling finds a page which suggests using a subdomain, for more logical separation https://library.linode.com/web-applications/analytics/piwik/centos-5. However, mediawiki doesn't use the root dir of the web server, so the analytics folder can't mess things up by existing there, and it doesn't have any crazy virtualhost settings which might conflict, so there is no need. Plus we get ssl for free by sharing the same domain.
-
-The docs also say: "When you have finished configuring Piwik, you can set more restrictive permissions (ie. read only) to the “piwik/config/” folder. Piwik will always write its data inside the “piwik/tmp/” folder, so this is the only folder that requires write permissions."
+== Stopping Spam ==
 
-But since the files are already owned by the web server user, and already can't be written by anyone else, it seems a bit of a pointless half measure since the owner can override any permissions. Enabling the .htaccess files seems more useful, which it doesn't even mention.
+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:
 
-We could also set up a backup for piwik data, but traffic stat data is not that important so I haven't bothered.
+* Find new spam quickly, revert it & ban the user.
+** 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."
+** 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].
+* Require registration to edit, and a custom captcha question on registration.
+* Install all non-user inhibiting anti-spam extensions / settings that take a reasonable amount of time to figure out.
 
 == Choosing Extensions ==
 
@@ -1080,42 +1036,46 @@ Mediawiki.org has pages for ~5200 extensions. Mediawiki maintains ~700 extension
 Here are brief descriptions of extensions that are part of distributions and why they were rejected for this wiki.
 
 {| class="wikitable"
-|+
-| '''InputBox''' || Add html forms to pages. Can't imagine using it. Would install if I did.
-|+
-| '''Pdfhandler''' || Gallery of pages from a pdf file. Can't imagine using it. Would install if I did.
-|+
-| '''Footnote''' || deprecated in newer versions
-|+
-| '''NewUserNotif''' || Send me a notification when a user registers. Seems like an excessive notification.
-|+
-| '''NewestPages''' ||  A page creation history that doesn't expire like recent-changes. Meh
-|+
-| '''RSSReader''' || Embed an rss feed. Can't imagine using it. Would install if I did.
-|+
-| '''Openid''' || Poor UI. 2 pages & 2 links <login> <login with openid> which is confusing & ugly.
-|+
-| '''Validator''' || dependency of of semantic
-|+
-| '''Semantic''' || Seems like a lot of trouble around analyzing kinds of data which my wiki will not have.
-|+
-| '''wikicalendar''' || Make a calendar of events etc. Can't imagine using it. Would install if I did.
+   |+
+   | '''InputBox''' || Add html forms to pages. Can't imagine using it. Would install if I did.
+   |+
+   | '''Pdfhandler''' || Gallery of pages from a pdf file. Can't imagine using it. Would install if I did.
+   |+
+   | '''Footnote''' || deprecated in newer versions
+   |+
+   | '''NewUserNotif''' || Send me a notification when a user registers. Seems like an excessive notification.
+   |+
+   | '''NewestPages''' ||  A page creation history that doesn't expire like recent-changes. Meh
+   |+
+   | '''RSSReader''' || Embed an rss feed. Can't imagine using it. Would install if I did.
+   |+
+   | '''Openid''' || Poor UI. 2 pages & 2 links <login> <login with openid> which is confusing & ugly.
+   |+
+   | '''Validator''' || dependency of of semantic
+   |+
+   | '''Semantic''' || Seems like a lot of trouble around analyzing kinds of data which my wiki will not have.
+   |+
+   | '''wikicalendar''' || Make a calendar of events etc. Can't imagine using it. Would install if I did.
 |}
 
 == Misc Notes ==
 
+''' Web Analytics Software '''
+
+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.
+
 ''' Mediawiki Documentation Quality '''
 
 Overall the documentation is good, but like wikipedia, it depends.
 
-The closer a topic is to core functionality and commonly used features, the better the documentation is likely to be. My guess is that 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 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.
+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.
 
 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].
 
 
 '''Bash here documents, EOF vs 'EOF' '''
 
-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 quoted by \, which itself must then also be quoted to be used literally.
+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.
 
 
 ''' Mediawiki automation tools survey 7/2014 '''
@@ -1143,8 +1103,7 @@ This means the code is compatible with gplv3.
 
 == todo list for this page ==
 
-* Evaluate any extensions bundled in 27 which I haven't checked out before.
-* Update style patch link.
-* Visual editor
-* Upgrade instructions
-* Consider changing default signature to not have talk link
+* Check if there are any new default extensions 1.27 which I haven't evaluated.
+* Test for any new config values set by the 1.27 gui install method.
+* Get Visual editor extension.
+* Don't require registration for edits