Should You Bother With Nix?


Hi Friends!

Curious about Nix? Me too. The past few months of exploring it were quite interesting, to say the least. And it still feels like I've barely scratched the surface.

[TL;DR] That said, it's already replacing some of my old workflows and I'm really happy discovering it, even while not even using Linux for most of my local work.

What’s Nix?

Nix is a powerful suite of tools, including a package manager (Nixpkgs), language (Nix DSL), and operating system (NixOS). It provides a robust environment for reproducible and declarative configuration management.

Why Should You Care?

Developers often struggle with maintaining consistent and reliable development environments. Traditional package managers fall short in managing dependencies and ensuring reproducibility.

Think of your local workspace when you build an application requiring Go 1.20 or your old web blog running on Jekyll that only builds on Ruby from 2018 (don’t ask me how I know).

On top of these, you may find yourself moving often to new machines where you need your tooling, or to remote servers where having your CLI tools like Tmux or your beloved Neovim with all its plugins would make your life 10X easier.

On top of all these, what if I told you there’s a better alternative to your current package manager? Whether your running MacOS or Linux, there’s a different, BETTER way, to build and install packages, and use local CLI tools. Interested?

What Most Users Do

Many developers rely on package managers like Homebrew on macOS or APT on Linux (yea yea, AUR on Arch, BTW). While these tools manage packages, they often fail to isolate dependencies or ensure consistent environments across different machines.

Another way many people use for local environments are docker containers. Building and running them is great at maintaining reproducible environment and sets of tools.

HOWEVER, even docker falls short in many places where Nix doesn’t: 1. With a container you’d have to mount the paths you with to work with prior to running. This means, that by default, your local code isn’t exposed to the running container. Every change of path / port / volumes, requires a re-run. 2. There’s a case made for Nix derivations and how they’re far more reliable than Docker layers 3. Lastly, even with the above solved, containers are simply not built to host your local tooling on other machines, remote servers, etc. While it is possible, it’s not built for that and you won’t enjoy doing let, let alone make most of the host around it.

In comes Nix

Before even going in the big claims Nix makes around reproducibility and package offerings, here’s a killer feature that may be enough for some to start using it today:

Nix Shells for One-Off Tooling: Nix allows you to create temporary development shells for one-off tasks without polluting your system. For example, you can run a shell with specific tools like cow by using the command:

nix-shell -p cow

This creates a temporary environment with cow available, which disappears after you exit the shell.

While cow is an esoteric example, think about all these just-install-this-for-one-minute tools to build a local tool you found on Github, or test your buddy’s app, just to find a bloated machine after a few months of use, with 50% of the tools installed are not even in use, running old, sometimes vulnerable versions.

Are you on a Mac? Run brew list. Happy with the list you see? I wasn't.

Apt users: apt --installed list.

Yum: yum list installed

For those on AUR: yum pacman -Qm

Reproducible Environments from a Nix File: You can declare a suite of packages in a Nix file to create a reproducible environment. Running nix-shell in the directory containing this file will set up an environment with the tools listed installed. The power here, is that it's still your environment. No mounting or tweaking needed! Your path, your code, and the tooling available via Nix! When you're done, just exit the shell!

Better Packages on macOS: Nix can replace Homebrew or MacPorts on macOS, offering a more reliable package management system. Install packages with precision and avoid the common pitfalls of other package managers.

Here’s a better Homebrew drop in the next time you install Tmux:

nix -iA "nixpkgs#tmux"

Moreover, MacOS users can enjoy the amazing Nix Darwin project allowing for a full OS configuration using a configuration file that can configure your dock, the finder menu, and even customize the login window all from one config file! Here’s an example from my dotfiles.

Moving Towards Nix Flakes: Nix is gradually adopting a new feature called flakes, which offers better dependency management and reproducibility. You can create a flake locally or use remote ones. Here’s how to create a basic flake:

  1. Enable experimental features in your Nix configuration like mine here.
  2. Initialize a new flake with nix flake init.
  3. Define your dependencies and outputs in the flake.nix file.

By running nix develop or nix build, you can create and use these environments consistently across different machines.

If you’re curious, here’s the part of my recent Nix intro video showing modern Nix!


All of the above made me switch most of my package management, as well as my way of configuring new machines and backing up my current setup to Nix. I’ve also starting playing with the idea of using it for my dotfiles with home manager but we’ll keep this story for a future post :)

Thank you for reading, as always, feel free to reply to this post directly with questions and comments!

Whenever you’re ready, here’s how I can help you:

ESPRESSO FRIDAYS

Every once in a while I send hand picked things I've learned. Kind of like your filter to the tech internet. No spam, I promise!

Read more from ESPRESSO FRIDAYS

Hi friends, Tmux is a fantastic tool for managing terminal sessions, but it has its limitations. One major drawback is the lack of a floating pane feature, which can make navigating between different panes cumbersome and inefficient. Me frustrated with Tmux lack of floating panes while Zellij is killing it... Most users workaround this by creating new Tmux windows or panes, or by using hidden splits to zoom in and out. These methods work but can be inefficient and require many keystrokes,...

My Neovim takes roughly 113ms to fire up. THIS IS FAST. However, I don’t lazy load anything. Being a Lazy.nvim user, it’s kind of a shame I’m not actually making use of my plugin manager's flagship feature. But then again, it takes 113ms for nvim to start, what is there to gain here? Let’s say I drop it to 50ms. I gained 60ms which means that if I’m going to spend 30 minutes to actually reduce it, I’d have to open Neovim 15,929 times to get my time back 🤣. With an average of probably 5 times...

Hello friends, Today, we’re diving into the world of dotfiles. If you’ve ever customized your terminal, text editor, or shell, you’ve likely encountered the concept of managed dotfiles. Let’s explore why managing these configuration files is essential, how to handle them locally with stow and symlinks, and how to sync them remotely to a remote dedicated machine we create using Coder. What Are Dotfiles? Dotfiles are a collection of configuration files that allow you to configure applications...