Writing Documentation for Sysadmins using Markdown and Gitlab CIlinux sysadmin markdown continuous integration mkdocs en
I figured I’d do a little writeup on how I write documentation at work, using Vim, Markdown, MkDocs and GitLab CI. I’ve been using this workflow and toolset for quite a while now and after a long search for something that works well for me, I feel like I’ve found just the thing. Personally I was mostly looking for something to write my own notes / personal knowledgebase with, but this software stack scales really well for teams.
What I wanted
- I wanted to write in an editor of my choice (which would be Vim, but that shouldn’t matter - I simply wanted no tool-specific editors)
- I wanted to write in Markdown, because it’s a great language that’s easy to read and write, widely compatible and has all the features I need
- I wanted to write plain Markdown files without any front matter, tags or anything else that’s specific to one renderer. That would lock me in (maybe not completely, but it would require some work to migrate to a different tool) and would be annoying as my main modus operandi is to look at the files in a text editor
- I wanted a way to look at the files as rendered Markdown, because it’s just nicer to read
- I wanted a way to structure the articles, with a clickable TOC or something similar
What I tried and didn’t like
Installing a “Markdown preview” plugin for my text editor and having rendered Markdown displayed in that. I tried a few of these plugins, but none did it quite right - one would mess up the encoding because it didn’t support UTF-8, another one would only work 75% of the time, and a lot more plugins did not support client-side rendering and sent everything I wrote i.e. to the GitHub API, which then returned GitHub-flavoured Markdown. Not acceptable for tinfoil-hat-reasons
Using an editor with built-in Markdown rendering. For a brief period I wrote my docs in Visual Studio Code, which instantly renders Markdown in a separate tab. I’m generally not a fan of such bloated software (it might not actually be bloated, but it very much felt like it in comparison to Vim), but with the Vim plugin, VS Code is bearable. Still, switching to a different editor made things more complicated and writing Markdown in Vim and reading the files in VS Code just made no real sense.
Using a Wiki. Seems like an abvious choice, right? Many Wikis support Markdown editing and I tried a few of them out. Unfortunately it just felt like too much clicketyclick to get something done. None of the wikis had good keyboard shortcuts and I always had to mess around in the browser with the mouse to do things. The closest I got was using CodiMD, which is technically not a Wiki, but its editor is nice. Still though, not what I wanted
What I ended up doing
At one point, I found the fantastic MkDocs - a static site generator written in Python, specifically made for documentation. Being a fan of static site generators, I gave it a look and saw that MkDocs can in fact work with “plain” Markdown files (or, to be exact, plain text files with Markdown in them) without any tool-specific front matter in them, which sets it apart from most other SSGs. (Honorable mention for Sphinx, which seems nice, but only supports ReStructured Text instead of Markdown.) It also has a bunch of built-in themes, although many of them don’t work with my workflow because they expect just one file for each “site” - themes with a classic “top bar Navigation” break immediately when you hit them with 100+ files. So I went with the ReadTheDocs theme, which does the job perfectly. It even has a client-side search, which is convenient.
So nowadays, my docs just live in a flat directory filled with .md files. I’ve made a bunch of rules for myself so it wouldn’t get too messy - for instance: make a new file for each
- Software program (by product name),
- Topic (like ‘Keyboards’ for everything related to them),
- Server (named after its hostname) and
- Customer to write down information about them.
Everything smaller than this does not deserve its own file and goes in a Topic file along with other things related to it.
Whenever I edit something, I simply commit and push to master, and then the Gitlab Runner starts building the sites. Here is what my
.gitlab-ci.yml looks like:
image: python:alpine before_script: - pip install mkdocs - "mkdocs new ." - "echo 'site_name: Cool name goes here' >> mkdocs.yml" - "echo 'theme: readthedocs' >> mkdocs.yml" - mv *.md docs/ pages: script: - mkdocs build -v - mv site public artifacts: paths: - public only: - master
As you can see, the CI initializes a new MkDocs project and adds the configuration file, so I don’t have to keep it in my documentation folder - only the .gitlab-ci.yml is needed there, so it’s all nice and clean. After that, the site is built and deployed to Gitlab Pages which is simply a static site hosting service, coincidentally very similar to Github Pages. We happen to have Pages installed on our Gitlab instance at work, otherwise I could use really any other webserver with about zero configuration as I am just serving HTML. With Pages, you have Authentication built-in and you don’t have to deal with SSH keys and such, so that’s good if you’re lazy.