Installing mediawiki
mediawiki install Ubuntu 16.04 notes, needs tidying and formatting
Basics
(https://www.mediawiki.org/wiki/Manual:Upgrading need mediawiki upgrade page but could just link to official)
apt-get install screen software-properties-common
Enable universe (for some of the php libraries)
add-apt-repository universe && apt-get update
Install base software
apt-get install apache2 mysql-server mysql-client php php-mysql php-gd php-curl php-intl php-json imagemagick unzip libapache2-mod-php php-xml php-mbstring
Configure a password for mysql root and store securely.
Extended search
If you want extended search capability in your wiki, also install Sphinx Search (check if the Sphinxsearch is still support for the mediawiki version you want to install, if is not skip this step)
apt-get install sphinxsearch
edit php.ini to set longer timeouts inline with a working day
vi /etc/php/7.0/apache2/php.ini
and set session.gc_maxlifetime to 43200
If making a VM to be a slave, jump to replication section now
Testing DB
If you want to test connection to your MySQL DB try:
vi /var/www/html/phpinfo.php <?php phpinfo(); ?> vi /var/www/html/phpmysql.php add: <?php $con = mysql_connect("localhost","root","yourMySQLrootPassword"); if (!$con) { die('Could not connect: ' . mysql_error()); } else { echo "Congrats! connection established successfully"; } mysql_close($con); ?>
Create DB and user
mysql -u root -p CREATE USER '<username>'@'localhost' IDENTIFIED WITH mysql_native_password BY '<password>'; create database dbname; grant all privileges on dbname.* to username@localhost; flush privileges;
Installing mediawiki files
Download latest version of mediawiki (1.28 at time of writing) from https://www.mediawiki.org/wiki/Download
wget <link>
Then untar it
tar -xzf mediawiki-<version>.tar.gz
Assuming the server will only be serving a wiki, copy the contents of expanded archive to web root (otherwise move the whole directory)
cp -r mediawiki-<version>/* /var/www/html/
Remove Ubuntu's default index page
rm /var/www/html/index.html
Configuration and setup
Visit server via web browser and follow installation steps. Ignore warning regarding cache as is built in to PHP 5.5 and later and will work regardless. Leave at defaults if not clear which option to use.
Configured admin user/password to suit
configured user email to suit (maybe should be a systems one or wikiadmin group depending on IS team setup)
follow steps in later configuration pages as desired, setting default license to CC-BY-SA(Creative Commons Attribution-ShareAlike)
Copied generated LocalSettings.php to /var/www/html
If wanted, place copy of organisation logo (square) in /var/www/html, then
vi LocalSettings.php
and set
$wgLogo="$wgResourceBasePath/<logoname>.png" $wgServer = "https://<whatever the FQDN will be>"
(can use something temporary if this will be a migration and change once the DB and image content is migrated over)
CAS (SSO) Authentication
Using Auth remoteuser extention: https://www.mediawiki.org/wiki/Extension:Auth_remoteuser
Download the extention from here by selecting the mediawiki version you need: https://www.mediawiki.org/wiki/Special:ExtensionDistributor/Auth_remoteuser And place it /var/www/html/extentions
wget <plugin-version-link> tar -xzf Auth_remoteuser-REL1_35-6f570b8.tar.gz mv Auth_remoteuser /var/www/html/extentions/
Add these lines to /var/www/html/LocalSettings.php
wfLoadExtension( 'Auth_remoteuser' ); $wgAuthRemoteuserUserUrls = [ 'logout' => $wgServer.'/logout.php' ]; $wgGroupPermissions['*']['autocreateaccount'] = true;
Create file /var/www/html/logout.php
<?php if (isset($_SERVER['HTTP_COOKIE'])) { $cookies = explode(';', $_SERVER['HTTP_COOKIE']); foreach($cookies as $cookie) { $parts = explode('=', $cookie); $name = trim($parts[0]); setcookie($name, '', 1); setcookie($name, '', 1, '/'); } } header('Location: https://cas.domain.com/cas/logout'); ?>
Install apache2 mod auth cas package and enable it. Note: it is normal for apache2 service to fail after installing the package because you did not configure the vhost yet.
apt-get install libapache2-mod-auth-cas a2enmod auth_cas
Add these lines to the apache2 vhost. Note: it is important to set the ServerName even if it's the only vhost on the server
ServerName wiki.domain.com CASVersion 2 CASLoginURL https://cas.domain.com/cas/login CASValidateURL https://cas.domain.com/cas/serviceValidate CASTimeout 43200 <Location "/"> AuthType CAS AuthName "CAS Authentication" require valid-user </Location>
Restart apache2
systemctl restart apache2
CAS Auth (Deprecated)
Using https://github.com/CWRUChielLab/CASAuth for CAS
Create folder $WIKI/extensions/CASAuth/
mkdir /var/www/html/extensions/CASAuth/ cd /var/www/html/extensions/CASAuth/
Download CASAuth and phpCAS
wget https://github.com/konfuzed/CASAuth/archive/master.zip wget https://github.com/apereo/phpCAS/archive/master.zip
(latest version of phpCAS can be found here: https://wiki.jasig.org/display/CASC/phpCAS)
Extract and install
tar -xzf CAS-1.3.5.tgz mv phpCAS-master/ CAS unzip master.zip mv CASAuth-master/* ./ cp CASAuthSettings.php.template CASAuthSettings.php
Edit file CASAuthSettings.php
$CASAuth["Server"]="cas.example.com"; $CASAuth["Url"]="/cas/"; (or the path that cas can be found at)
And replace other example.com config lines to oxfordarchaeology.com
$CASAuth["CreateAccounts"]=true; (set to false by default)
And would normally set
$CASAuth["RestrictUsers"]=false;
Although you may want to set this to true and enable individual users in some cases, for example where the content should be readable by anyone but only editable by some.
Add following line to LocalSettings.php
require_once( "$IP/extensions/CASAuth/CASAuth.php" );
If you get the wiki longin page after you login through CAS, add this to the apache vhost, most probably in /etc/apache2/sites-enabled/000-default.conf
RedirectMatch ^/$ https://<domain>/index.php/Main_Page
Enabling SphinxSearch (Deprecated)
Create directory under $wiki/extensions/ and download the extension to it
mkdir SphinxSearch cd SphinxSearch
Download
wget https://github.com/wikimedia/mediawiki-extensions-SphinxSearch/archive/master.tar.gz
unzip resulting file, then delete it.
tar -xzf master.tar.gz rm master.tar.gz
move the resulting sphinx.conf to place where it will be readable
cp sphinx.conf /etc/sphinxsearch/
Edit sphinx.conf to suit e.g. database name, login details, log file location and create a data directory for sphinx to create indexes in as per the conf file entries. Ensure you change ownership of the data directory to sphinxsearch:sphinxsearch
mkdir -p /var/data/sphinx chown sphinxsearch:sphinxsearch /var/data/sphinx mkdir /var/log/sphinx chown sphinxsearch:sphinxsearch /var/log/sphinx
Edit /etc/default/sphinxsearch
START=yes
Run indexer first run:
indexer --config /etc/sphinxsearch/sphinx.conf --all
Then start sphinxsearch
To keep it updated, create a file in cron.daily and add
indexer --quiet --config /etc/sphinxsearch/sphinx.conf wiki_main --rotate >/dev/null 2>&1 indexer --quiet --config /etc/sphinxsearch/sphinx.conf wiki_incremental --rotate >/dev/null 2>&1
And if your wiki is active, also create a file in cron.hourly
indexer --quiet --config /etc/sphinxsearch/sphinx.conf wiki_incremental --rotate >/dev/null 2>&1
Download a copy of sphinxapi.php and place in extensions/SphinxSearch/
https://raw.githubusercontent.com/romainneutron/Sphinx-Search-API-PHP-Client/master/sphinxapi.php
In the file LocalSettings.php append the following lines:
$wgSearchType = 'SphinxMWSearch'; require_once "$IP/extensions/SphinxSearch/SphinxSearch.php";
Enabling Cirusssearch
The CirrusSearch extension implements searching for MediaWiki using Elasticsearch.
Dependencies
1. Elasticsearch
You will need to install Elasticsearch
* MediaWiki 1.29.x and 1.30.x require Elasticsearch 5.3.x or 5.4.x. * MediaWiki 1.31.x and 1.32.x require Elasticsearch 5.5.x or 5.6.x. * MediaWiki 1.33.x, 1.34.x and 1.35.x require Elasticsearch 6.5.x (6.5.4 recommended).
Take note that a Java installation like OpenJDK is needed in addition.
sudo apt -y install apt-transport-https wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - echo "deb https://artifacts.elastic.co/packages/oss-6.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-6.x.list sudo apt update sudo apt install apt-transport-https default-jdk default-jre sudo apt-get update && sudo apt-get install elasticsearch-oss
2. After you have modified the configuration, you can start Elasticsearch:
sudo systemctl daemon-reload sudo systemctl enable elasticsearch.service sudo systemctl restart elasticsearch.service
3. Limit Elastic search RAM usage:
Edit /etc/elasticsearch/jvm.options, and set min and max RAM usage:
-Xms128m -Xmx128m
Restart the service:
sudo systemctl daemon-reload sudo systemctl restart elasticsearch.service
3. Elastica Elastica is a PHP library to talk to Elasticsearch. Install Elastica per the instructions below.
Instalation
Get Elasticsearch up and running somewhere. Place the CirrusSearch extension in your extensions directory. You also need to install the Elastica MediaWiki extension. Add this to LocalSettings.php:
wfLoadExtension( 'Elastica' ); wfLoadExtension( 'CirrusSearch' ); $wgDisableSearchUpdate = true;
Configure your search servers in LocalSettings.php if you aren't running Elasticsearch on localhost:
$wgCirrusSearchServers = [ 'elasticsearch0', 'elasticsearch1', 'elasticsearch2', 'elasticsearch3' ];
There are other $wgCirrusSearch variables that you might want to change from their defaults.
Now run this script to generate your elasticsearch index:
php $MW_INSTALL_PATH/extensions/CirrusSearch/maintenance/UpdateSearchIndexConfig.php
Now remove $wgDisableSearchUpdate = true from LocalSettings.php. Updates should start heading to Elasticsearch.
Next bootstrap the search index by running:
php $MW_INSTALL_PATH/extensions/CirrusSearch/maintenance/ForceSearchIndex.php --skipLinks --indexOnSkip php $MW_INSTALL_PATH/extensions/CirrusSearch/maintenance/ForceSearchIndex.php --skipParse
Note that this can take some time.
Once that is complete add this to LocalSettings.php to funnel queries to ElasticSearch:
$wgSearchType = 'CirrusSearch';
Create a crontab to update the elasticsearch indexes:
0 * * * * /usr/bin/php /var/www/html/maintenance/runJobs.php --maxtime=3600 > /var/log/runJobs.log 2>&1
Adding extended <code> tag support
Download geshi:
wget https://github.com/GeSHi/geshi-1.0/archive/master.zip unzip master.zip cp -r geshi-1.0-master /var/www/html/extensions/SyntaxHighlight_GeSHi/
Create a file and copy the code below in it:
mkdir /var/www/html/extensions/Code vi /var/www/html/extensions/Code/Code.php
<?php if( !defined( 'MEDIAWIKI' ) ) { echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" ); die( -1 ); } $wgExtensionCredits['other'][] = array( 'path' => __FILE__, 'name' => 'Code', 'version' => '0.9', 'author' => 'Paul Grinberg', 'url' => 'https://www.mediawiki.org/wiki/Extension:Code', 'description' => 'Allows syntax highlighting using GeSHi' ); $wgHooks['ParserFirstCallInit'][] = 'efCodeExtensionInit'; function efCodeExtensionInit(Parser &$parser) { $parser->setHook( "Code", "efCodeExtensionRenderCode" ); return true; } function efCodeExtensionRenderCode($input, $argv, $parser) { global $wgShowHideDivi, $wgOut; // default values $language = 'text'; $showLineNumbers = false; $showDownloadLink = false; $source = $input; $tabwidth = 4; foreach ($argv as $key => $value) { switch ($key) { case 'lang': $language = $value; break; case 'linenumbers': $showLineNumbers = true; break; case 'tabwidth': $tabwidth = $value; break; case 'download': $showDownloadLink = true; break; case 'fileurl': $html = $parser->unstrip($parser->recursiveTagParse($value),$parser->mStripState); $i = preg_match('/<a.*?>(.*?)<\/a>/', $html, $matches); $url = $matches[1]; //print("URL is '$url'"); #$source = "file_get_contents disabled! Contact your wiki admin with questions."; $source = file_get_contents($url); break; default : wfDebug( __METHOD__.": Requested '$key ==> $value'\n" ); break; } } if (!defined('GESHI_VERSION')) { include('extensions/SyntaxHighlight_GeSHi/src/geshi.php'); // include only once or else wiki dies } $geshi = new GeSHi($source, $language); $error = $geshi->error(); // die gracefully if errors found if ($error) { return "Code Extension Error: $error"; } $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS); // always display line numbers $geshi->set_tab_width($tabwidth); $code = $geshi->parse_code(); $code_pieces = preg_split('/\<ol/', $code ); $output = ''; $ol_tag = '<ol'; if (!$showLineNumbers) { // if not asked to show line numbers, then we should hide them. This is the preferred method // because this allows for a means of a block of code in the middle of a numbered list $output .= "<style type='text/css'><!-- ol.codelinenumbers { list-style: none; margin-left: 0; padding-left: 0em;} --></style>"; $ol_tag = "<ol class='codelinenumbers'"; } $output .= $code_pieces[0]; if ($showDownloadLink) { $output .= "<a href=\"javascript:win3 = window.open('', 'code', 'width=320,height=210,scrollbars=yes');win3.document.writeln('$source');\" style=\"float:right\">Download Code</a>\n"; } $output .= $ol_tag . $code_pieces[1]; return $output; }
Add the following line to /var/www/html/LocalSettings.php:
require_once "$IP/extensions/Code/Code.php";
Public pages on secured server
If you want to secure your server but have some pages available publicly, then you can add them to $wgWhitelistRead
vi /var/www/html/LocalSettings.php
Find
$wgWhitelistRead
And add in a comma separated list the pages you want to make public, in quotes " " so you get something like
$wgWhitelistRead = array ( "Special:Search", "Special:Random", "Installing mediawiki" );
Any pages added will be public immediately the file is saved.
Apache vhost example for a reverse proxy
NB in virtual host declaration on proxy, use 301 redirect to force SSL - this prevents problems with CAS URL redirects e.g.
<VirtualHost *:80>
ServerName blahwiki.oxfordarchaeology.com ServerAlias blahwiki.thehumanjourney.net
Redirect 301 / https://blahwiki.oxfordarchaeology.com
ProxyPass / http://192.168.98.45/ ProxyPassReverse / http://192.168.98.45/
CustomLog /var/log/apache2/blahwiki.oxfordarchaeology.com.access.log combined ErrorLog /var/log/apache2/blahwiki.oxfordarchaeology.com.error.log
</VirtualHost>
<VirtualHost *:443> ServerName blahwiki.oxfordarchaeology.com
SSLEngine on SSLCertificateFile /etc/apache2/ssl/oxfordarchaeology.crt SSLCertificateKeyFile /etc/apache2/ssl/oxfordarchaeology.com.key SSLCertificateChainFile /etc/apache2/ssl/oxfordarchaeology.intermediate.crt
ProxyPass / http://192.168.98.45/ ProxyPassReverse / http://blahwiki.oxfordarchaeology.com/ ProxyPassReverse / http://192.168.98.45/
CustomLog /var/log/apache2/blahwiki.oxfordarchaeology.com.access.log combined ErrorLog /var/log/apache2/blahwiki.oxfordarchaeology.com.error.log </VirtualHost>
Replication
Following wikipedia with master/slave DB replication and then using rysnc wih --delete flag to keep mediawiki dir synched
On the master:
vi /etc/mysql/my.cnf
set bind-address to the LAN IP of the server
set server-id to something unique for the replication group. Easiest choice is LAN IP (without the dots)
uncomment log_bin
set binlog_do_db to the name of the wiki DB (as per LocalSettings.php)
Restart mysql
service mysql restart
Enter mysql root
mysql -u root -p
Create slave user (username/password as you want)and grant access
GRANT REPLICATION SLAVE ON *.* TO 'username'@'%' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
Switch to the wikiDB (name as per LocalSettings.php
USE wikiDB
Lock the database to prevent any new changes during setup:
FLUSH TABLES WITH READ LOCK;
Then enter
SHOW MASTER STATUS;
Copy the outcome into text file for reference (as in on your PC)
+------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000001 | 428 | itwiki | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
In a new console start a new shell into the master wiki and dump the DB
mysqldump -u root -p --opt nameofwikiDB > /tmp/nameofwikiDB.sql
Now return to original console and unlock the DB
UNLOCK TABLES;
EXIT;
On the slave
Goto mysql root
mysql -u root -p
and create the DB to be replicated (name as per previous)
CREATE DATABASE wikiDB;
EXIT;
Copy the SQL file dumped earlier to the slave VM, then import it
mysql -u root -p wikiDB < wikiDB.sql
vi /etc/mysql/my.cnf
set server-id to something unique for the replication group. Easiest choice is LAN IP (without the dots)
uncomment log_bin
set binlog_do_db to the name of the wiki DB (as per LocalSettings.php)
Add line below log_bin
relay-log = /var/log/mysql/mysql-relay-bin.log
Restart mysql
service mysql restart
Goto mysql root
mysql -u root -p
Enter the following command, changing values as appropriate
CHANGE MASTER TO MASTER_HOST='ip.ad.re.ss', MASTER_USER='usernamefromabove',MASTER_PASSWORD='passwordfromabove',MASTER_LOG_FILE='mysql-bin.xxxx',MASTER_LOG_POS=xxx;
Replication (files)
Create user for replication on slave
adduser --disabled-password <username>
su <username>
Create key as per sshauth pages but without a passphrase
change to master server, create account and add key auth as per sshauth page, but prepend key (all one line still) with
from="slave.ip.addr.ess",no-X11-forwarding,no-agent-forwarding,no-port-forwarding
chown html dir on slave to <username>:root
chown -R <username>:root /var/www/html
on slave server change to wiki replication user
su <username>
and run
rsync -a --delete <master.ip.addr.ess>:/var/www/html/ /var/www/html/|more
checking output for errors. NB this command will recursively copy from source to target, deleting any files on target that do not exist on the host
Assuming no errors, create a cron.daily script to keep it up to date and log output (exit from <username> shell)
vi /etc/cron.daily/
- !/bin/bash
FULLDATE=`date +%Y-%m-%d:%H:%M:%S` DATE=`date +%Y%m%d` echo $FULLDATE > /tmp/rsynclog chmod +w /tmp/rsynclog sudo -i -u wikisync rsync -av --delete 192.168.98.46:/var/www/html/ /var/www/html/ >> /tmp/rsynclog mv /tmp/rsynclog /var/log/rsynclog-$DATE
Making the slave into the master copy of the wiki may (a) require changing permissions on the web dir, (b) changing master/slave settings in mysql (though should work without, just no write access) and (c) removing the cron.daily script (though it should just mark an error in the log)
---need notes on adding '<code>' tag
Troubleshooting CAS
Enable debug by editting CASAuth.php and adding the line
phpCAS::setDebug()
after
// Load phpCAS require_once($CASAuth["phpCAS"]."/CAS.php");
This creates a logfile in /tmp of the server attempting CAS authentication with detailed information about the CAS attempt and failures.
Remember to comment out or delete the line once the issue has been resolved.
Migration
On the old server dump all pages into an xml file
php /var/www/html/maintenance/dumpBackup.php --full > wikidump.xml
Copy the file to the new server and import it
php /var/www/html/maintenance/importDump.php < wikifile.xml php /var/www/html/maintenance/rebuildrecentchanges.php
If you also have images, copy the directory /var/www/html/images from the old server to the new one(not in the same location) and import the images. The command will need to run as www-data user so the images will be imported with the right ownership.
sudo -u www-data php /var/www/html/maintenance/importImages.php --search-recursively /path/to/import/images
Session timeout
To set the session timeout put this in /var/www/html/LocalSettings.php
$wgCookieExpiration = 28800; $wgExtendedLoginCookieExpiration = null;
Troubleshoot
Lock the database:
$wgReadOnly = "We are upgrading MediaWiki, please be patient. This wiki will be back in a few minutes.";
Db connection error:
Cannot access the database: :real_connect(): (HY000/1698): Access denied for user 'root'@'localhost'. Check the host, username and password and try again. If using "localhost" as the database host, try using "127.0.0.1" instead (or vice versa).
To fix this error run the command below:
ALTER USER '<username>'@'localhost' IDENTIFIED WITH mysql_native_password BY '<password>';