从零部署 MediaWiki 服务

 

由于某些需要,最近尝试了自行部署著名的 MediaWiki 平台。记录一下遇到的一些坑和相关注意事项,供此后参考。

不要用 Docker!

虽然 MediaWiki 官方提供了 Docker 镜像,但我个人并不推荐使用。比较大的问题来源于它不能清晰地区分源码和 artifact。特别地,源码目录下的 imagesextensionsskins 目录都是需要持久化的,分别保存了上传的图片、安装的扩展和皮肤。

通常使用的挂载为 volume 的方法对于 MediaWiki 并不优雅,因为它的源码中内置了一些 extensionsskins,于是必须先复制出来才能正常工作。 这与 Overleaf 部署 一文中将一些 TeX Live 需要的目录复制并挂载有本质的区别,因为这些插件或者皮肤是与 MediaWiki 程序本身存在紧密的耦合,不像 TeX Live 或者字体都是能够独立工作的组件。 这样,如果遇到版本升级,就可能遇到意想不到的问题。

此外,官方 Docker 镜像中还包含了一层 Apache httpd,我并不喜欢这种套娃,还是直接暴露 FastCGI 接口比较优雅,并且能够任意修改 NGINX 配置。

安装与初始配置

依赖

源代码可以使用官方的 release 版本,则可以直接解压(如 /srv/mediawiki)。或者从 GitHub 等处 clone。如果使用 git 仓库,clone 后务必 checkout 一个稳定版本,并递归获取所有 submodule(git submodule update --init --recursive)。

MediaWiki 的第三方依赖不复杂,在 Debian / Ubuntu 上运行:

sudo apt install nginx-extras php-fpm php-xml php-intl php-mysql php-apcu imagemagick

此外,它还需要数据库支持,MySQL / PosgreSQL / SQLite 都可以。Git 版本还需要 PHP Composer 支持,可以参照 官方文档 安装,然后在源码目录下运行 composer install --no-dev 获得所有的依赖。

HTTP 服务器配置

MediaWiki 是一个典型的 PHP 应用,这里以 NGINX 配置为例(没有包含 overlay):

location ~* \.php$ {
  fastcgi_pass unix:/run/php/php-fpm.sock;
  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}

location @mediawiki {
  rewrite ^/([^?]*)(?:\?(.*))? /index.php?title=$1&$2 last;
}

location / {
  index index.php;
  try_files $uri $uri/ @mediawiki;
}

更完善的配置可以参考官方文档的 Manual:Short URL/Nginx

文件分离

考虑到上面提到的问题,即使不使用 Docker,也应该尽量避免污染源代码(无论是否使用 Git 版本)。主要需要处理的目录包括:

  • images:可以直接在源码外新建(需要给 www-data 用户写权限),并链接到源码目录中;
  • 其他的静态文件:使用 前一篇文章 中提到的 overlay 方法配置;
  • 插件与皮肤:在源码外新建同名目录存放,并逐个软链接到源码目录下的中,如 ./src/extensions/foo -> ./overlay/extensions/foo

安装

此时,访问 NGINX,应当可以看到 MediaWiki 的安装页面,通常来说依赖检查应该通过,填写各种信息(尤其是数据库),一路下一步即可(插件和皮肤土建都选上)。此时会得到一个 LocalSettings.php,下载后将其放入源码目录(推荐链接进去,以防备不慎覆盖)后,Wiki 应该就可以访问了。需要注意的是,生成的配置中,$wgServer 的值可能需要手工修改为服务的真实路径。

后续完善

在 Wiki 正常运行后,检查 Special:Version 页面就可以看到当前安装的插件和版本,这对于插件调试非常有用。

此时,可以进一步进行完善,让它看起来更像 Wikipedia

路径 rewrite

默认的路径是 /index.php?title=xxx&args=foo,看起来很丑,可以修改为 /wiki/xxx&args=foo 的形式。改动如下:

NGINX 的配置文件 @mediawiki 部分修改为:

location @mediawiki {
  rewrite ^/([^?]*)(?:\?(.*))? /index.php?title=$1&$2 last;
  rewrite ^/(.*)$ https://$server_name/wiki/$1 redirect;
}

LocalSettings.php 中增加 $wgArticlePath = "/wiki/$1";

其中 NGINX 配置的第二个 rewrite 用于将非 /wiki 路径也导向 MediaWiki,以提供友好的 404 消息,当然也可以不使用。

可视化编辑器

为了使得可视化编辑器 VisualEditor 和它的后端 Parsoid 正常工作,首先需要添加 NGINX 配置:

location /rest.php/ {
  try_files $uri $uri/ /rest.php?$query_string;
}

如果是 git 版本,还需要在 LocalSettings 最后添加:

wfLoadExtension( 'Parsoid', 'vendor/wikimedia/parsoid/extension.json' );
$wgVisualEditorParsoidAutoConfig = false;
$wgParsoidSettings = [
    'useSelser' => true,
    'rtTestMode' => false,
    'linting' => false,
];
$wgVirtualRestConfig['modules']['parsoid'] = [
    'url' => $wgServer . $wgScriptPath . '/rest.php',
];

此时,“编辑”应该能正常触发可视化编辑器。

移动端布局

默认的 MediaWiki 皮肤(Vector)对移动端并不友好,需要通过插件和额外的皮肤来实现。首先分别下载 MobileFrontend 插件Minerva Neue 皮肤extensionsskins 目录(如果在源码目录外,则需要链接进去)。如果从 git 下载,记得 checkout 与你安装的 MediaWiki 版本兼容的分支(官方插件通常名为 REL1_XX)。

而后,在 LocalSettings.php 最后添加:

wfLoadExtension( 'MobileFrontend' );
wfLoadSkin( 'MinervaNeue' );
$wgMFDefaultSkinClass = 'minerva';

即可启用响应式布局,并在移动设备上自动使用 Minerva 主题。

Logo 与 favicon

站点的 Logo 通过 $wgLogos 变量配置,具体可见 Manual:$wgLogos。注意位图一定要使用文档中说明的大小,否则无法正确工作。推荐使用 SVG 格式,就不需要生成多种大小的图片了。

关于 favicon(以及各种浏览器的 metadata),推荐使用一些工具(如 https://realfavicongenerator.net/)生成多种格式的图片和配置,并使用 overlay 的方式放置。此时通常需要在 HTML 的 <head> 标签中加入各类元数据,推荐使用 HeadScript 插件,安装方式如上。安装完后,在配置最后可添加相关信息,如:

wfLoadExtension( 'HeadScript' );
$wgHeadScriptCode = <<<'START_END_MARKER'
<link rel="apple-touch-icon" sizes="180x180" href="/images/icons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/icons/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/images/icons/safari-pinned-tab.svg" color="#743481">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
START_END_MARKER;

吐槽一下,PHP 的 raw string 写法真是太丑了。

元数据标签

OpenGraphMetaDescription2 这两个插件可以配合,在 <head> 中生成 OpenGraph 元数据,以便搜索引擎和其他工具的检索。

安装后,添加配置:

wfLoadExtension( 'OpenGraphMeta' );
wfLoadExtension( 'Description2' );
$wgEnableMetaDescriptionFunctions = true;

调试

考虑到隐私和配置泄露的风险,MediaWiki 默认的调试等级并不高。如果遇到问题,可以在配置中添加:

error_reporting(-1);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
$wgShowExceptionDetails = true;
$wgShowDBErrorBacktrace = true;
$wgShowSQLErrors = true;

可以显著增加 PHP-FPM 日志中和页面上报告错误的详细程度,通常对于调试很有用。