On-The-Fly Mediawiki Deployments with Docker

Last Updated: 2022-10-06

Setting Up New Web Services Doesn’t Have To Suck

Sometime in the past I wrote a quick guide on Setting up an NGINX reverse proxy for Docker, in conjunction with the release of Piminder. Truth is, though… that system had been the cornerstone of my service architecutre generally for probably a year or two before that, even.

This guide presupposes, at a minimum, that you are using Docker and docker-compose to permit containerization. Parts of it also presuppose that you’re using the reverse proxy setup I describe above. There are a lot of good reasons to do things that way, and this isn’t the place to describe them in full; however, the main reason we’re using it for this guide is to simplify addressing the new containers you’re creating.

Why a Wiki?

A brief note on the best reasons to use a wiki (over, say, a static-site-generator or a simple text file), in my experience, are the following:

  • Online Editing of the site is possible via an authenticated user. You can restrict this signficantly through the MediaWiki config, and I do for most of my wikis, to the point where you may be the only authorized editor.
  • Depending on configuration this could also be online-as-in-the-internet, allowing you access to the data from anywhere.
  • Data organization is the literal function of the wiki concept. The use of catagories is the most obvious example, but the wiki also takes care of quite a bit of data organization through metadata that allows for simple discovery, like searching and direct linking of related concepts.
  • By extension, redlinks are an extremely useful work-organization tool. You can define a link that goes to a page yet to be created, and there is a build-in reporting page to list all such links. Thereafter, just go in and create it.

Yes, it’s overkill for many tasks, inappropriate for others, and downright goofy in yet other states. But for some things, like technical documentation and worldbuilding exercises, it can be really hard to beat. I’m even considering creating a documentation wiki for PETI (the obstacle, of course, is in keeping the wiki up to date). There’s a reason the format has become so popular.

Cons and Considerations

There are two main cons to using a wiki to do this kind of work:

  • Something that has to be hosted incurs a cost. This will either be a real cost (in terms of a paid service to host the thing) or a labour cost (in terms of your work to maintain it). Not everything is necessarily worth that. Most of the labour cost is isolated in the launching of the wiki for the first time. It’s not necessarily an appropriate way to track a shopping list. It might be great for your DnD campaign, but less than useful for the novel you’re writing.
  • Backing these up is non-trivial. I am going to describe below a process by which you could potentially do it. Fortunately I’ve never had cause to recover from such a failure. Remember, your backups only exist after you’ve tested them.

If either of those considerations gives you pause, consider if a full wiki is really appropriate here. Github repos have a wiki-like functionality built into them (I don’t like it, but they do). Some projects don’t need something this elabourate. Most of my wikis are, admittedly, toys - worldbuilding projects or notes for TTRPG campaigns, which by and large amount to the same thing.

Enough Preamble: First-Time Boot

I have not disuaded you, and you really want to host a wiki. Good for you! If you are using the ngnix reverse proxy method I alluded to at the top of the guide, start by registering the subdomain or domain you want to host the wiki at; without it, the letsencrypt-helper image will struggle to get a certificate for you, and you could have trouble connecting to the wiki later. I do this 10-15 minutes before I turn the wiki on; usually by just amending a domain record I already own to have a new subdomain. Glory to the junk drawer domain!

This deployment uses two docker containers per wiki; one to host the actual mediawiki application and one to host a mariadb instance. Make sure you have all the relevant resources available to do this. Don’t try to cram it into an already over-taxed old laptop hidden under the couch. Ask me how I know!

For my money, this sort of thing therefore becomes easiest to manage via docker-compose, which of course will call for a bit of docker-compose.yaml, to be placed anywhere you feel is relevant:

# MediaWiki with MariaDB
# Designed for use with a ngnix-revproxy setup like this one: https://www.arcanalabs.ca/guides/revproxy.html
version: '3'
services:
  some-mediawiki:
    image: mediawiki
    restart: always
    expose:
      - 80
    links:
      - wisteria-database
    volumes:
      - /var/www/html/images
      # After initial setup, download LocalSettings.php to the same directory as
      # this yaml and uncomment the following line and use compose to restart
      # the mediawiki service
      #- ./somewiki-LocalSettings.php:/var/www/html/LocalSettings.php
      - ./extensions/TemplateStyles:/var/www/html/extensions/TemplateStyles
    environment:
      VIRTUAL_HOST: wiki.somedomain.tld
      #VIRTUAL_PORT: 8080
      LETSENCRYPT_HOST: wiki.somedomain.tld
      LETSENCRYPT_EMAIL: admin@somedomain.tld
  some-mediawiki-database:
    image: mariadb
    restart: always
    environment:
      # @see https://phabricator.wikimedia.org/source/mediawiki/browse/master/includes/DefaultSettings.php
      MYSQL_DATABASE: my_wiki
      MYSQL_USER: wikiuser
      MYSQL_PASSWORD: -somepassword-
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
    volumes:
      - somewiki_database:/var/lib/mysql
      - ./somewiki-db:/var/drops/db
networks:
  default:
    external:
      name: nginx-proxy
volumes:
  somewiki_database:

After firing up the compose file above, navigate to wiki.somedomain.tld (or whatever you’ve configured - you may have to edit your hosts file as well for internal hosts if you have as much jank in your setup as I do), and you’ll get walked through a confgurator. At the end of the configuration process, you’ll be asked to download a file, LocalSettings.php.

For the most part the installer itself will walk you through the configuration process in-browser, but here’s a couple of points I want to call out:

  • The database will ABSOLUTELY break if you do this wrong. If that happens, you should get pretty verbose error output. Just google the error message and you’ll get shot in the right direction - usually, to rerun the installer. It’s worth noting that rerunning the installer doesn’t always nuke the wiki content. I’ve had some pleasurable experiences where I thought an entire project was lost only to recover it in the final moments.
  • You absolutely, positively, absolutely have to save LocalSettings.php when it tells you to.

Configuring Persistence Properly

You can now open the docker-compose.yml file in your editor and uncomment the line under volumes that mounts LocalSettings.php; just make sure you’ve put the file where you’re telling it you put it first (the notation is .hostMachinePath:/var/www/html/LocalSettings.php).

You may have also noted that we created a directory that’s mounting into the mariaDB container. This is going to be useful for you for creating data dumps, using your automation tool of choice to dump the full my_wiki database from MariaDB into that location. My chosen methodology was a terribly hacked-together python script. You may want something more robust, and honestly, it’s not worth my culpability to share you exactly what I did.

Once you are taking regular database dumps (which you should then back up somewhere else) and the localsettings.php persistence is… persistant… you’re fully configured. Get cracking on your wiki!

I hope you found this guide as useful toward your first foray into this topic as I'll be finding it to my next need to repeat the process. Much like the output of my other projects, the guides collection offered at Arcana Labs is freely available knowledge. If you enjoyed this guide and want to see more guides like it, have a trip over to the support page. See an error? Something unclear? Contact me!