Migrating to Nikola


Last Modified:


This site is now built using ox-hugo and the Hugo static site generator.

This blog originally started a few years back on Blogspot. Google has since begun making a whole host of changes that I’m not a big fan of – in particular, eliminating Google Reader. This was my notice to begin seeking alternative places to host my email and other services.

The idea of a static site generator for my blog appeals to me. You can host your site anywhere and move it at a moment’s notice. The server you’re hosting it on is more secure since there is no need for databases, PHP, NodeJS, etc. Even backups are really easy to make using version control software (I’m partial to Joey Hess' Git-Annex).

There are loads of static site generators out there. I started off with the Pelican site generator. This is a really nice piece of software, but I was never quite confident in how everything worked. I migrated my content over and stuck with it for a few months. I went through a laptop reinstall and was never able to get it quite back to where I wanted it to be. This is probably not Pelican’s fault. In addition, I wasn’t happy with the way image galleries worked.

Since my Pelican setup wasn’t acting quite right, I began looking at some other options. I wanted to stay with Python based generators since I’m most comfortable in that environment. One engine that stuck out was Nikola. I was impressed by how quick it was to get something up and running. The builds are faster than they were with Pelican and I think the workflow is a bit easier to grok.

I’m attempting to detail how I’ve set things up here.


I tend to travel fairly often for work, so I want to be able to edit my blog on any of my computers – personal laptop, Microsoft Surface Pro. This means that I need to use a DVCS for storing the files. I setup Git + Git-Annex to do this.

Git-Annex is a neat add-on to Git that allows you to efficiently store binary files. It has some very nice features like tracking the location of the files across multiple computers. This means you don’t need to have every file on every computer.

The git-annex assistant is a really neat piece of software that synchronizes folders automatically using ssh+rsync. It can be used to implement a self-hosted and version controlled Dropbox.

My git repository is hosted on a small computer that I’m running as a home server. Git-annex was already installed and added to my path.

I first created a directory on the server and initialized it as a git repository. Then I initialized it as a git-annex repository.

mkdir /media/backupdrive/blogdir
cd /media/backupdrive/blogdir
git init
git-annex init

The annex on the backup drive is periodically encrypted and sent to somewhere in the cloud for offsite backup. I may detail this setup further some other time.

I then cloned that repository to my local machine. I want to be able to use the git-annex assistant to synchronize the files between my local computer and the server.

git clone ssh://user@backupmachine/path/to/repository local_repository
git-annex sync

One thing to be careful about with the git-annex assistant is that it hoovers up any file in that directory and puts it in the annex. This sets the file permission to read only, moves the file into an objects directory and symlinks the file back to the correct location. This is fine for many types of files, but I don’t want this to happen to any of the text files that the posts are stored in. I would prefer that only things like pictures and videos get put into the annex.

To prevent this, I made some changes to my .git/config file. Under the annex section, I added a largefiles line. This excludes all Markdown, ReStructuredText, css, js, txt, or Emacs Org files from being added to the git-annex. In addition, it prevents the output files from being put into the annex.

    uuid = 00000000-0000-0000-0000-000000000000
    version = 5
    fscknudge = true
    autoupgrade = true
largefiles = not (include=*.org or include=*.org_archive or include=*.txt or include=*.tex or include=*.rst or include=*.md or include=*.js or include=*.css or include=*.py or include=listings/* or include=output/* or include=*.plugin)

In addition, I added a number of entries to my .gitignore:


I’m ignoring the output directory altogether in git. I’m not sure this is a good idea, but I’d prefer to not have an overly large repository.

You can either periodically run git-annex sync or run the git-annex assistant to automatically synchronize your changes.

Nikola installation

Installing Nikola is nice and easy. Follow the instructions in the Nikola Handbook

Next, I created the blog on my local machine using the nikola init --demo mysite command in the repository I previously created. This created a small demo site in the directory. The default settings are pretty good. I added a few filters to optimize the images that I’m uploading – jpegoptim and optipng. In addition, I defined a deploy command to set the correct permissions and to rsync the output folder to my server in the cloud.

Blog posts are created in a directory called “posts”. You can create a new post by running the commane nikola new_post. This will create the appropriate headers for the ReStructuredText file.

I also replicated the Nikola installation on one of my backup servers. I can write the content on any machine that I have git installed on, push the content to the backup server, build and deploy it to my webhost.

Next projects

  1. Enable the serving of pre-gzipped files on my webserver.
  2. Build a plugin to display GPX tracks from my runs.
  3. Write some actual content.