How This is Setup

This is setup using mdBook. It’s hosted as a repository on github. I set up a pipeline in concourse to build, check that things work, and then push new versions once things are set up.

TL;DR, check out these instructions at the bottom

Repository Layout

This is a simple mdbook, the actual content files is under src/. is missing, because I have tooling to automatically generate one automatically.


The pipeline1 is relatively simple:

  • Check for new pushes to master
  • Generate a for the book.
  • Build the book (using this mdbook docker image)
  • Test that the generated book isn’t broken (mostly verify the links work) using html-proofer, via this docker image.
  • rsync the updated book to the server hosting the contents.

Server Setup

The server hosting this is a linode VPS. It gets deployed to/managed via an ansible playbook. The current setup is pretty bad/full of bad patterns, but needless to say that playbook manages setting up nginx, getting letsencrypt set up, and configuring nginx to serve the static files for this repository.

On Sol, the repository containing this playbook is located at ~/workspace/Apps.

Offline/Development Setup

For making changes and doing a local preview (or just simply running locally), the following setup is recommended/required:

  • Rust/Cargo: Install rustup
  • mdbook-generate-summary: cargo install mdbook-generate-summary will get you an out-of-date version. The CI uses a dockerimage for this, but that docker image is not yet set up for local usage. The “best” way to get an up-to-date version is to download the source, and run cargo install --path .. Which isn’t the best way to distribute software. 🤷🏻‍♀️
  • mdbook: cargo install mdbook


mdbook-generate-summary will build a file for you. This way, you don’t have to maintain one.

mdbook watch will build your sources, watch for any changes to the src/ directory, and serve up the book on localhost:3000.

I do this for my work repository, which I want to keep separate from my personal stuff.


After noticing an embarrassing amount of spelling errors on this (one of the drawbacks to editing this mostly in vim), I spent time looking into how to spellcheck markdown files.

Regardless, I’ve used markdown-spellchecker (which I discovered via this article) to locally spellcheck this, using this command:

mdspell --ignore-acronyms --ignore-numbers --en-us "**/*.md"

Future Work

  • On a per-section basis, add other lines to show up for all pages in that section (e.g. I want everything in my flying section to have the “This is for my own use and is not flight instruction” disclaimer).


Here’s what I did to stand up additional versions of this repository (e.g. a separate one for work, the coz-e build).

Machine Setup

mdBook requires rust to use, so we first install rust. This is done via rustup.

  • curl --proto '=https' --tlsv1.2 -sSf | sh

Next, we install mdbook itself: cargo install mdbook.

Additionally, there’s a bunch of extra tooling I use. I won’t go through them in detail, but here’s the following commands to install everything:

cargo install mdbook-generate-summary mdbook-api mdbook-chapter-path mdbook-git-atom mdbook-section-validator

This is all that’s required to setup the machine.

You can optionally install the validation tooling (markdown-spellcheck, html-proofer) with the following commands:

npm i -g markdown-spellcheck
gem install html-proofer

Setting up the Repository

To set up the repository itself, you need to create a book.toml file, an initial src/ file, and (if not using mdbook-generate-summary) a src/ file.

For reference, this repository’s book.toml file is:

title = "Knowledge Repository"
authors = ["Rachel Brindle"]
description = "Rachel's Digital Garden"

preprocess = ["links", "index"]

curly-quotes = true
no-section-label = true
mathjax-support = true
additional-css = ["css/custom.css"]
git-repository-url = ""
edit-url-template = "{path}"


hide_invalid = false
invalid_message = "🚨 Warning, this content is out of date and is included for historical reasons."

after = ["section-validator"]
strict = true

after = ["chapter-path"]
base_url = ""
article_preview_lines = 10

Building the Repository

If you want to view the repository locally, you can use mdbook build, and open book/index.html in your web browser. If you’re doing interactive work, then you can use mdbook watch.

Note that if you’re using mdbook-generate-summary, you should run that every time you create, delete, or move a page.


The pipeline definition looks like this:

- name: rsync-resource
  type: docker-image
    repository: mrsixw/concourse-rsync-resource
    tag: latest

  # Knowledge Wiki
  - name: knowledge_source
    type: git
      uri: https:/
      branch: master
  # Task info
  - name: tasks
    type: git
      branch: master
  # Book Server
  - name: book_server
    type: rsync-resource
      server: {{book_server}}
      base_dir: /usr/local/var/www/knowledge/
      user: you
      disable_version_path: true
      private_key: {{BOOK_SERVER_PRIVATE_KEY}}

  - name: build_knowledge
      - aggregate:
        - get: knowledge_source
          trigger: true
        - get: tasks
      - task: spellcheck
          platform: linux
            type: docker-image
              repository: tmaier/markdown-spellcheck
              tag: latest
            path: sh
            - -c
            - |
              cd knowledge_source
              mdspell --ignore-acronyms --ignore-numbers --en-us "**/*.md"
            dir: ""
          - name: knowledge_source
      - task: generate_summary
          platform: linux
            type: docker-image
              repository: younata/mdbook-generate-summary
              tag: latest
            path: sh
            - -c
            - |
              cd knowledge_source
              mdbook-generate-summary src/ -v
              cp -r * ../generated/
            dir: ""
          - name: knowledge_source
          - name: generated
      - task: mdbook
        file: tasks/tasks/mdbook.yml
          code: generated
          concourse: tasks
          book: book
      - task: test
        file: tasks/tasks/html_proofer.yml
          code: book
          concourse: tasks
        params: {DOMAIN: ""}
      - put: book_server
        params: {sync_dir: book}

Last updated: 2021-11-15 19:52:51 -0800