3. Install MediaWiki

  1. Start the virtual machine and log in:

    ssh -p 8015 hjc@dynamicshjc.case.edu
    
  2. Check for and install system updates on the virtual machine:

    sudo apt-get update
    sudo apt-get dist-upgrade
    sudo apt-get autoremove
    
  3. Install these new packages,

    Package Description
    php server-side, HTML-embedded scripting language
    php-pear PEAR - PHP Extension and Application Repository
    php-mbstring MBSTRING module for PHP
    php-intl Internationalisation module for PHP
    php-dev Files for PHP module development (needed for phpize for compiling apcu)
    imagemagick image manipulation programs
    python-mysqldb Python interface to MySQL
    python-ldap LDAP interface module for Python
    Mail Class that provides multiple interfaces for sending emails
    php-apcu APC (Alternative PHP Cache) User Cache for PHP [1]

    using the following (when asked about enabling internal debugging, just press Enter):

    sudo apt-get install php php-pear php-mbstring php-intl php-dev imagemagick python-mysqldb python-ldap
    sudo pear install --alldeps Mail
    sudo pecl install apcu_bc-beta
    sudo bash -c "echo extension=apcu.so > /etc/php/7.0/mods-available/apcu.ini"
    sudo bash -c "echo extension=apc.so > /etc/php/7.0/mods-available/z_apc.ini"
    sudo phpenmod apcu z_apc
    
  4. Download the source code for the latest version of MediaWiki with long term support (LTS).

    LTS versions of MediaWiki receive guaranteed support (e.g., security updates) for 3 years, although these updates must be applied manually (see Updating MediaWiki). As of August 2016, the latest LTS version is MediaWiki 1.27.1, which will be supported until June 2019. The next LTS release should be available in mid-2018. [2]

    Run these commands to download and install the source code:

    wget -P ~ https://releases.wikimedia.org/mediawiki/1.27/mediawiki-1.27.1.tar.gz
    tar -xvzf ~/mediawiki-*.tar.gz -C /var/www
    mkdir -p /var/www/mediawiki
    mv /var/www/mediawiki-*/* /var/www/mediawiki
    rm -rf /var/www/mediawiki-* ~/mediawiki-*.tar.gz
    sudo chown -R www-data:www-data /var/www/mediawiki
    sudo chmod -R ug+rw /var/www/mediawiki
    
  5. Download and install a custom Apache configuration file for MediaWiki:

    sudo wget -O /etc/apache2/conf-available/mediawiki.conf https://neurowiki-docs.readthedocs.io/en/latest/_downloads/mediawiki.conf
    sudo a2enconf mediawiki
    sudo apache2ctl restart
    

    If you are curious about the contents of mediawiki.conf, you can view it here:

    mediawiki.conf

    Direct link

    #
    #
    # MEDIAWIKI CONFIGURATION
    #
    #
    
    
    # Aliases allow short URLs for the wiki
    
    Alias /wiki /var/www/mediawiki/index.php
    Alias /w    /var/www/mediawiki
    
    
    # Redirect to the wiki when a URL lacks a path, e.g.,
    # https://example.com redirects to https://example.com/wiki
    
    RedirectMatch ^/$ /wiki
    
    
    # Allow large form submissions (for grading) and large file transfers
    # (for wiki uploads)
    
    php_admin_value max_input_vars 50000
    php_admin_value memory_limit 256M
    php_admin_value post_max_size 105M
    php_admin_value upload_max_filesize 100M
    
    
    # Allow wiki files to be served
    
    <Directory ~ "/var/www/mediawiki">
        Require all granted
    </Directory>
    
    
    # Prevent scripts uploaded to the wiki from being executed
    
    <Directory ~ "/var/www/mediawiki/images">
        # Serve HTML as plaintext, don't execute SHTML
        AddType text/plain html htm shtml php phtml php5
    
        # Don't run arbitrary PHP code
        php_admin_flag engine off
    </Directory>
    
    
    # Forbid access to deleted files
    
    <Directory ~ "/var/www/mediawiki/images/deleted">
        Require all denied
    </Directory>
    
    
    # Forbid access to the cache
    
    <Directory ~ "/var/www/mediawiki/cache">
        Require all denied
    </Directory>
    
    
    # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
    
  6. Create and initializing the wiki database (do not forget to fill in the passwords):

    php /var/www/mediawiki/maintenance/install.php --dbname wikidb --dbuser root --dbpass <MySQL password> --pass <wiki admin password> NeuroWiki Hjc
    
  7. Download and install the MediaWiki configuration file:

    wget -O /var/www/mediawiki/LocalSettings.php https://neurowiki-docs.readthedocs.io/en/latest/_downloads/LocalSettings.php
    

    Set the passwords and randomize the secret keys inside the configuration file:

    read -s -r -p "MySQL password: " DBPASS && sed -i '/^\$wgDBpassword/s|".*";|"'$DBPASS'";|' /var/www/mediawiki/LocalSettings.php; DBPASS= ; echo
    
    read -s -r -p "Gmail password: " GMPASS && sed -i '/^    .password./s|".*"|"'$GMPASS'"|' /var/www/mediawiki/LocalSettings.php; GMPASS= ; echo
    
    sed -i '/^\$wgSecretKey/s|".*";|"'$(openssl rand -hex 32)'";|' /var/www/mediawiki/LocalSettings.php
    
    sed -i '/^\$wgUpgradeKey/s|".*";|"'$(openssl rand -hex 8)'";|' /var/www/mediawiki/LocalSettings.php
    

    Protect the passwords in the configuration file:

    sudo chown www-data:www-data /var/www/mediawiki/LocalSettings.php*
    sudo chmod ug=rw,o= /var/www/mediawiki/LocalSettings.php*
    

    If you are curious about the contents of LocalSettings.php, you can view it here:

    LocalSettings.php

    Direct link

    <?php
    # This file was automatically generated by the MediaWiki 1.27.0
    # installer. If you make manual changes, please keep track in case you
    # need to recreate them later.
    #
    # See includes/DefaultSettings.php for all configurable settings
    # and their default values, but don't forget to make changes in _this_
    # file, not there.
    #
    # Further documentation for configuration settings may be found at:
    # https://www.mediawiki.org/wiki/Manual:Configuration_settings
    
    # Protect against web entry
    if ( !defined( 'MEDIAWIKI' ) ) {
    	exit;
    }
    
    ## Uncomment this to disable output compression
    # $wgDisableOutputCompression = true;
    
    $wgSitename = "NeuroWiki";
    
    ## The URL base path to the directory containing the wiki;
    ## defaults for all runtime URL paths are based off of this.
    ## For more information on customizing the URLs
    ## (like /w/index.php/Page_title to /wiki/Page_title) please see:
    ## https://www.mediawiki.org/wiki/Manual:Short_URL
    $wgScriptPath = "/w";
    
    ## The protocol and server name to use in fully-qualified URLs
    ## Note: Leaving $wgServer undefined will allow it to be determined
    ## automatically, which is necessary when switching from port forwarding to
    ## bridged networking or when cloning the dev server
    #$wgServer = "https://dynamicshjc.case.edu:8014";
    
    ## The URL path to static resources (images, scripts, etc.)
    $wgResourceBasePath = $wgScriptPath;
    
    ## The URL path to the logo.  Make sure you change this from the default,
    ## or else you'll overwrite your logo when you upgrade!
    $wgLogo = "$wgScriptPath/images/a/a0/Wiki-logo.png";
    
    ## UPO means: this is also a user preference option
    
    $wgEnableEmail = true;
    $wgEnableUserEmail = true; # UPO
    
    $wgEmergencyContact = "neurowiki.case@gmail.com";
    $wgPasswordSender = "neurowiki.case@gmail.com";
    
    $wgEnotifUserTalk = true; # UPO
    $wgEnotifWatchlist = true; # UPO
    $wgEmailAuthentication = true;
    
    ## Database settings
    $wgDBtype = "mysql";
    $wgDBserver = "localhost";
    $wgDBname = "wikidb";
    $wgDBuser = "root";
    $wgDBpassword = "<MySQL password>";
    
    # MySQL specific settings
    $wgDBprefix = "";
    
    # MySQL table options to use during installation or update
    $wgDBTableOptions = "ENGINE=InnoDB, DEFAULT CHARSET=binary";
    
    # Experimental charset support for MySQL 5.0.
    $wgDBmysql5 = false;
    
    ## Shared memory settings
    $wgMainCacheType = CACHE_ACCEL;
    $wgMemCachedServers = [];
    
    ## To enable image uploads, make sure the 'images' directory
    ## is writable, then set this to true:
    $wgEnableUploads = true;
    $wgUseImageMagick = true;
    $wgImageMagickConvertCommand = "/usr/bin/convert";
    
    # InstantCommons allows wiki to use images from https://commons.wikimedia.org
    $wgUseInstantCommons = true;
    
    ## If you use ImageMagick (or any other shell command) on a
    ## Linux server, this will need to be set to the name of an
    ## available UTF-8 locale
    $wgShellLocale = "en_US.utf8";
    
    ## Set $wgCacheDirectory to a writable directory on the web server
    ## to make your wiki go slightly faster. The directory should not
    ## be publically accessible from the web.
    $wgCacheDirectory = "$IP/cache";
    
    # Site language code, should be one of the list in ./languages/data/Names.php
    $wgLanguageCode = "en";
    
    $wgSecretKey = "<random string>";
    
    # Changing this will log out all existing sessions.
    $wgAuthenticationTokenVersion = "1";
    
    # Site upgrade key. Must be set to a string (default provided) to turn on the
    # web installer while LocalSettings.php is in place
    $wgUpgradeKey = "<random string>";
    
    ## For attaching licensing metadata to pages, and displaying an
    ## appropriate copyright notice / icon. GNU Free Documentation
    ## License and Creative Commons licenses are supported so far.
    $wgRightsPage = ""; # Set to the title of a wiki page that describes your license/copyright
    $wgRightsUrl = "https://creativecommons.org/licenses/by-nc-sa/4.0/";
    $wgRightsText = "Creative Commons Attribution-NonCommercial-ShareAlike";
    $wgRightsIcon = "$wgResourceBasePath/resources/assets/licenses/cc-by-nc-sa.png";
    
    # Path to the GNU diff3 utility. Used for conflict resolution.
    $wgDiff3 = "/usr/bin/diff3";
    
    # The following permissions were set based on your choice in the installer
    $wgGroupPermissions['*']['createaccount'] = false;
    $wgGroupPermissions['*']['edit'] = false;
    
    ## Default skin: you can change the default skin. Use the internal symbolic
    ## names, ie 'vector', 'monobook':
    $wgDefaultSkin = "vector";
    
    # Enabled skins.
    # The following skins were automatically enabled:
    wfLoadSkin( 'Vector' );
    
    
    # Enabled extensions. Most of the extensions are enabled by adding
    # wfLoadExtensions('ExtensionName');
    # to LocalSettings.php. Check specific extension documentation for more details.
    # The following extensions were automatically enabled:
    wfLoadExtension( 'Cite' );
    wfLoadExtension( 'Gadgets' );
    wfLoadExtension( 'Interwiki' );
    wfLoadExtension( 'Nuke' );
    wfLoadExtension( 'ParserFunctions' );
    wfLoadExtension( 'Renameuser' );
    wfLoadExtension( 'SyntaxHighlight_GeSHi' );
    wfLoadExtension( 'WikiEditor' );
    
    
    # End of automatically generated settings.
    # Add more configuration options below.
    
    
    # Disable one form of caching so that newly uploaded files are immediately
    # visible on pages
    $wgParserCacheType = CACHE_NONE;
    
    # Set default time zone for display
    $wgDefaultUserOptions['timecorrection'] = 'ZoneInfo|-240|America/New_York';
    
    # Enable short URLs
    $wgUsePathInfo = true;
    $wgArticlePath = "/wiki/$1";
    
    # Favicon
    $wgFavicon = "$wgScriptPath/images/7/77/Wiki-favicon.ico";
    
    # Fix site customization on Special:Preferences page
    $wgAllowSiteCSSOnRestrictedPages = true;
    
    # Configure email sent from the wiki
    $wgPasswordSenderName = $wgSitename;
    $wgSMTP = array(
        'host'      => "smtp.gmail.com",
        'IDHost'    => "gmail.com",
        'port'      => 587,
        'auth'      => true,
        'username'  => "neurowiki.case",
        'password'  => "<gmail password>"
    );
    
    # Allow uploads of additional file types
    $wgFileExtensions[] = "nb";
    $wgFileExtensions[] = "cdf";
    $wgFileExtensions[] = "m";
    $wgFileExtensions[] = "wl";
    $wgFileExtensions[] = "pdf";
    $wgFileExtensions[] = "ico";  # for uploading the wiki favicon
    
    # MediaWiki is suspicious of Import and Export commands in Mathematica
    # notebooks, e.g., Chapter02.nb from BIOL 300. Disable script checks before
    # uploading notebooks, then re-enable them for security purposes. Toggle between
    # states by running
    #   sudo disable-upload-script-checks
    # which will change the value of this variable.
    $wgDisableUploadScriptChecks = false;
    
    # Some Mathematica notebooks with file sizes smaller than the PHP memory limit
    # will still cause PHP to run out of memory when the notebooks are uploaded
    # (perhaps data compressed in the notebook is being expanded?). A blank white
    # page will appear when uploading the file. Enable PHP error reporting for
    # debugging.
    #error_reporting(E_ALL);
    #ini_set('display_errors', 1);
    
    # When all else fails, enable debugging details to track down issues with
    # extensions, etc.  Useful when you get the MWException error.
    #$wgShowExceptionDetails = true;
    
  8. Create a script for toggling a security variable by downloading and installing a file:

    sudo wget -O /usr/local/sbin/disable-upload-script-checks https://neurowiki-docs.readthedocs.io/en/latest/_downloads/disable-upload-script-checks
    sudo chmod +x /usr/local/sbin/disable-upload-script-checks
    

    If you are curious about the contents of the script, you can view it here:

    disable-upload-script-checks

    Direct link

    #!/bin/bash
    
    # Place this script in /usr/local/sbin and make it executable (chmod +x).
    #
    # This script will toggle the MediaWiki variable $wgDisableUploadScriptChecks.
    # This variable should be set to false to improve security, but occasionally it
    # must temporarily be set to true so that certain files (e.g., Chapter02.nb from
    # BIOL 300) can be uploaded, since MediaWiki mistakenly thinks it contains
    # malicious code.
    
    
    # Function for aborting with an error message
    
    die () {
        echo >&2 "$@"
        exit 1
    }
    
    
    # Require that the user is root.
    
    [ "$UID" -eq 0 ] || die "Aborted: superuser privileges needed (rerun with sudo)"
    
    
    # Get the current state of the $wgDisableUploadScriptChecks variable
    
    STATE=$(grep ^\$wgDisableUploadScriptChecks /var/www/mediawiki/LocalSettings.php | awk '{ print $3 }')
    
    
    # Determine the new state
    
    if [ "$STATE" == "false;" ]; then
        NEWSTATE="true;"
        echo "Security checks on wiki file uploads are now DISABLED. RE-ENABLE WHEN YOU'RE DONE!"
    else
        NEWSTATE="false;"
        echo "Security checks on wiki file uploads are now ENABLED."
    fi
    
    
    # Set the new state.
    
    sed -i '/^\$wgDisableUploadScriptChecks/s|= \(.*\);|= '$NEWSTATE'|' /var/www/mediawiki/LocalSettings.php
    
    exit 0
    
  9. Allow MediaWiki to recognize Mathematica notebooks and package files so that they can be uploaded:

    echo "text nb cdf m wl" >> /var/www/mediawiki/includes/mime.types
    
  10. Download and install a script for fetching real names for MediaWiki users. Since the CASAuth extension, which will be installed later, automatically fetches real names, this script should not need to be run regularly.

    sudo wget -O /usr/local/sbin/set-real-names-in-mediawiki https://neurowiki-docs.readthedocs.io/en/latest/_downloads/set-real-names-in-mediawiki
    

    Set the MySQL password inside the script:

    read -s -r -p "MySQL password: " DBPASS && sudo sed -i "/^sql_pass =/s|= .*|= '$DBPASS'|" /usr/local/sbin/set-real-names-in-mediawiki; DBPASS= ; echo
    

    Protect the password:

    sudo chown root:www-data /usr/local/sbin/set-real-names-in-mediawiki
    sudo chmod ug=rwx,o= /usr/local/sbin/set-real-names-in-mediawiki
    

    Run the script to fetch your real name for your account:

    sudo set-real-names-in-mediawiki
    sudo apache2ctl restart
    

    If you are curious about the contents of the script, you can view it here:

    set-real-names-in-mediawiki

    Direct link

    #!/usr/bin/python
    
    # Place this script in /usr/local/sbin and make it executable (chmod +x).
    #
    # This script will fetch real names for any MediaWiki user lacking a real name.
    
    
    from __future__ import print_function
    import MySQLdb
    import ldap
    
    def ldap_search(searchstr):
        """Use a search string to fetch a uid and displayName using LDAP"""
    
        # login to the LDAP server
        l = ldap.init('ldap.case.edu')
        l.simple_bind('anonymous','')
    
        # look up the user's name by user id
        res_id = l.search('ou=People,o=cwru.edu,o=isp',
                ldap.SCOPE_SUBTREE, searchstr)
        res_t, res_d = l.result(res_id, 1000)
    
        if len(res_d) > 0:
            result = [res_d[0][1]['uid'][0],
                      res_d[0][1]['displayName'][0]]
                      #res_d[0][1]['cn'][0],
                      #res_d[0][1]['givenName'][0],
                      #res_d[0][1]['sn'][0]]
        else:
            result = []
    
        # log out of the server
        l.unbind_s()
    
        return result
    
    # database connection credentials
    sql_user = 'root'
    sql_pass = '<MySQL password>'
    sql_db   = 'wikidb'
    
    # connect to the wiki database
    db  = MySQLdb.connect(host='localhost', user=sql_user, passwd=sql_pass, db=sql_db)
    cur = db.cursor()
    
    # query for ids of users lacking a real name
    cur.execute('SELECT user_name FROM user WHERE (user_real_name = "" OR LOWER(CONVERT(user_real_name USING latin1)) = LOWER(CONVERT(user_name USING latin1)))')
    ids = [row[0] for row in cur.fetchall()]
    
    if len(ids) == 0:
        print("Aborting: All wiki users already have real names.")
        exit(0)
    
    # print the user ids
    print("Wiki users without a real name:")
    print(' '.join(ids) + '\n')
    
    # query ldap for user real names
    results = []
    for id in ids:
        result = ldap_search("(uid={0})".format(id))
        if len(result) > 0:
            results.append(result)
        else:
            print('%s does not appear in the LDAP database!' % (id))
    
    if len(results) == 0:
        print("Aborting: All wiki users without real names cannot be identified.")
        exit(0)
    
    # construct a list of queries for updating user real names
    sql_queries = [];
    for user in results:
        sql_queries.append('UPDATE user SET user_real_name="%s" WHERE user_name="%s"' % (user[1], user[0].title()))
    
    # print the queries
    print('\n'.join(sql_queries) + '\n')
    
    # prompt for confirmation
    raw_input('Press [Enter] to execute these SQL commands.')
    
    # execute each query
    for query in sql_queries:
        try:
            cur.execute(query)
        except MySQLdb.Error, e:
            try:
                print('MySQL Error [%d]: %s' % (e.args[0], e.args[1]))
            except IndexError:
                print('MySQL Error: %s' % str(e))
    db.commit()
    print('Done!')
    
    # close the database connection
    cur.close()
    db.close()
    
  11. The wiki should now be accessible. Open a web browser and navigate to

    You should see a default page provided by MediaWiki. The wiki logo and favicon should be missing for now.

  12. Shut down the virtual machine:

    sudo shutdown -h now
    
  13. Using VirtualBox, take a snapshot of the current state of the virtual machine. Name it “MediaWiki installed”.

Footnotes

[1]

PHP version 7.0 is packaged with this version of Ubuntu; in earlier versions of Ubuntu, PHP 5 was used (fun fact: PHP 6 never existed). The PHP module APC provides the wiki with object caching, which should improve its performance. This module is compatible with PHP 5.4 and earlier, but not PHP 5.5, 5.6, or 7.0. For these newer versions of PHP, a replacement module called APCu exists. For the purposes of object caching, it can do the job, but it uses different function calls than the MediaWiki source code expects (e.g., apcu_fetch() rather than apc_fetch()). The versions of APCu that work with PHP 5.5 and 5.6 include backwards compatibility code that handles this. However, the version of APCu that works with PHP 7.0, which is what you get if you use sudo apt-get install php-apcu, dropped the backwards compatibility. Instead, a forked version of APCu needs to be used which restores backwards compatibility. To install that, I followed the instructions found here, which have been incorporated into the instructions above.

This was so much fun to figure out. If you could see my face right now, you would know that I am totally serious and not at all being sarcastic.

[2]You can visit this page to see the release schedule for versions of MediaWiki. The MediaWiki download page provides the URL for downloading the tar archive.