Post

Nix Home Manager

After almost one year from my last Nix journey post. Here I am with another one! Let’s dive into using Nix Home Manager to manager all the Nix packages declaratively!

Introduction

If you’ve ever found yourself reinstalling your system and painstakingly re-installing every package, re-tweaking your .bashrc, or re-downloading your favorite CLI tools, you’re not alone.

Nix Home Manager is a tool that takes Nix’s declarative philosophy and brings it to your personal environment. It allows you to define everything from your installed packages to your shell configuration, editor settings, and dotfiles.

With that said, I am still not full in with Nix Home Manager just yet. My current approach is only use Home Manager to manage Nix related packages while using a global Git method to track my dotfiles.

Getting Started

For a brand new machine, you can init your home-manager with the following command, and yes, we are still on Ubuntu.

1
nix run home-manager/master -- init --switch

The above command will create a home-manager directory under your $XDG_CONFIG_HOME which is usually the .config directory.

Managing Packages

Edit the home.nix file and update the home.packages session. This file can be found at $HOME/.config/home-manager/home.nix.

1
2
3
4
  home.packages = [
    # Add your nix packages here!
    pkgs.neofetch
  ];

Once you are done updating the packages you need, you can simply apply the home-manager configurations by running:

1
home-manager switch

If you are wondering where you can find the available packages, like me, there are two ways to search.

The first method, is to go to the official package website and use their interactive search bar to look for the packages you need. Visit the link below:

1
https://search.nixos.org/packages

The second method, is to use nix search, you will need to provide a installable source before the package name.

1
nix search nixpkgs pixi

The nice thing about using the cli is that you can provide a few more keywords as well as to tell it to exclue plugin, like the example below:

1
nix search nixpkgs htop vim -e "plugin"

Managing Dotfiles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{ config, pkgs, ... }:

{
  home.username = "bruce";
  home.homeDirectory = "/home/bruce";

  # Let Home Manager manage itself
  programs.home-manager.enable = true;

  # Packages to install declaratively
  home.packages = with pkgs; [
    git
    neovim
    htop
    jq
  ];

  # Manage dotfiles declaratively
  programs.bash = {
    enable = true;
    shellAliases = {
      ll = "ls -alF";
      gs = "git status";
    };
    promptInit = ''
      export PS1="\u@\h:\w$ "
    '';
  };

  # Example: Configure git user info declaratively
  programs.git = {
    enable = true;
    userName = "Bruce Chan";
    userEmail = "bruce@example.com";
  };
}

That’s it — your packages, aliases, and configuration are now managed declaratively.

Why Home Manager (and not nix-env)?

Aspectnix-env (Imperative)Home Manager (Declarative)
ConfigurationYou install packages manually (nix-env -iA nixpkgs.htop)You define packages in a home.nix file
State trackingNix doesn’t “remember” what you installedEverything is version-controlled
ReproducibilityHard to reproduce your setup elsewhere100% reproducible and portable
RollbacksManual and limitedBuilt-in rollbacks for config generations
DotfilesManaged manually or with symlinksManaged declaratively and consistently

In short: nix-env is like running apt install, while Home Manager is like having an aptfile you can share with future-you.

Useful Features Worth Mentioning

Home Manager is surprisingly deep. Here are some highlights of its advanced yet practical capabilities:

1. Version-controlled Configs

Your entire environment is just code, well Nix code, you can commit it to Git and reproduce it anywhere with one command.

2. Dotfile Management

No need for symlink farms (stow, chezmoi, etc.). Home Manager directly manages files in home.file.:

1
home.file.".config/nvim/init.vim".source = ./dotfiles/init.vim;

Of course, I am still on the fence for this one!

3. Program Modules

Home Manager has modules for many common programs: zsh, starship, tmux, alacritty, neovim, vscode, and more, all declaratively configurable. However, for those that are not in the list, you will have to either do a pull request or wait for the maintainers to get there.

4. Per-User Profiles

Different users on the same system can each have their own reproducible environments.

5. Seamless Nix Flake Integration

For more advanced setups, integrate with flakes for fully reproducible, version-pinned configs:

1
2
3
4
homeConfigurations.bruce = home-manager.lib.homeManagerConfiguration {
  pkgs = import nixpkgs { system = "x86_64-linux"; };
  modules = [ ./home.nix ];
};

Then update it anywhere with:

1
nix run .#homeConfigurations.bruce.activationPackage

6. Automatic Rollbacks

Home Manager keeps generations, so if something breaks, just roll back:

1
2
home-manager generations
home-manager rollback

Closing Thoughts

Home Manager is a perfect bridge between Nix-the-package-manager and NixOS-the-declarative-system. It’s ideal whether you’re:

  • a developer who hops between machines,
  • a dotfile perfectionist, or
  • just someone looking for a declarative way to manage your Nix packages

Anyways, that wraps up this article, as always, keep learning until we meet again!

This post is licensed under CC BY 4.0 by the author.

Trending Tags