Running my blog on NixOS
Today, I write about how I solved running a local jekyll server, specifically for GitHub pages, on NixOS, in order to view my blog posts before publishing.
My blog is powered by GitHub pages, which is a service offered by GitHub which allows users to create simple static websites. In addition to that, GitHub pages also provides an interface to create blogs - which is powered by Jekyll, a static site generator which is written in the Ruby programming language.
When creating blog posts, I normally like to view what they would look like on the actual site before publishing them. In order to do that, I set up a local server on my computer which recreates the blog in the same way that GitHub does it. This is something that I’ve gotten the hang of since I created the blog, since it was one of the first things I did as stated in my first blog post.
In general, the process is very simple:
- Install Ruby
- Run the command
gem install github-pages
- Start the server with the command
jekyll servein the directory where your site is.
However, I’m running NixOS. Of course, this means that the process is not “very simple”. The first thing that comes to mind when trying to tackle this is to see what Nix packages are available to me. Basically, NixOS is powered by Nix, the purely functional package manager. Packages can be browsed on the NixOS package browser, or using the built in
nix search command. Using the online browser,
Attempt 1: Install Jekyll
I discover that jekyll is one of the available packages available on Nix! What a relief - I don’t have to go through the effort of installing Ruby, I can just get straight to the point and run the
jekyll serve command.
jekyll to my
configuration.nix file and rebuild the config. I run
jekyll serve. Error! Cannot find the required plugins! It appears that GitHub pages using custom plugins in addition to jekyll which enable support for fancy styling and creating RSS feeds. Unfortunately, if I want to install those plugins, I have to install Ruby. Oh well, it seems that jumping the gun wasn’t the right method.
Attempt 2: Install Ruby
No problem, I just install Ruby. Luckily for me, Ruby is also available on Nix. I add
ruby to my
configuration.nix file and rebuild the config. I run
gem install github-pages and sit back as it gets to work. Not even 5 seconds later, an error has appeared in my terminal. Apparently, one of the Ruby gems called “ffi” produces an error when installing! No problem, we can just install it manually via Nix. I add
libffi to my
configuration.nix file and rebuild the config.
Unfortunately, this doesn’t fix the issue - I now have to deal with a new bug: one of the Ruby gems, in particular “nokogiri”, requires the C header file zlib.h. At this point, I’m beginning to lose my patience. I go to Nix. I add
zlib to my
configuration.nix file. What’s the error this time? Nokogiri can’t find zlib.h. I research a little more and find out that sometimes, using a dev build of zlib can resovle this issue. I add
zlib.dev to my
configuration.nix file. What’s the error this time? Nokogiri can’t find zlib.h.
Evidently, we have to try a completely new approach.
Attempt 3: Stack Overflow
Of course, a programmer’s #1 (or #0 if you’re zero-indexed) resource for help like this is good old Stack Overflow. I search my problem and find someone has the exact same issue: Building GitHub pages locally using Nix. And when I mean “exact same issue”, I mean EXACTLY what I’m looking for:
- They’re on NixOS trying to build GitHub pages
- They’re having the same issue that I am when trying to install the nokogiri gem
- They’ve tried a lot of stuff. They’ve tried everything I’ve tried.
I follow the results in the solution which has a tick, implying that the solution solved the issue that the original person stated. Now, their solution involves creating a Gemfile (Some Ruby related file, I barely know what it is myself), then create some Gemfile.lock file, then use some fancy Nix thing called “bundix” then create some derivations for some things, then …
Luckily for me, the person that answered the question linked to the blog post that had the full detailed solution. I decided to take a quick look - maybe it would explain things a little better. Oh boy. Not only did it have creating Gemfiles, it included creating custom
.nix files to create jekyll environments. Now, I’ve only been using this operating system for a few days and I am NOT AT ALL comfortable with creating
.nix files yet. Sure, someone reading this might be like “ugh, just create the file - it’ll solve your problems” and sure, that someone may be correct. However, this was not a path I was willing to follow.
Attempt 4: Give up
At this point, I had basically given up. There was no hope. Guess I won’t be debugging my blog on my local machine. I was still trying again and again to install zlib for the chance that I can get Attempt 2 to work, but there was no hope. That was, until I found the NixOS FAQ webpage. It so happens that on this page, one of the questions were:
I installed a library but my compiler is not finding it. Why?
The answer explains that only applications should be installed into user profiles, whereas libraries are to by used within the
nix-shell. Now, I knew that this shell existed, but never really took any notice of it, considering
configuration.nix seemed to be sufficient. However, this question seemed relevant. I was trying to build GitHub pages by using the
gem install command.
Attempt 4.5: Use
This was definitely my last hope. Use this
nix-shell command. How bad could it be? Just to be EXTRA safe, I make sure to run
nix-shell -p zlib ruby as opposed to just
nix-shell -p ruby. Can’t afford to forget that zlib. Never again. It opens up the Nix shell with the relevant libraries (Ruby and zlib) and I run the all-so-famous
gem install github-pages command.
Surprisingly, it works! First time! After this successfully works, I use
bundle exec jekyll serve to start up the server (the bundle command is part of Ruby) and have finally been able to work on my blog on NixOS. After reading the rest of the NixOS FAQ page on the issue, its solution is basically the same as whatever Attempt 3 had, except much simpler and easier to understand. Perhaps I’ll figure out how to use
.nix files in the near future.