Alexander Shagov
Posted on September 4, 2024
It might be overwhelming to dive into the Nix world, but this little glossary should help refine your understanding of the tools you might encounter when starting your journey.
UPD: I wrote one more short article to articulate why I prefer nix over non-nix setups in general: https://dev.to/alexander_shagov/why-use-nix-even-on-macos-786
Nix Package Manager – The core tool that allows declarative and reproducible package management.
NixOS – A Linux distribution built entirely on the Nix package manager. It's better to start with nix package manager alone before switching to NixOS completely.
Home Manager – Manages user packages, dotfiles, environment variables, shell configurations, and more. Allows for portable user environments across different machines.
Flakes – Provides a standardized structure for Nix projects, improving reproducibility and composability. It's worth noting that while Flakes are still technically experimental, they have been widely adopted by the Nix community due to their benefits. Many newer Nix configurations and projects are built using Flakes.
Old flow vs New flow
When you start searching for actual commands, you might encounter that some of them have different syntax (e.g., 'nix build' vs 'nix-build').
https://nixos-and-flakes.thiscute.world/nixos-with-flakes/introduction-to-flakes
Based on the article, there are two "flows" or approaches to using Nix: the old (or classic) flow and the new flow using flakes.
New Flow (Flakes and New CLI):
Introduces flake.nix and flake.lock files.
Uses new CLI commands that start with "nix" (e.g., nix develop, nix shell, nix build).
Replaces channels with explicit inputs in flake.nix.
Aims for improved reproducibility and composability.
Old Flow (Classic Nix):
Used commands like nix-channel, nix-env, nix-shell, and nix-build.
Relied on channels for package management.
Less standardized structure for Nix projects.
Could lead to less reproducible builds in some cases.
The new flow is essentially an evolution of Nix, addressing some limitations of the classic approach and borrowing ideas from other modern package managers (like npm, Cargo, etc.).
Assuming you're not using NixOS itself but, let's say, macOS, your flow of working with your development environment might look like this:
1) Use home-manager (preferably with flakes) to manage user-specific packages, tools, and configurations. This includes system-wide tools like Emacs, as well as dotfiles and environment settings.
2) For each project you're working on, create a flake.nix
file to define the project-specific development environment and dependencies.
The aim of the article was to provide a good starting point and set up the mental model for further readings. Even though I didn't set a goal to share specific code snippets, here's the example of a home-manager (home.nix) file defining the global configuration on my MacOS. This configuration defines the global state of my system. Any project-related pieces live a in separate flake.nix files in their own namespaces. NOTE: I'm not using brew anyhow!
{ config, pkgs, ... }:
{
home.username = "<username>";
home.homeDirectory = "<homeDirectory>";
home.stateVersion = "24.05";
home.packages = with pkgs; [
direnv
ripgrep
htop
inetutils
jq
emacs29
emacsPackages.vterm
];
home.shellAliases = {
# ============ git aliases =====================
gs = "git status";
gcm = "git checkout main && git pull";
gc = "git checkout";
};
home.sessionVariables = {
EDITOR = "emacs";
};
# ======== Zsh configuration ============
programs.zsh = {
enable = true; # Enable managing the Zsh configuration
initExtra = ''
# Private ENV vars configuration
if [ -f ~/.bashrc_private ]; then
. ~/.bashrc_private
fi
# ========= Prompt with a branch ========
function git_branch_name() {
git rev-parse --abbrev-ref HEAD 2>/dev/null || echo '='
}
autoload -Uz colors && colors
setopt prompt_subst
prompt='%F{yellow}%~/%f [%F{green}$(git_branch_name)%f] > '
'';
};
programs.direnv = {
enable = true;
# enableBashIntegration = true; # see note on other shells below
nix-direnv.enable = true;
};
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
}
Any time I need to add/remove system-wide package, or adjust, let's say, zsh
configuration, it just boils down to editing the home.nix file and running the home-manager switch
to apply the change (or home-manager build
to see if a build compiles correctly).
Where to look for packages
Given you want to install htop
. Just use the search.nixos.org and put the package name into your home.nix file. Run home-manager switch
and you'll have your htop
configured automatically (e.g. /Users/<username>/.nix-profile/bin/htop
)
How to install a specific version of a package?
If you want to install a specific version of a package (not the latest one by default), you can search at nixhub.io. There, you'll see a specific Nixpkgs Reference you should use in your home.nix file to point to a specific version you're interested in.
Useful links for further reading
- Introduction to Flakes: https://nixos-and-flakes.thiscute.world/nixos-with-flakes/introduction-to-flakes
- Nix flakes syntax basics: https://serokell.io/blog/practical-nix-flakes
- Official nix package manager step-by-step guide: https://nixos.org/guides/nix-pills/01-why-you-should-give-it-a-try
- A good article where a person shows how they cleaned up their $HOME with nix: https://juliu.is/tidying-your-home-with-nix/
⭐ Comments and more useful articles for nix beginners appreciated!
Posted on September 4, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.