This page is part of my digital garden.

This page might be unfinished or have typos. These pages are meant as part of a public living notebook to be edited over time. For more, visit the page explaining the concept of a digitial garden.

Nix: Language, Nixpkgs, and NixOS

Nix is an amazing tool which makes it much easier to package and maintain software on a system.

What is amazing about it is that it uses very simple tools to provide a far more reliable, efficient, and secure system than many others out there. It provides a way to manage packages in every language at the same time and also not have issues using their tooling.

Nix is first a language which lets you describe functions, it is a functional language, that take some inputs and use those to provide some outputs. More plainly: the language makes it easy to specify files or packages somewhere (github, pypi, etc.) easily and convert that in a content addressable piece of data to be used elsewhere. Using those pieces of data you can write other data as outputs which are hashed using their contents as well as the hashes of the content used to make them so it’s impossible1 to remake the content until the same inputs are used.

A simple example being a C program with a single C file compiled using a specific C Compiler Binary should always evaluate to the same thing. The C source file will be hashed and stored and so will the C Compiler Binary. The function using these two inputs can run the C Compiler on the C Source to provide a new C Binary.


The same idea as before but taken to the whole operating system. Given a configuration provide the set of boot loader, kernel, and File System Hierarchy you desire and Nix can provide it. Thanks to it having lazy evaluation and smart caching from hashing all the contents of the derivations building a different operating system configuration could take seconds.

NixOS’s minimal ISO is now fully reproducible2

Configuring NixOS

Configuring NixOS is a little bit like feast or famine. Sometimes a very complicated thing is literally one line and always works and other times you need to dig deeply into the .nix files of nixpkgs to figure out how it even works and how you can, maybe, change it to work for you for now.

Typically you’re changing the /etc/nixos/configuration.nix file for system things and using home-manager and ~/.config/nixpkgs/home.nix for things related to your user.

Basically I use one for things like Chrome, Firefox, my editors, ssh config and etc related to my user and I use configuration.nix for system wide configuration like the Kernel, networking, essential utils, etc.


Hiding the output while NixOS starts is as simple as adding boot.plymouth = { enable = true; }; to your configuration.

Dual Boot Windows

On my desktop I have Windows installed on one drive and NixOS installed on another. I use zfs for my NixOS drive. To be able to boot Windows on another Disk you must use GRUB 2 instead of simply using systemd-boot (which is simpler and faster, but again doesn’t support this).

My config looks like this:

boot.loader.systemd-boot.enable = false;
boot.loader.efi.canTouchEfiVariables = true;
boot.loader.efi.efiSysMountPoint = "/boot";
boot.supportedFilesystems = [ "zfs" ];

boot.loader.grub = {
devices = [ "nodev" ];
efiSupport = true;
enable = true;
version = 2;
# useOSProber = false;
extraEntries = ''
    menuentry "Windows" {
    insmod part_gpt
    insmod fat
    insmod search_fs_uuid
    insmod chain
    search --fs-uuid --set=root XXXX-XXXX
    chainloader /EFI/Microsoft/Boot/bootmgfw.efi

OS Prober did not work for me so I added an entry manually. When looking for the values to replace XXXX-XXXX make sure to pick the EFI volume (usually around 500MB and at the end of the drive) because otherwise it won’t work.

You can use something like lsblk -o name,label,partlabel,uuid,size to see what the UUID is for the parition you need.

Warning: I’ve heard that Windows can get confused when doing major updates and screw up the EFI for NixOS instead of updating the one on it’s drive if it’s not the one which gets tried by the BIOS first. I haven’t run in to this yet, but it’s a known issue. Hopefully I can write some notes about fixing Windows EFI paritions later.


Some packages and extensions to install:

  • xsel is a good tool for using clipboard from the terminal like pbcopy in macOS
  • ddcutil is a great tool for controling your monitors.
    • This doesn’t work yet, but it probably will soon: Recommended to install gnomeExtensions.brightness-control-using-ddcutil to control from Gnome tray
  • gnomeExtensions.screenshot-tool is great, but requires gjs. Otherwise works really nicely for making screenshots quickly.


While working on my NixOS Router project I’ve learned a lot about setting up networks via NixOS as well as needed Kernel modules to do things.

I will add some notes later on about things I learned trying to enable tc_cake, creating multiple IP networks, setting up NATs, and creating port fowards. There is also some stuff to write in here about manging BIND and DHCP for internal networking stuff.

Setup tc_cake

tc_cake which I used for my NixOS router project to help improve my internet latency.

Was very difficult because I made my life difficult by configuring NixOS too securely making it hard to test changes without rebooting (and therefore kicking me out of my SSH session).

Configuring Nix for macOS

  1. Nix is not magic and the functions written must be written to be reproducible. Nix, the ecosystem of tools/etc., provide ways to isolate your builds as well as test them for being flaky and non-deterministic. ↩︎

  2. Discussion on NixOS reproduciblity ↩︎

Last updated on