Jump to content

MediaWiki Setup Guide Portainer-Docker-251215-00

From Game in the Brain Wiki

MediaWiki Setup Guide (Portainer & Docker)

This guide documents how to deploy, configure, and secure a MediaWiki instance using Portainer and Docker Compose. Designed as a general tutorial for any user, it walks through the process of setting up a wiki from scratch. It covers initial deployment, resolving common extension folder issues, and applying production configurations (using wiki.gi7b.org as the example domain).

Reference: Official MediaWiki Docker Image https://hub.docker.com/_/mediawiki

1. Prerequisites

Before starting, ensure you have:

1. Docker & Docker Compose

    Installation (Linux/Windows/Mac): https://docs.docker.com/engine/install/

    Docker Compose Standalone (if needed separately): https://docs.docker.com/compose/install/

2. Portainer CE (Community Edition)

    Docker Standalone Install Guide: https://docs.portainer.io/start/install-ce/server/docker/linux

3. Domain & Cloudflare Setup

    How to Register a Domain with Cloudflare: https://developers.cloudflare.com/registrar/get-started/register-domain/

    Cloudflare Tunnel (Cloudflared) Setup Guide: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/create-remote-tunnel/

4. NGINX Reverse Proxy

    Nginx Proxy Manager (Docker Setup): https://nginxproxymanager.com/guide/#quick-setup (This is the standard GUI-based Nginx used in Docker stacks)

    Nginx Official Docker Image (for raw configuration): https://hub.docker.com/_/nginx

2. Host Folder Setup

Create a dedicated folder for your stack on the Docker host. This path is critical as it will store your configuration and extensions.

# Run on host terminal 
sudo mkdir -p /opt/stacks/mediawiki
sudo mkdir -p /opt/stacks/mediawiki/extensions
cd /opt/stacks/mediawiki

3. Deployment (Portainer / Docker Compose)

Use the following YAML configuration.

In Portainer:

  1. Go to StacksAdd stack.
  2. Name it mediawiki.
  3. Paste the configuration below into the Web editor.
  4. Click Deploy the stack.

docker-compose.yml

services:
  mediawiki:
    image: mediawiki
    container_name: mediawiki
    restart: always
    ports:
      - 8595:80
    depends_on:
      - database
    volumes:
      - 230912_images:/var/www/html/images
      # EXTENSIONS: Mounts host folder to container (Requires "Magic Command" step below)
      - /opt/stacks/mediawiki/extensions:/var/www/html/extensions
      # CONFIG: Uncomment the line below AFTER generating LocalSettings.php
      # - /opt/stacks/mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php:ro

  database:
    image: mariadb
    container_name: mediawiki-db
    restart: always
    environment:
      MYSQL_DATABASE: mediawiki
      MYSQL_USER: mediawiki
      MYSQL_PASSWORD: mediawiki
      MYSQL_ROOT_PASSWORD: mediawiki
    volumes:
      - 230912_db:/var/lib/mysql

volumes:
  230912_images:
  230912_db:

4. First-Time Setup Wizard

  1. Open http://localhost:8191 (or your server IP:8191).
  2. Follow the prompts. When asked for Database Settings, use:
  • Host: database
  • Name: mediawiki
  • User: mediawiki
  • Password: mediawiki
  1. Complete the wizard and Download LocalSettings.php to your computer.

5. Fixing Extensions (The "Magic Command")

Crucial Step: Because we mounted a volume to /extensions, the container's default extensions (VisualEditor, WikiEditor, etc.) are hidden. We must copy them from the image to the host.

Run this on your Host Terminal:

docker run --rm --entrypoint tar mediawiki -c -C /var/www/html/extensions . | tar -x -C /opt/stacks/mediawiki/extensions

Download Mermaid (External Extension):

<cd /opt/stacks/mediawiki/extensions
git clone https://github.com/SemanticMediaWiki/Mermaid.git Mermaid

Verify the folder content: You should see a mix of default extensions and Mermaid:

ls -F /opt/stacks/mediawiki/extensions/

Output should look like this:

AbuseFilter/    CiteThisPage/      Echo/         Interwiki/      Mermaid/          PageImages/        README          SpamBlacklist/          TextExtracts/       WikiEditor/
CategoryTree/   CodeEditor/      Gadgets/    Linter/      MultimediaViewer/  ParserFunctions/  ReplaceText/      SyntaxHighlight_GeSHi/  Thanks/
CheckUser/      ConfirmEdit/      ImageMap/   LoginNotify/  Nuke/              PdfHandler/        Scribunto/      TemplateData/          TitleBlacklist/
Cite/            DiscussionTools/  InputBox/   Math/       OATHAuth/          Poem/            SecureLinkFixer/  TemplateStyles/      VisualEditor/

6. Configuring LocalSettings.php

Move the downloaded LocalSettings.php to /opt/stacks/mediawiki/LocalSettings.php.

# in linux terminal
sudo nano /opt/stacks/mediawiki/LocalSettings.php

Edit the file (sudo nano /opt/stacks/mediawiki/LocalSettings.php) and make the following changes:

A. Set the Custom Domain

Find the $wgServer line (around line 30) and change it to your actual domain:

## The protocol and server name to use in fully-qualified URLs 
$wgServer = "https://wiki.gi7b.org";

B. Add Permissions & Extensions

Paste this block at the very bottom of the file to enable security and extensions.

# -----------------------------------------------------------------------
# CUSTOM PERMISSIONS & EXTENSIONS
# -----------------------------------------------------------------------

# 1. SECURITY: Prevent anonymous editing and account creation
$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['createaccount'] = false;

# 2. BUNDLED EXTENSIONS (Included in Docker image)
wfLoadExtension( 'WikiEditor' );
wfLoadExtension( 'VisualEditor' );
wfLoadExtension( 'CodeEditor' );
wfLoadExtension( 'SyntaxHighlight_GeSHi' );
wfLoadExtension( 'Cite' );
wfLoadExtension( 'InputBox' );
wfLoadExtension( 'Scribunto' );
wfLoadExtension( 'AbuseFilter' );
wfLoadExtension( 'Gadgets' );
wfLoadExtension( 'ParserFunctions' );
wfLoadExtension( 'Interwiki' );

# 3. EXTERNAL EXTENSIONS (Must be manually downloaded to /extensions folder)
wfLoadExtension( 'Mermaid' );

# 4. VISUALEDITOR CONFIGURATION
# Enable by default for everyone
$wgDefaultUserOptions['visualeditor-enable'] = 1;
# Allow VE to work in Docker containers (Fixes "Error contacting Parsoid")
$wgVisualEditorParsoidForwardCookies = true;

# 5. LUA CONFIGURATION (Required for Scribunto)
$wgScribuntoDefaultEngine = 'luastandalone';

C. Adding additional Extensions (WIP - waiting till v1.46 is released this does not work)

go to the HOST PC running the docker mediawiki. you can ssh into it. as an example lets add Collections and PdFBook these two extensions allow you 1: Create a Personal Collection of topics, and 2: Compose a Book - this way the wiki can easily generate a book.

on the terminal or ssh you can:

cd /opt/stacks/mediawiki/extensions

Then in the extensions directory

git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/Collection

you should see Collections directory when you

ls Collection

then repeat the same steps doing the for PDFbook

git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/PdfBook

then check if the folder appears

ls PdfBook

Then go to localsettings.php and edit it.

sudo nano /opt/stacks/mediawiki/LocalSettings.php

then you will see:

# 3. EXTERNAL EXTENSIONS (Must be manually downloaded to /extensions folder)
wfLoadExtension( 'Mermaid' );

add the other extensions and it should appear like this:

# 3. EXTERNAL EXTENSIONS (Must be manually downloaded to /extensions folder)
 wfLoadExtension( 'Mermaid' );
wfLoadExtension( 'Collection' ); // wait till version 1.46
wfLoadExtension( 'PdfBook' ); // or ElectronPdfService

7. Apply Changes

  1. Mount the settings: In Portainer, go to the Stack Editor and uncomment the LocalSettings.php line.
  2. Update the Stack: Click "Update the stack".
  3. Run Database Update: Run this command to initialize tables for the new extensions: docker exec -it mediawiki php maintenance/update.php --quick

Your wiki is now live at https://wiki.gi7b.org with VisualEditor and Mermaid enabled!

8. Email Configuration and Admin Set up


1. Email goal (what we were trying to achieve)

  • MediaWiki must be able to send email reliably
    • account confirmation
    • password reset
    • notifications
  • Emails should appear as coming from info@gi7b.org
  • Authentication must work with Gmail / Google Workspace
  • No local SMTP server, no Docker mail container

Success criterion (important to remember):

MediaWiki explicitly says “email sent” — not just “no error”.


2. App Password (Google side)

Where it lives

  • Google Account settings, not Gmail UI https://myaccount.google.com
  • → Security → App passwords

Preconditions

  • 2-Step Verification must be enabled
  • App type: Mail
  • Device: Other (e.g. MediaWiki wiki.gi7b.org)

Critical detail (easy to miss, caused real failure)

Google shows the password like this:

But MediaWiki / PHP must receive it without spaces:

If you keep the spaces:

  • Google returns SMTP 535 5.7.8 BadCredentials
  • MediaWiki misleadingly says “invalid characters”

This was one of the key fixes.


3. Real email vs alias (authentication reality)

Core rule (non-negotiable)

SMTP login must use a real mailbox, not an alias.

Examples:

Address type Can authenticate?
Real Gmail / Workspace mailbox ✅ Yes
Alias (Send mail as) ❌ No
Forward-only address ❌ No

So:

  • Login / username → real mailbox (e.g. admin@gi7b.org, justin@gi7b.org)
  • Sender address → can be info@gi7b.org

This is how Google enforces auditability and DMARC integrity.


4. “Send as” using Cloudflare Email Routing (alias setup)

Your info@gi7b.org address was not a real mailbox.

It was configured as an alias using Cloudflare Email Routing.

That’s fine — and correct — for sending.

Reference (as requested, naked link only):

https://www.cloudflare.com/developer-platform/products/email-routing/

Key idea:

  • Cloudflare routes mail for info@gi7b.org
  • Gmail authenticates as the real mailbox
  • MediaWiki sends “from” the alias

This combination is valid and common.


5. Final MediaWiki SMTP configuration (conceptual)

$wgEnableEmail = true;
$wgEnableUserEmail = true;
$wgSMTP = [
  'host'     => 'ssl://smtp.gmail.com',
  'IDHost'   => 'wiki.gi7b.org',
  'port'     => 465,
  'auth'     => true,
  'username' => 'admin@gi7b.org',   // REAL mailbox
  'password' => 'APP_PASSWORD_OF_ADMIN',
];
$wgPasswordSender = 'info@gi7b.org'; // ALIAS is fine here

What mattered conceptually (not copying exact secrets):

  • username = real mailbox
  • password = App Password, no spaces
  • wgPasswordSender = alias (info@gi7b.org)
  • SMTP host = smtp.gmail.com
  • TLS/SSL enabled

Once all three conditions were true:

  1. real mailbox for login
  2. app password without spaces
  3. alias only used for sending

→ Google accepted authentication.


6. Testing and defining “success”

What failed before

  • Account confirmation attempted
  • Gmail rejected auth
  • MediaWiki showed:

What changed after fixes

  • Retried account confirmation
  • MediaWiki returned:

    “email sent”

This is the success criterion

Not:

  • “no error”
  • “page didn’t crash”

But explicitly:

MediaWiki confirms the email was sent

That tells you:

  • SMTP auth works
  • Mailer pipeline is functional
  • Future account/password flows will work

7. Final step: making your account admin

Once email was stable, we finalized control.

What we did

  • Used the MediaWiki maintenance runner
  • Promoted your existing account
  • Forced promotion because the user already existed

Command (conceptually):

  • promote justinaquino
  • assign sysop + bureaucrat
  • confirmed by:

Important nuance

  • Some helper scripts (showUserRights, version) are missing in newer MediaWiki builds
  • That does not invalidate the promotion
  • UI verification (Special:UserRights, Special:CreateAccount) is canonical

8. Final mental model (so this sticks)

  • Email
    • Gmail = SMTP server
    • MediaWiki = SMTP client
    • App Password = machine credential
    • Alias ≠ login identity
  • Security
    • Real mailbox authenticates
    • Alias is presentation only
    • Cloudflare handles routing, not auth
  • Success
    • “Email sent” is the only signal that matters
    • Admin rights are confirmed via UI, not missing CLI helpers

9. Protect your account from brute force (real defenses)

MediaWiki already has some protection, but we’ll harden it properly.

Layer 1 — Enable built-in throttling (do this)

Add to LocalSettings.php:

# Login attempt throttling
$wgRateLimits['user']['login'] = [ 5, 60 ];   // 5 attempts per minute
$wgRateLimits['ip']['login']   = [ 20, 300 ]; // 20 attempts per 5 minutes

This alone stops most brute-force scripts.

10. List of Extensions

Youtube: Introduction to MediaWiki: Wikipedia's extensions (Part 2)

  1. The installed Extensions of Wikipedia