How to create a Wiki with Bourne to Blog

Published: 2021-01-24 | Last Updated: 2021-03-19 | ~13 Minute Read

Table of Contents

Context

I have been looking for a way of documenting things that is easy to maintain, portable and resilient. There are many amazing wiki tools out there however, most that I came across either had too many features, making them bloated for my taste, or had too many requirements / dependencies thus complicating the installation process and maintenance.

Since the inception of Bourne to Blog I have been trying to add features that make it a flexible tool and decided that it would be fun to use it to make a simple wiki system.

Wiki Requirements

This wiki is by no means full featured, however it does have the following traits:

Infrastructure

I’ll only need two main servers:

I could use the same box as the git source however separating the git repository can help make it more resilient (think of using Github which is more resilient than say a local server would be).

Server Setup

So without further delay, I got started with setting the wiki up.

These are the steps that we need to take:

Configure the OS

I will be using Slackware as the base OS, there shouldn’t be much surprise there.

I’ll be using the 14.2 stable version since I don’t need any additional functionality or features from the Slackware current release.

I performed a clean Slackware installation for this, I included the A, AP, D, K, L, N, T, TCL, X, XAP, XFCE package series.

Now time to update the base system like so:

Uncomment the mirror of your liking from /etc/slackpkg/mirrors, and then execute the following:

root@wiki:~ # slackpkg update gpg
root@wiki:~ # slackpkg update
root@wiki:~ # slackpkg upgrade-all

Once that is done I’ll install the sbopkg binary from the sbopkg webpage:

root@wiki:~ # cd /tmp
root@wiki:/tmp# wget https://github.com/sbopkg/sbopkg/releases/download/0.38.1/sbopkg-0.38.1-noarch-1_wsr.tgz 
root@wiki:/tmp# installpkg sbopkg-0.38.1-noarch-1_wsr.tgz 
Verifying package sbopkg-0.38.1-noarch-1_wsr.tgz.
Installing package sbopkg-0.38.1-noarch-1_wsr.tgz:
PACKAGE DESCRIPTION:
# sbopkg  (SlackBuilds.org Package Browser)
#
# Sbopkg is a command-line and dialog-based tool to interact with the
# SlackBuilds.org repository, a collection of third-party SlackBuild
# scripts to build Slackware packages.
#
# Homepage   :  https://www.sbopkg.org
# Development:  https://github.com/sbopkg/sbopkg
#
Executing install script for sbopkg-0.38.1-noarch-1_wsr.tgz.
Package sbopkg-0.38.1-noarch-1_wsr.tgz installed.

Now run the sbopkg command, type c for create and run an initial sync.

Create a system user that will be in charge of the wiki related operations, I used the adduser command:

root@wiki:~# adduser
Login name for new user []: wiki
User ID ('UID') [ defaults to next available ]: 
Initial group [ users ]: 
Additional UNIX groups:
Users can belong to additional UNIX groups on the system.
For local users using graphical desktop login managers such
as XDM/KDM, users may need to be members of additional groups
to access the full functionality of removable media devices.
* Security implications *
Please be aware that by adding users to additional groups may
potentially give access to the removable media of other users.
If you are creating a new user for remote shell access only,
users do not need to belong to any additional groups as standard,
so you may press ENTER at the next prompt.
Press ENTER to continue without adding any additional groups
Or press the UP arrow key to add/select/edit additional groups
:  

Home directory [ /home/wiki ] 
Shell [ /bin/bash ] 
Expiry date (YYYY-MM-DD) []: 
New account will be created as follows:

---------------------------------------
Login name.......:  wiki
UID..............:  [ Next available ]
Initial group....:  users
Additional groups:  [ None ]
Home directory...:  /home/wiki
Shell............:  /bin/bash
Expiry date......:  [ Never ]

This is it... if you want to bail out, hit Control-C.  Otherwise, press
ENTER to go ahead and make the account.
Creating new account...
Changing the user information for wiki
Enter the new value, or press ENTER for the default
        Full Name []: 
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Changing password for wiki
Enter the new password (minimum of 5 characters)
Please use a combination of upper and lower case letters and numbers.
New password: 
Bad password: too short.  
Warning: weak password (enter it again to use it anyway).
New password: 
Re-enter new password: 
passwd: password changed.
Account setup complete.

Alternatively you can use the useradd command.

Install NGINX

Nginx is simple to install via sbopkg. Apache comes already installed with Slackware, but I prefer NGINX.

Simply search for it in the sbopkg menu and then select Process. This should download, compile and install it on the system.

Configure NGINX

First I enable the service and start it:

root@wiki:~# chmod +x /etc/rc.d/rc.nginx 
root@wiki:~# /etc/rc.d/rc.nginx start
Starting Nginx server daemon...

And now I make sure that it starts on system boot, that is done by adding these lines to the /etc/rc.d.rc.local file:

# Start NGINX:
if [ -x /etc/rc.d/rc.nginx ]; then
  /etc/rc.d/rc.nginx start
fi

With this we can test access to the default NGINX page:

Default NGINX Page

The web root directory for NGINX is configured in /etc/nginx/nginx.conf, but we can add a separate server block via an include file thanks to the include /etc/nginx/conf.d/*.conf directive in the /etc/nginx/nginx.conf file.

Next we create wiki.conf in /etc/nginx/conf.d and then populate it like so:

root@wiki:~ # touch /etc/nginx/conf.d/wiki.conf

This is the final content of a very simple configuration:

root@wiki:~# cat /etc/nginx/conf.d/wiki.conf
server {
        listen 80;
        server_name 192.168.2.5;
        root /var/www/html;
        index index.html;
}

We’re almost ready to start making changes to the files in the /var/www/html/ directory.

First delete the default NGINX pages and allow the wiki user’s group users privileges over the /var/www/html/ directory:

root@wiki:~ # rm /var/www/html/*
root@wiki:~ # chmod 775 /var/www/html/

Since we will be building all .html files dynamically, we only need to add two directories manually. Create the css and the img directory:

wiki@wiki:~$ mkdir /var/www/html/img /var/www/html/css

Install Bourne to Blog

I’ll be using Bourne to Blog in order to build the wiki on every push to the git server, this will make updating the wiki much simpler.

I simply followed the install instructions over at github

root@wiki:/tmp# wget https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/blog -P /usr/local/bin/
--2021-01-24 02:57:53--  https://raw.githubusercontent.com/grokkingnix/bourne-to-blog/master/blog
Resolving raw.githubusercontent.com... 151.101.48.133
Connecting to raw.githubusercontent.com|151.101.48.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11798 (12K) [text/plain]
Saving to: '/usr/local/bin/blog'

blog           100%  11.52K  --.-KB/s    in 0.001s       

2021-01-24 02:57:53 (17.1 MB/s) - '/usr/local/bin/blog' saved [11798/11798]

root@wiki:/tmp# chown wiki:users /usr/local/bin/blog 
root@wiki:/tmp# chmod +x /usr/local/bin/blog

Install the discount library via sbopkg as well by running sbopkg then search for it in the Search option, select it and Process, Install. The discount program, like NGINX, does not have any additional dependencies, so it should take just a moment to install. This is what you should see after installation is complete:

+++++++++++++++++++++++++++++++++++++++++++
SUMMARY LOG
Using the SBo repository for Slackware 14.2
Queue Process:  Download, build, and install

discount:
  MD5SUM check for discount-2.2.7.tar.gz ... OK
  Building package discount-2.2.7-x86_64-1_SBo.tgz ... OK
  Installing package discount-2.2.7-x86_64-1_SBo.tgz ... OK

+++++++++++++++++++++++++++++++++++++++++++

###########################################
          Queue process complete!
###########################################

Bourne to Blog is going to be used only for building the data locally and provide its output to NGINX. We don’t yet have the files on the server so we’ll be skipping the Bourne to Blog configuration until the repository is cloned.

Configure Git

On the remote server (NGINX web server) I’ll be configuring access to the Git repository over SSH with the use of SSH keys.

I executed the following:

wiki@wiki:~ $ mkdir .ssh
wiki@wiki:~ $ chmod 700 .ssh/
wiki@wiki:~ $ cd .ssh
wiki@wiki:~/.ssh$ ssh-keygen -t ed25519

Now add the id_ed25519.pub key contents to the git server. Depending on whether you are using github, gitlab, gitea or just git this process may differ a bit. In my case I’m using Gitea, so I added the public key in Profile and Settings > Settings > SSH / GPG Keys > Add Key.

Once the key is added clone the repository on the NGINX server:

wiki@wiki:~$ git clone gitea@giteadomain.com:wiki/wiki.git
Cloning into 'wiki'...
remote: Enumerating objects: 50, done.
remote: Counting objects: 100% (50/50), done.
remote: Compressing objects: 100% (43/43), done.
remote: Total 50 (delta 9), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (50/50), 9.57 KiB | 979.00 KiB/s, done.
Resolving deltas: 100% (9/9), done.

We now have the latest contents of the wiki repository on our NGINX server in the /home/wiki path:

wiki@wiki:~$ ls
wiki/

You can organize your wiki any way you prefer, here is the structure of the wiki system I’m creating as an example:

wiki@wiki:~$ tree wiki/
wiki/
|-- css
|   `-- wiki-style.css
`-- img
|   `-- image.png
`-- pages
    |-- footer.html
    |-- header.html
    `-- index.md

Now that the CSS and IMG files are available on the system we can manually copy them to the /var/www/html directory:

wiki@wiki:~ $ cp /home/wiki/wiki/css/wiki-style.css /var/www/html/css
wiki@wiki:~ $ cp /home/wiki/wiki/img/image.png /var/www/html/img

Copying the CSS file once should suffice, should any changes be made to the wiki-style.css file it will have to be manually copied again to the /var/www/html path. As for the images under the img folder I’d like to avoid having to manually copy images as wiki articles are created so the sync script will also handle this since this is not something that Bourne to Blog does, I may add that feature in the future.

Configure Bourne to Blog

With Bourne to Blog installed and Git configured we can now configure the Bourne to Blog variables. The final configuration for the user provided variables in /usr/local/bin/blog is the following:

# Start editing
############

# Define global script variables
# Source directory that contains the original files to process
SOURCE_DIR=/home/wiki/wiki/pages/

# Directory to store html files created by the buildWebsite function
WORK_DIR=/var/www/html/

# Blog posts path on the public server
BLOG_DIR=/blog/path/on/your/webserver

# Full path to the header file. This value will be ignored if the -h flag is provided
HEADER_FILE=/home/wiki/omega-wiki/pages/header.txt

# Full path to the footer file. This value will be ignored if the -f flag is provided
FOOTER_FILE=/home/wiki/omega-wiki/pages/footer.txt

# Variables for SFTP connection
USER=ftpusername
HOST=ftp.host.name.com
IDENTITY_FILE=/home/username/.ssh/identity/file

# The format/extension that the files to process are in
SOURCE_EXTENSION=*.md

As you can see variables related to the public web server are not provided, and are left with the default values.

Note: At the time of writing I also needed to comment out a line in the script since there is an access error for the SFTP identity file because it’s not provided. I will fix this as soon as possible, so I hope this is not a necessary step in the near future. The line is the following:

#OUTPUT=`(echo "$REMOTE_LS"; echo quit) | sftp -b - -i "$IDENTITY_FILE" "$USER"@"$HOST"`

From the script comments this line is used for the following:

# Define the OUTPUT variable with the output from the REMOTE_LS variable value over the SFTP connection on the web server

Git Sync Script

The best way to sync the repository with a remote build server is with the use of Git’s hooks feature, which allows git to call a URL on the remote server on every push and that in turn triggers events on the remote server. In this use case however I’d like to keep my NGINX box not publicly reachable over HTTP so I’ll take a different approach.

I will be creating a bash script that checks for changes to the remote repository and when changes are seen it triggers a git pull and a rebuild of the entire wiki.

This is the final script:

wiki@wiki:~$ cat sync-script.sh
#!/bin/bash
# This script will sync the local git repository with the remote git upon changes and trigger a full build of the wiki

# Infinite while loop
while true
do 
        # Define variables
        LOCAL_REPOSITORY=/home/wiki/wiki

        # Enter the local repository folder
        cd $LOCAL_REPOSITORY

        # Have git fetch the remote git main branch
        git fetch

        # Determine if there are differences between the remote main branch and the local main branch
        if [ `git diff master origin/master | wc -l` != 0  ]

        # If the local repository is different from the remote repository
        then

                # Have git pull the contents of the remote repository
                git pull

                # Build the wiki with Bourne to Blog
                /usr/local/bin/blog -b

                # Copy all images from the local repository img folder to the NGINX web server's css folder
                /usr/bin/cp /home/wiki/wiki/img/* /var/www/html/img/
        fi
done

This simple script will rebuild the entire wiki upon detecting a change using Bourne to Blog.

We will do something similar to what we did with NGINX to make sure the script runs on system boot. I added the following to the /etc/rc.d/rc.local file:

# Run the sync-script.sh script
sudo -u wiki bash /home/wiki/sync-script.sh &

This will ensure that we start polling for changes to the remote git repository upon system boot.

Wiki CSS

The wiki-style.css file has some modifications from the CSS used on this blog to present the information in a more wiki-like way. There are two main changes:

Adding an aside

To add an aside to any article you simply have to add content between an <aside> and <section> HTML tags:

<aside>
<section>

## Technologies used in this Wiki

- [Markdown](https://daringfireball.net/projects/markdown/)
- [NGINX](https://www.nginx.com/)
- [CSS Grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout)

</aside>
</section>

You will also need to let CSS know where your main article content ends so the aside can be formatted properly, you simply have to add a closing </main> tag before your aside starts:

</main> 
<aside>
<section>

## Technologies used in this Wiki

- [Markdown](https://daringfireball.net/projects/markdown/)
- [NGINX](https://www.nginx.com/)
- [CSS Grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout)

</aside>
</section>

Wiki Menu

The modified CSS also includes two classes that allow you to indent sub-menu items. You can easily use these two classes by editing the header file that you use to create your wiki. Add the indent1 and indent2 classes to your menu items like so:

<nav>
<img src="/img/image.png">
    <a href="/index.html">Wiki Index</a>
    <a href="/category1.html">Category 1</a>
    <a class="indent1" href="/sub-category1.html">Sub-category 1</a>
    <a class="indent1" href="/sub-category2.html">Sub-category 2</a>
    <a class="indent2" href="/sub-category3.html">Sub-category 3</a>
    <a href="/category2.html">Category 2</a>
    <a href="/category3.html">Category 3</a>
    <a href="/category4.html">Category 4</a>
</nav>

Because of the way that Bourne to Blog builds the wiki, your menu will be updated on all pages when you update your header file and build the wiki.

This will render your wiki with the updated menu and an aside on the top right hand side of the page:

Sample Wiki Image

Workflow

Now that the system is ready we can test our wiki. The workflow would be the following:

  1. Update a file from our local system’s git repository and push the changes to the main git repository
  2. Have a colleague update a file from their local system’s git repository and push the changes to the main git repository
  3. Visit your NGINX web server IP / domain address and see both of your changes live in the wiki

Conclusion

There we have it, a simple wiki system that we can easily manage via git with little to no server maintenance. Make sure to update your system and take care of any NGINX security fixes that come out, but other than that there is not much else to do on the NGINX web server. Due to Git’s collaboration focus we can now have any number of members contribute to the creation of the wiki.

This simple wiki system is possible thanks to the flexibility of the Bourne to Blog tool and a bit of additional bash scripting. This wiki system can be easily customized to fit your specific use case, I encourage you to create your own wiki with Bourne to Blog, enjoy!