Skip to content

Development shell concepts

A development shell makes it easy to get all of the dependencies needed to interact with your homelab. Nix with Flakes provides a convenient way to define and manage these dependencies in a reproducible manner.

Installation

Info

NixOS users can skip this step.

Install Nix using one of the following methods:

If you're using the official installer, add the following to your ~/.config/nix/nix.conf to enable Flakes:

experimental-features = nix-command flakes

Usage

Run the following command:

nix develop

It will open a shell and install all the dependencies defined in flake.nix file at the root of the project:

ktchn8s on  docs [!+] using 󰅟 default/wlcm-tfstate-ffcb87 via 󱔎 default via ❄ impure (nix-shell-env)
➜ which mkdocs
/nix/store/86p3knkm02c1ix9rfd3y1b53daybl9ag-python3-3.12.10-env/bin/mkdocs

Warning

If you have a python virtual environment activated, you should deactivate it before entering the nix shell. The nix shell environment in this project will create (if not exists) and activate it's own python venv, which may create conflicts. You can also create a custom nix bash function that would deactivate any possibly-active virtualenv, and then run the nix develop itself.

Entering the nix-shell automatically

If you have direnv installed, you can run direnv allow once and it will automatically enter the nix shell every time you cd into the project.

Using your shell environment within nix-shell

One of my outstanding pain points with Nix is that any time I'm in a nix shell, none of my stuff works the way I want it to... I have lots of aliases, fzf-based autocomplete thingy, tmux integrations, ..., and most importantly - strong feelings about how my shell should look like and behave.

So how do I get my shell environment within a nix-shell? So far I've simply added the following aliases (which I found in this post) to my default (zsh) shell environment:

alias nix-shell='nix-shell --run $SHELL'

nix() {
  if [[ $1 == "develop" ]]; then
    shift
    # deactivate any possibly-active virtualenv
    command -v deactivate &> /dev/null && deactivate
    command nix develop -c $SHELL "$@"
  else
    command nix "$@"
  fi
}

Having just started playing around with nix I don't know if this is an ideal solution, but I like to keep things simple and it does seem to work just fine.

And now, instead of a default PS1 and no configs of my own:

 nix develop
razorback:ktchn8s sergio$ ela

bash: ela: command not found

I have all of my configs within the nix shell environment:

 nix develop

ktchn8s on  docs [!+] using 󰅟 default/wlcm-tfstate-ffcb87 via 󱔎 default via  impure (nix-shell-env)
 ela

Permissions Size User   Date Modified Name
drwxr-xr-x@    - sergio 28 May 16:53  .git/
.rw-r--r--@  456 sergio 28 May 09:16  .yamlfmt.yaml
.rw-r--r--@  291 sergio 28 May 09:16  .yamllint.yml
drwxr-xr-x@    - sergio 28 May 09:16  docs/
.rw-r--r--@ 1.5k sergio 28 May 14:53  flake.lock
.rw-r--r--@  772 sergio 28 May 16:32  flake.nix
.rw-r--r--@ 1.1k sergio 28 May 09:16  LICENSE.md
.rw-r--r--@ 1.3k sergio 28 May 14:43  mkdocs.yml
.rw-r--r--@  117 sergio 28 May 09:15  README.md

Searching for particular commands in nix packages

Sometimes you may find yourself asking: "What nix package provides the foobar command?"

Instead of going directly to search.nixos.org, you may want to try the nix-search tool, which lets you ask exactly the above question. It's also available as a flake github:peterldowns/nix-search-cli.

Let's say we need the ifconfig command:

 nix-search -p ifconfig
unixtools.nettools @ 1003.1-2008 : ifconfig arp hostname netstat route
unixtools.ifconfig @ 2.10 : ifconfig
toybox @ 0.8.12 : ifconfig [ acpi arch ascii ...
nettools @ 2.10 : ifconfig arp dnsdomainname ...
inetutils @ 2.6 : ifconfig dnsdomainname ftp ...
busybox @ 1.36.1 : ifconfig [ [[ acpid add-shell ...