Grav

Official Documentation

Requirements

# apt install nginx php php-fpm php-gd php-apcu php-yaml php-zip php-xml php-mbstring php-curl unzip

Download grav

Make sure the directory you want to use is owned by your webserver user. (www-data on debian)
# chown www-data:www-data -R /var/www

With included admin client sudo -u www-data wget https://getgrav.org/download/core/grav-admin/1.7.32

TODO

Packages: php-mysql php-sqlite3

Theme Learn2 Customisations

Fix for wonky sidebar

With the default configuration, using jquery-scrollbar, there are issues with extremely long subtopics making the bar not scroll all the way to the bottom.
My workaround is adding the following CSS to custom.css in the theme's css directory.

.highlightable {
  overflow: auto;
}

Code copy don't copy # or $

This needs to be modified in js/learn.js
Here's the change as well as the surrounding code.

    // clipboard
    var clipInit = false;
    $('code').each(function() {
        var code = $(this),
            text = code.text();

        if (text.length > 5) {
            if (!clipInit) {
                var text, clip = new Clipboard('.copy-to-clipboard', {
                    text: function(trigger) {
                        text = $(trigger).prev('code').text();
                        // NOTE custom stuff to strip # or $ from the beginning of my inline command blocks
                        return text.replace(/^[\$\s\#\$]{1,4}/gm, '');
                        // original code
                        return text.replace(/^\$\s/gm, '');
                    }
                });

Custom theme based on Learn2

$ sudo -u www-data /var/www/wiki-grav/bin/plugin devtools new-theme

You'll be asked a few questions next
Important: when asked to choose an option, choose inheritance
With this, an installed theme can be selected as a base

Nginx config

server {
    server_name DOMAIN_NAME;

    # Security / XSS Mitigation Headers
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    listen *:443 ssl http2; #set ipv6 address
    ssl_certificate_key /etc/acme-sh/DOMAIN_NAME/key.pem;
    ssl_certificate /etc/acme-sh/DOMAIN_NAME/cert.pem;

    index index.html index.php;

    ## Begin - Server Info
    root /var/www/grav-admin;
    ## End - Server Info

    ## Begin - Index
    # for subfolders, simply adjust:
    # `location /subfolder {`
    # and the rewrite to use `/subfolder/index.php`
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    ## End - Index

    ## Begin - Security
    # deny all direct access for these folders
    location ~* /(\.git|cache|bin|logs|backup|tests)/.*$ { return 403; }
    # deny running scripts inside core system folders
    location ~* /(system|vendor)/.*\.(txt|xml|md|html|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
    # deny running scripts inside user folder
    location ~* /user/.*\.(txt|md|json|yaml|yml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
    # deny access to specific files in the root folder
    location ~ /(LICENSE\.txt|composer\.lock|composer\.json|nginx\.conf|web\.config|htaccess\.txt|\.htaccess) { return 403; }
    ## End - Security

    ## Begin - PHP
    location ~ \.php$ {
        # Choose either a socket or TCP/IP address
        fastcgi_pass unix:/var/run/php/php-fpm.sock;
        # fastcgi_pass unix:/var/run/php5-fpm.sock; #legacy
        # fastcgi_pass 127.0.0.1:9000;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    }
    ## End - PHP
}

server {
    if ($host = DOMAIN_NAME) {
        return 301 https://$host$request_uri;
    }
    listen *:80; #set ipv6 address
    server_name DOMAIN_NAME;
    return 404;
}