Prep Work Before Install

In NixOS, due to how it organizes files/packages, it cannot run Ruby Gems in the typical way, so you will run into issues with the gems installing right via Bundler.

Go into the folder that you want to run/install Jekyll in and type the following:

nix-shell -p bundler

This will get you in an environment that provides bundler for use of getting a Gemfile and associated Gemfile.lock built.

If it is a new installation for Jekyll (without a Gemfile), we need to create a Gemfile and make it writeable:

bundle init
chmod +w Gemfile

Add jekyll to the Gemfile:

bundler add jekyll

We need to make sure it doesn’t try to install the Gems when adding gems:

bundler package --no-install --path vendor

Now we need to generate a gemset.nix that will allow installations of gems:

bundix

We should then delete the unneeded vendor folder since it would have put the files in the nix store anyway:

rm -rf vendor

There is a much easier way to automate this whole task (if you have a Gemfile already). We can put everything in one line of code that will allow bundler to update and updating of the gemset.nix file as well:

nix-shell -p bundler -p bundix --run 'bundler update; bundler lock; bundler package --no-install --path vendor; bundix; rm -rf vendor'

Install of Jekyll and Nix-Shell Setup

Now we need to create a file that will allow us to then compile the Jekyll and its dependencies when launching nix-shell. Now create a default.nix file in the folder of the Jekyll site (make up a name for the your-package, doesn’t have to exist anywhere):

with (import <nixpkgs> {});
let env = bundlerEnv {
    name = "your-package";
    inherit ruby;
    gemfile = ./Gemfile;
    lockfile = ./Gemfile.lock;
    gemset = ./gemset.nix;
  };
in stdenv.mkDerivation {
  name = "your-package";
  buildInputs = [env bundler ruby];
}

Now we need to run nix-shell (it should by default use default.nix, if it doesn’t, run nix-shell default.nix). Run the following to get into the environment:

nix-shell

If we are trying to start fresh without any config, we need to run a special command to generate the default config and files without bundler:

jekyll new --force --skip-bundle .

After running that, when trying to run Jekyll, you may get an error about it not having packages like minima. We need to get out of nix-shell (run exit). The easiest thing to update everything would just be to run that one liner (should take care of updating everything):

nix-shell -p bundler -p bundix --run 'bundler update; bundler lock; bundler package --no-install --path vendor; bundix; rm -rf vendor'

If you changed the default theme from the default theme in the config, you may need to add it to the Gemfile your self or do a nix-shell -p bundler --run 'bundle add <package-name>'. This same line would be the easiest way to add new gems to the Gemfile. You would then need to rerun the one liner.

Even creating a small bash script could be handy to run:

#!/usr/bin/env bash

nix-shell -p bundler -p bundix --run 'bundler update; bundler lock; bundler package --no-install --path vendor; bundix; rm -rf vendor'

echo "Ready for nix-shell"

Autorunning Jekyll Tasks in Nix-Shell

If you want Jekyll to automatically run the web server each time you go into nix-shell, change your default.nix to resemble this:

with (import <nixpkgs> {});
let
  env = bundlerEnv {
    name = "your-package";
    inherit ruby;
    gemfile = ./Gemfile;
    lockfile = ./Gemfile.lock;
    gemset = ./gemset.nix;
  };
in stdenv.mkDerivation {
  name = "your-package";
  buildInputs = [env ruby];

      shellHook = ''
      exec ${env}/bin/jekyll serve --watch
    '';
}

You can make other .nix files that could automate different tasks. One good example would be if you are using algolia for searching. You can change the exec ${env}/bin/jekyll serve --watch to exec ${env}/bin/jekyll algolia to have it index your posts and name it a different file like algolia.nix. To run it, you would type nix-shell algolia.nix.

Other Things to Note

As of writing this blog, Nokogiri 1.11 and up has an issue with trying to compile within the nix-shell environment. Changing the Gemfile to require 1.10.10, gem "nokogiri", "~> 1.10.10" and then clearing out the Gemfile.lock and rerunning bundler and bundix should fix it.

If you use shell.nix in your development workflow, you will need to run nix-shell default.nix instead of just running nix-shell.

Useful References