Skip to content

Poor Man's Continuous Delivery

About this site

This website is built by mkdocs, which is a static site generator. It uses a markdown file for each page, with a yaml file as the main options file. Mkdocs then builds the site, which converts it into html, css and whatnot. Then you then can point Nginx, Apache or another http server at the directory where you output the built site, and boom, website. Each markdown file is another page, and rearranging your site is as easy as moving the markdown files between directories.

You can also run mkdocs serve, which will build the site, and use a python http server to serve it. It will detect changes in the source files, and then rebuild and reload any open pages. This serve command is very explicitly not supported for anything but local development, so don't get any ideas about using it in production. In production, either use mkdocs build and Nginx or another http server, or you could use Github/Gitlab site, or something like Netlify.

There are also themes available that you can download. I am also using the mkdocs-material theme, although with a couple of tweaks, look in the overrides directory. I am overriding the footer section to remove the build with mkdocs material message, and another override to load the web fonts from here, instead of loading them from google fonts. I used this page to get the font files I needed from google quickly and without too much pain.


How I develop and deploy

To develop this site, I first locally make changes, and preview the changes with mkdocs server, going to localhost:8000 in a browser. When I am satisfied, I commit the changes with git, and git push to Gitlab.

Gitlab then pushes the changes to the machine I host the website on. I have repository mirroring setup to do this. I had SSH setup already on the machine, so I setup the mirroring to run over ssh. The url is ssh:// + username to push to + @full.hostname + /path/to/git/repo, so like ssh://user@naoh.host/path/to/repo. Then detect the host keys, and select public key as authentication method. Then, after it is enabled, click the button to copy the SSH public key, and put it in the authorized_keys file for the user you want to mirror to. Also, run git config --local receive.denyCurrentBranch updateInstead on the system you are mirroring to. Then whenever you push to gitlab, it will also push to the mirroring system.

Now this does not completely take care of automating the deployment, since the docs still need to be built. Fortunately, this can be taken care of really easily with git hooks, specifically the post-receive hook. Hooks are git executing a file with a specific name in the .git/hooks directory. The post-receive hook gets run after the the repository gets files pushed to it. It is pretty simple, see below.

#!/bin/bash
git -C /path/to/repo pull
/venv/path/to/python3 -m mkdocs build -c -f /path/to/repo/mkdocs.yml -d /path/to/build/directory

There are still some quirks with this setup, such as the revision date plugin is failing to get the git revision date when mkdocs is executed by the hook, and Gitlab mirroring over SSH was broken for a while, but overall it works fairly well.

I then point nginx at the build directory, like this. To setup, remove the second server block, and everthing managed by certbot, then run certbot --nginx, and when prompted do select the redirect.

server {
        server_name naoh.host;

        location / {
                root /path/to/build/directory/;
                index index.html;
        }

        error_page 404 404.html;

    add_header X-Download-Options noopen always;
    add_header X-Permitted-Cross-Domain-Policies none always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Strict-Transport-Security "max-age=31536000" always;


    listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/naoh.host/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/naoh.host/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = naoh.host) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        listen [::]:80;

        server_name naoh.host;
    return 404; # managed by Certbot
}


Last update: 2020-07-12