Run Jekyll locally on NixOS
Setup
- PC: Lenovo T590
- OS: NixOS 24.05
- Jekyll theme: Chirpy
Summary
Run Jekyll locally on NixOS.
Method 1 [Deprecated]
Go to the root directory of your Jekyll site and start an interactive shell containing the packages Jekyll
and bundler
.
1
nix-shell -p jekyll bundler
Install the gems listed in Gemfile
.
1
bundle install
Start the Jekyll site locally.
1
bundle exec jekyll serve
When I switched from NixOS 23.11 to NixOS 24.05, his method no longer worked. Instead, I got the following error:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Configuration file: /home/wout/Documents/WoutSwinkels.github.io/_config.yml
Source: /home/wout/Documents/WoutSwinkels.github.io
Destination: /home/wout/Documents/WoutSwinkels.github.io/_site
Incremental build: disabled. Enable with --incremental
Generating...
Conversion error: Jekyll::Converters::Scss encountered an error while converting 'assets/css/jekyll-theme-chirpy.scss':
Broken pipe
/home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:61: warning: Could not start dynamically linked executable: /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/ext/sass/dart-sass/src/dart
/home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:61: warning: NixOS cannot run dynamically linked executables intended for generic
/home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:61: warning: linux environments out of the box. For more information, see:
/home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:61: warning: https://nix.dev/permalink/stub-ld
------------------------------------------------
Jekyll 4.3.4 Please append `--trace` to the `serve` command
for any additional information or backtrace.
------------------------------------------------
/home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:90:in `write': Broken pipe (Errno::EPIPE)
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:90:in `block in write'
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:89:in `synchronize'
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/connection.rb:89:in `write'
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/dispatcher.rb:92:in `send_proto'
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/channel.rb:59:in `send_proto'
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/host.rb:220:in `send_message'
from /home/wout/.local/share/gem/ruby/3.1.0/gems/sass-embedded-1.79.3/lib/sass/compiler/host.rb:79:in `block in compile_request'
...
As pointed out by midchildan, this fails because a downloaded dependency, sass-embedded-1.79.2
, runs a native binary, which almost never works on NixOS, as explained in the Packaging/Binaries section of the NixOS wiki. Initially, I considered reverting to the Jekyll package from NixOS 23.11, but that seemed like a lazy approach and not future-proof. It would feel like ductaping things together. The proper solution is to use bundix to create Nix packages from Gemfiles. Before we do that, let me explain why the previous method no longer works.
If we look at the Jekyll package in NixOS 23.11, and more specifically at the Gemfile.lock
then you can see that the jekyll-sass-converter
is version 2.2.0
, and it uses sassc
, which is a wrapper around libsass
, a now deprecated library. As a result, sassc
is also deprecated.
Why does this matter? Well, let’s check the Gemfile.lock
of the Jekyll package in NixOS 24.05. The jekyll-sass-converter
is now version 3.0.0
, and as stated in its documentation, it now uses sass-embedded
since sassc
is deprecated. And guess what? sass-embedded
is a wrapper around a native Dart executable, and this native executable is the reason why the previous method no longer works.
Method 2
As mentioned in the previous section, we will use bundix
. To do this, I followed the tutorial of Matthew Rhone. However, I made some minor changes to his approach along the way.
- Go to the root directory of your Jekyll site and start an interactive shell containing the packages
bundler
andbundix
.1
nix-shell -p bundler bundix
- Set the path for the Gemfiles to
vendor
.1
bundle config set path vendor
- Make sure that bundler doesn’t use platform-specific gems.
1
bundle config set --local force_ruby_platform true
If you skip this, you might encounter an error similar to the following in step 8. The solution above is suggested by ymarkus and jonknapp.
1 2 3 4 5
error: hash mismatch in fixed-output derivation '/nix/store/q8r80dxq77ajl83jb0bvlrv4ah7viq7n-ffi-1.17.0.gem.drv': specified: sha256-YJyHTnZhRULG1IWwV25Cp6OP/N8IZhL5owDE7D/NDRI= got: sha256-UWMOQ0JQeDEcBWynX5Ybs72hZBqzbkStTEVeCw5KIxw= error: 1 dependencies of derivation '/nix/store/2c93xzahy79b3xd6yzd7z2g0khlldi79-ruby3.1-ffi-1.17.0.drv' failed to build error: 1 dependencies of derivation '/nix/store/536yqbf0z7anv7byd85wh77zipgybag8-GitHubPagesBlog.drv' failed to build
- Package the gem files to
vendor/cache
without installing them to the local install location.1
bundle cache --no-install
- Run
bundix
to create Nix packages from the Gemfiles. This command also generates thegemset.nix
file.1
bundix
- The
vendor
directory was only needed forbundix
and can now be deleted. The same applies to thebundix
cache directory.1 2
rm -rf vendor rm -rf ~/.cache/bundix
- Create a
default.nix
file which sets up thenix-shell
environment to locally run Jekyll. You can change the name parameters to your liking.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
with (import <nixpkgs> {}); let env = bundlerEnv { name = "YourJekyllSite"; inherit ruby; gemfile = ./Gemfile; lockfile = ./Gemfile.lock; gemset = ./gemset.nix; }; in stdenv.mkDerivation { name = "YourJekyllSite"; buildInputs = [env ruby]; shellHook = '' exec ${env}/bin/jekyll serve --watch ''; }
- Exit the
nix-shell
and enter a new one with thedefault.nix
we just created.1 2
exit nix-shell
If no path is given to the
nix-shell
command thendefault.nix
is used. If this doesn’t work then explicitly specifydefault.nix
.1
nix-shell default.nix
The Jekyll site is now running locally.
Resources
- Chirpy Jekyll theme GitHub repository [link]
- Setup github pages + jekyll with a nix shell [link]
- NixOS wiki: Packaging/Binaries [link]
- Bundix GitHub repository [link]
- Jekyll’s NixOS 23.11 Gemfile.lock [link]
- SassC GitHub repository [link]
- LibSass is Deprecated [link]
- Jekyll’s NixOS 24.05 package [link]
- Jekyll Sass Converter documentation [link]
- npm sass-embedded documentation [link]
- Jekyll in NixOS [link]
- Bundix GitHub issue #88 [link]