How do you take notes? How do you organize all the information you want to remember? If you’re anything like me, you’ve tried 100 different solutions. Evernote, OneNote, wikis, physical notebooks. You name it. Although I don’t think I’ve yet come to my ideal solution, my latest project gets me close.
TLDR: I made a Docker image that auto installs Dokuwiki and backs itself up every hour. Source: https://github.com/ericbarch/dockuwiki
An Ideal Solution
Before trying to build a solution that fit my needs, I first wanted to lay out exactly what I needed from a note taking solution. Here was my (not so) short list of things I wanted:
- Self hosted
- Good organization tools (folders, tags, etc)
- Non-proprietary storage format
- Auto backups
- Easy to deploy/maintain
- Encrypted access via multiple devices
- Mechanism for access when traveling without internet
Looking at the list (above) that I had written down, I realized I had rapidly whittled down the available potential solutions. Wanting something that was self hosted and non-proprietary, a wiki seemed like the obvious choice. I had used wikis in the past with good luck, but the hassle of setup and backups were often the pain point of using them. The open source Dokuwiki sprung back to mind.
Why does Dokuwiki make for an ideal solution? It’s designed to be self hosted, supports hierarchical organization, and stores pages as flat files via the local filesystem. This already hit most of the items on my list.
The challenges remaining: making setup simple, automatic backups, and remote access over something like HTTPS.
Making Setup A Breeze
It’s often said that a programmer’s greatest motivation is laziness. Or put another way: the desire to automate what you may have to do again in the future. I wanted to create a simple solution for downloading, installing, hosting, and backing up an instance of Dokuwiki. So what’s an easy way of doing that? For me, the tool for the job was Docker.
Luckily, Dokuwiki doesn’t require any sort of database. I really just needed some simple scripts to download the latest Dokuwiki, install it, serve it up via a webserver, and back itself up.
Dockerizing Dokuwiki was simple enough. But I also needed a simple and effective backup system. This is where I turned to Git. As Dokuwiki uses flat files to store the entire contents of the wiki, I simply needed to put the wiki directory under version control and automatically commit/push changes at a regular interval. As I also wanted a simple method to restore from backups, I configured the Docker image so that you can pass it a Git repo URL and have an existing wiki cloned and served up.
With the pieces laid out, I began work on the bash scripts and Dockerfile that would accomplish all of this. I called this assortment of scripts “Dockuwiki”; a combination of “Docker” and “Dokuwiki”.
What Dockuwiki Does
In order to meet my criteria for the (almost) perfect note taking solution, Dockuwiki does the following:
Build time (Dockerfile)
- Run time (Docker + bash scripts)
- Downloads the latest stable Dokuwiki
- Installs Nginx, PHP, and Git
- Configures Nginx/PHP
- Loads the bootstrap/backup bash scripts into the Docker image
Run time (Docker + bash scripts)
- Generate a fresh SSH key and print the public key to the Docker logs
- Clone the git repo URL provided as an ENV variable
- Extract a fresh install of Dokuwiki if the cloned repo is empty
- Set proper filesystem permissions (scripts are run as unprivileged users)
- Fire up Nginx
- Auto commit and push the Dokuwiki directory every hour
No need to re-invent the wheel here. Let’s Encrypt hands out free SSL/TLS certs, so I just needed to make Dockuwiki link in with this existing infrastructure. Lucky for me, there were already two projects that help accomplish this. The first being https://github.com/jwilder/nginx-proxy and the second https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion.
Just by firing up these two Docker images and adding the VIRTUAL_HOST, LETSENCRYPT_HOST, and LETSENCRYPT_EMAIL ENV variables to a Dockuwiki instance, you suddenly have a fully configured/automated HTTPS wiki deployment. Of course this does require that you are running your Docker containers on a host that can expose ports 80/443 via the net.
Wiki on the Go (Raspberry Pi/ARM Support)
The last item from my requirements list that I had not yet satisfied was using my wiki during the rare times I would be without internet access. The solution for this was quite simple. Raspberry Pi to the rescue!
Thanks to the hard work of these guys, it’s trivial to install Docker onto a Raspberry Pi. As I had created the original Dockerfile using a base Debian image, all I needed to do was copy my Dockerfile and use a Raspberry Pi ARM based image as the base. Resin.io is a pretty neat service that helps developers deploy code to embedded devices using Docker. Even better is that they’ve shared much of what they’ve done as open source. This meant it was as simple as changing my “FROM debian:8.6” line to “FROM resin/rpi-raspbian:jessie”. Then I copied the Dockuwiki files to my Raspberry Pi and executed the build. Success!
As Dockuwiki constantly backs itself up to a Git repo, it’s trivial to duplicate my wiki to my Raspberry Pi. When I know I’ll be without Internet, I simply shut down my primary Dockuwiki instance. Then I bring up Dockuwiki on my Raspberry Pi by pointing it to the same Git repo URL. Once my wiki is transferred and being hosted by my Pi, I shut it down and take it with me. By using a Raspberry Pi 3, I simply configure the integrated WiFi adapter to function in Access Point mode and now I can power up my Pi anywhere and connect to it wireless when I want to access my wiki. As soon as I’m back within range of the glorious net, I just fire up the Pi and allow it to commit/push any changes I’ve made back to the Git repo. Huzzah!
Conclusion / Give it a spin!
Although I’ve only had a chance to test Dockuwiki for a few weeks now, I’m much happier with this note taking solution than anything else I’ve used thus far. In fact I’m writing this post in my wiki, as I now prefer the editing and formatting tools I’ve become familiar with.
If you’re interested in taking Dockuwiki for a spin, you can find everything I put together on GitHub: https://github.com/ericbarch/dockuwiki I’ve included a fair bit of documentation in the README as well. As this is something I’m hoping to continue developing and improving as time goes on, feel free to open tickets in the issue tracker or send me feedback regarding the project.