Jump to content

MediaWiki Setup Guide Portainer-Docker-251215-00: Difference between revisions

From Game in the Brain Wiki
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 10: Line 10:
1. Docker & Docker Compose
1. Docker & Docker Compose


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


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


2. Portainer CE (Community Edition)
2. Portainer CE (Community Edition)


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


3. Domain & Cloudflare Setup
3. Domain & Cloudflare Setup


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


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


4. NGINX Reverse Proxy
4. NGINX Reverse Proxy


    Nginx Proxy Manager (Docker Setup): <nowiki>https://nginxproxymanager.com/guide/#quick-setup</nowiki> (This is the standard GUI-based Nginx used in Docker stacks)
    Nginx Proxy Manager (Docker Setup): [https://nginxproxymanager.com/guide/#quick-setup&#x20;(This&#x20;is&#x20;the&#x20;standard&#x20;GUI-based&#x20;Nginx&#x20;used&#x20;in&#x20;Docker&#x20;stacks) <nowiki>https://nginxproxymanager.com/guide/#quick-setup</nowiki> (This is the standard GUI-based Nginx used in Docker stacks)]


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


== 2. Host Folder Setup ==
== 2. Host Folder Setup ==
Line 48: Line 48:


=== docker-compose.yml ===
=== docker-compose.yml ===
  <services:
  services:
   mediawiki:
   mediawiki:
     image: mediawiki
     image: mediawiki
Line 78: Line 78:
  volumes:
  volumes:
   230912_images:
   230912_images:
   230912_db:</code>
   230912_db:


== 4. First-Time Setup Wizard ==
== 4. First-Time Setup Wizard ==
Line 86: Line 86:


* '''Host:''' database
* '''Host:''' database
* '''Name:''' wiki
* '''Name:''' mediawiki
* '''User:''' wiki
* '''User:''' mediawiki
* '''Password:''' wiki
* '''Password:''' mediawiki


# Complete the wizard and '''Download LocalSettings.php''' to your computer.
# Complete the wizard and '''Download LocalSettings.php''' to your computer.
Line 98: Line 98:
  docker run --rm --entrypoint tar mediawiki -c -C /var/www/html/extensions . | tar -x -C /opt/stacks/mediawiki/extensions
  docker run --rm --entrypoint tar mediawiki -c -C /var/www/html/extensions . | tar -x -C /opt/stacks/mediawiki/extensions
'''Download Mermaid (External Extension):'''
'''Download Mermaid (External Extension):'''
  <code>cd /opt/stacks/mediawiki/extensions
  <cd /opt/stacks/mediawiki/extensions
  git clone <nowiki>[https://github.com/SemanticMediaWiki/Mermaid.git]</nowiki>(<nowiki>https://github.com/SemanticMediaWiki/Mermaid.git</nowiki>) Mermaid</code>
  git clone <nowiki>https://github.com/SemanticMediaWiki/Mermaid.git</nowiki> Mermaid</code>
Verify the folder content: You should see a mix of default extensions and Mermaid:
Verify the folder content: You should see a mix of default extensions and Mermaid:


Line 164: Line 164:
Your wiki is now live at '''<nowiki>https://wiki.gi7b.org</nowiki>''' with VisualEditor and Mermaid enabled!
Your wiki is now live at '''<nowiki>https://wiki.gi7b.org</nowiki>''' with VisualEditor and Mermaid enabled!


== 8. List of Extensions ==
== 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 '''<code>info@gi7b.org</code>'''
* Authentication must work with '''Gmail / Google Workspace'''
* No local SMTP server, no Docker mail container
 
Success criterion (important to remember):<blockquote>MediaWiki explicitly says '''“email sent”''' — not just “no error”.</blockquote>
----
 
=== 2. App Password (Google side) ===
 
=== Where it lives ===
 
* '''Google Account settings''', not Gmail UI  <nowiki>https://myaccount.google.com</nowiki>
 
* → Security → App passwords
 
=== Preconditions ===
 
* 2-Step Verification '''must be enabled'''
* App type: '''Mail'''
* Device: '''Other''' (e.g. <code>MediaWiki wiki.gi7b.org</code>)
 
=== 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 <code>SMTP 535 5.7.8 BadCredentials</code>
* MediaWiki misleadingly says “invalid characters”
 
'''This was one of the key fixes.'''
----
 
=== 3. Real email vs alias (authentication reality) ===
 
=== Core rule (non-negotiable) ===
<blockquote>'''SMTP login must use a real mailbox, not an alias.'''</blockquote>Examples:
{| class="wikitable"
!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. <code>admin@gi7b.org</code>, <code>justin@gi7b.org</code>)
* '''Sender address''' → can be <code>info@gi7b.org</code>
 
This is how Google enforces auditability and DMARC integrity.
----
 
=== 4. “Send as” using Cloudflare Email Routing (alias setup) ===
Your <code>info@gi7b.org</code> 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 <code>info@gi7b.org</code>
* 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):
 
* <code>username</code> = '''real mailbox'''
* <code>password</code> = '''App Password, no spaces'''
* <code>wgPasswordSender</code> = alias (<code>info@gi7b.org</code>)
* SMTP host = <code>smtp.gmail.com</code>
* TLS/SSL enabled
 
Once all three conditions were true:
 
# real mailbox for login
# app password without spaces
# 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:<blockquote>'''“email sent”'''</blockquote>
 
=== This is the success criterion ===
Not:
 
* “no error”
* “page didn’t crash”
 
But explicitly:<blockquote>'''MediaWiki confirms the email was sent'''</blockquote>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 <code>justinaquino</code>
* assign <code>sysop</code> + <code>bureaucrat</code>
* confirmed by:
 
=== Important nuance ===
 
* Some helper scripts (<code>showUserRights</code>, <code>version</code>) are missing in newer MediaWiki builds
* That '''does not invalidate''' the promotion
* UI verification (<code>Special:UserRights</code>, <code>Special:CreateAccount</code>) 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 <code>LocalSettings.php</code>:
# 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 ==
[https://www.youtube.com/watch?v=4xYbqbabTwI Youtube: Introduction to MediaWiki: Wikipedia's extensions (Part 2)]
[https://www.youtube.com/watch?v=4xYbqbabTwI Youtube: Introduction to MediaWiki: Wikipedia's extensions (Part 2)]
# '''[[wikipedia:Special:Version|The installed Extensions of Wikipedia]]'''
# '''[[wikipedia:Special:Version|The installed Extensions of Wikipedia]]'''
#
#

Latest revision as of 16:24, 16 December 2025

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';

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