★ nix-env in a nutshell for basic usage in macOS
• 749 words • 4 min • updated
I am currently evaluating Nix as a replacement for Homebrew CLI apps in macOS1. Others have previously written about this.
My goal is to keep a sane learning curve and learn things on-the-fly, only as needed. Nix is a massive ecosystem and has so many batteries included and components (NixOS, NixPkgs, NixOps, Nix programming language, nix-shell, nix-env, nix-darwin, home-manager, …). The good news is that those components are for the most part modular, there’s no need to adopt them all in order to reap the benefits that Nix provides.
For now, I am only adopting nix-env and nix-shell, with no *.nix config
files. This post covers nix-env.
For simplicity, think of nix-env as a package manager, akin to apk,
pacman, brew, apt, pkg, etc.
Install a package #
$ nix-env -i moreutils
installing 'moreutils-0.67'
building '/nix/store/jsp0l5ny3kx8p9lx9w9r0x159i9jjnn6-user-environment.drv'...I see some guides using nix-env -iA but -i seems to suffice. We could
optionally specify the nixpkgs. prefix:
$ nix-env -i nixpkgs.moreutils
error: selector 'nixpkgs.moreutils' matches no derivationsOh no! Maybe that’s what the -A is for?
$ nix-env -iA nixpkgs.moreutils
replacing old 'moreutils-0.67'
installing 'moreutils-0.67'Indeed! Apparently that -A thing stands for attribute. The only thing I know
is that there are both nixpkgs.* and nixos.*. But I don’t care about NixOS
at this point. I’ll just ignore -A from now on, for the time being.
List installed packages #
$ nix-env -q
moreutils-0.67Easy! This actually gets displayed in my less pager.
Upgrade installed packages #
$ nix-env -uEasy! At this point, I am not super confident whether that works as intended though. We will find out in a few days when there’s some update to one of my installed CLI applications. I’ve heard there’s something called nix channel to control that. Leaving it for another day though.
Update(2022-02-18): I learned that nix-env -u is akin to apt upgrade or
apk upgrade. It upgrades installed packages to newer versions but only if it
is aware there are newer versions. To actually refresh the repositories à la
apt update or apk update, use nix-channel --update.
Note: On macOS this needs to be sudo -i nix-channel --update. See
issue.
Uninstall a package #
$ nix-env --uninstall moreutils
uninstalling 'moreutils-0.67'
building '/nix/store/5k8rsf4cxg4iz7cqnqirpww6r97bwnqr-user-environment.drv'...Easy!
Search for packages #
$ nix-env -qaP '.*moreutils.*'The .* seems to be needed. It works if I omit them, but only if I write the exact package name (apparently called ‘derivation’ in Nix):
$ nix-env -qaP moreutils
nixpkgs.moreutils moreutils-0.67If I write the wrong package name, the following happens:
$ nix-env -qaP moreutil
error: selector 'moreutil' matches no derivations, maybe you meant:
moreutilsIt was helpful in this case, but I wouldn’t always count on that. It is a bit
annoying that there’s no nix search moreutils command, but it seems that
nix-env is very heavily tailored to use short flags, just like pacman in
Arch Linux. I got used to pacman, hopefully I can get used to the nix-env
short flags at some point.
Actually I tried it out and there is a nix search command!
$ nix search moreutils
error: experimental Nix feature 'nix-command' is disabled; use '--extra-experimental-features nix-command' to overrideThis isn’t very promising though. How come searching is experimental?! Anyway, I can live with the nix-env form for now.
These are the 5 basic package management operations that I needed to bootstrap my dev environment. Without putting much effort on it, my initial list of package looks like this:
$ nix-env -q
atool-0.39.0
bash-interactive-5.1-p12
coreutils-9.0
exa-0.10.1
fpp-0.9.2
fzf-0.29.0
git-2.34.1
htop-3.1.2
hugo-0.92.0
jq-1.6
less-600
moreutils-0.67
ncdu-1.16
perl5.34.0-ack-3.5.0
ranger-1.9.3
stow-2.3.1
tmux-3.2a
tree-1.8.0
vim-8.2.4186
watch-procps-3.3.16
wget-1.21.2
zoxide-0.8.0Those were very intuitive to find, with the exception of ack and bash-interactive:
bashis a bit odd because Nix splits it into two packages: a non-interactive version and an interactive version. I have no idea why. My~/.bashrcwrecked havoc with the non-interactive version.ackis very oddly named. Really. Also:nix-env -i ackdoesn’t work, butnix-env -iA nixpkgs.ackdoes. I suspect it will be hard to ignore-Ain the future.
-
Strictly speaking there’s nothing special about macOS in this context. The same setup can also be used in Linux distributions, for example, Debian or Ubuntu. In fact, this is what I did at $DAYJOB, because relying solely on Debian for package management is a very big limitation. I find that Nix complements the Debian repositories very well, the same way that it does for macOS. ↩︎