home-manager and dotfiles
Introduction
Nix home-manager allows you to control your user environment using nix, providing a declarative approach to managing your dotfiles and system configuration. However, it’s worth noting that you don’t have to use nix for everything. If you choose to, you can still use home-manager to manage your other dotfiles and system configuration while controlling some customization manually. For instance, you can manage a specific configuration file for a particular application manually, while letting home-manager handle everything else. This approach lets you strike a balance between centralized configuration management and controlled customization. By using home-manager to manage most of your configuration files, you can still benefit from its declarative approach, while keeping some level of flexibility for specific cases.
Goal
In this post, we are going to set zsh, fish and bash configuration using nix home-manager. However, the goal is not to use nix for everything.
The goal is to set up sensible configuration hierarchical structure such that
- Nix configurations that can be shared entire engineering team
- Provides an organization wide configuration
- Does not compromise on user-level customization
To demonstrate an ability above, we are going to set up, bash, zsh, and fish.
Details
Initial bash, zsh, and fish setup.
First we are going to set bash, zsh, and fish enabled through home-manager. To do that,
~/.config/home-manager/home.nix
must be updated as following.
home.stateVersion = "22.11";
programs.direnv.enable = true;
+
+ programs.bash.enable = true;
+ programs.zsh.enable = true;
+ programs.fish.enable = true;
}
Once the file is saved, we need to apply the home-configuration. We’ve alraedy created the handy
script to do that at $HOME/.config/bin/hms
, so let’s call that.
$HOME/.config/bin/hms
Starting Home Manager activation
Activating checkFilesChanged
Activating checkLinkTargets
Existing file '/home/rexk/.bashrc' is in the way of '/nix/store/pzf4zq0ls1lj7jqfch0yf114mw8gn3hj-home-manager-files/.bashrc'
Please move the above files and try again or use 'home-manager switch -b backup' to back up existing files automatically.
Oh, of course. home-manager wants to create symlink on ~/.bashrc
, ~/.zshrc
, and ~/.config/fish/config.fish
,
but we usuall already have our own file there. Since we are using
nix flake to control home-manager rather than usual home-manager route, we can’t use
home-manager switch -b backup
command. So let’s back everything up ourselves
mv ~/.bashrc ~/.bashrc.bak
mv ~/.zshrc ~/.zshrc.bak
mv ~/.config/fish/config.fish ~/.config/fish/config.fish.bak
Since, this might be common for many people, let’s make a script that people can use.
Let’s call this script backup-original-rc-files
and place it under ~/.config/bin
#!/usr/bin/env bash
backup_file_if_exists() {
local file="$1"
if [ -f $file ];
then
mv -f $file $file.bak
fi
}
backup_file_if_exists ~/.bashrc
backup_file_if_exists ~/.zshrc
backup_file_if_exists ~/.config/fish/config.fish
case "$(uname -s)" in
Darwin)
# for MacOS as we would be installing
# nix-darwin as well
# it is good idea to back up the original
sudo backup_file_if_exists /etc/zshrc
sudo backup_file_if_exists /etc/bashrc
;;
esac
Once all files are backed up, let’s try again
$HOME/.config/bin/hms
tarting Home Manager activation
Activating checkFilesChanged
Activating checkLinkTargets
Activating writeBoundary
Activating installPackages
replacing old 'home-manager-path'
installing 'home-manager-path'
Activating linkGeneration
Cleaning up orphan links from /home/rexk
Creating profile generation 29
Creating home file links in /home/rexk
Activating onFilesChange
Activating reloadSystemd
Ok, that’s better.
We can try to configure all of our shell with nix, but I would rather want to keep most of our shell configurations in our usual shell file, despite we are making our nix environment impure.
So, let’s give a bit more changes on to our ~/.config/home-manager/home.nix
file.
home.stateVersion = "22.11";
programs.direnv.enable = true;
+
+ programs.bash = {
+ enable = true;
+ initExtra = "
+if [ -f $HOME/.config/bash/.bashrc ];
+then
+ source $HOME/.config/bash/.bashrc
+fi
+";
+ };
+ programs.fish = {
+ enable = true;
+ initExtra = "
+if test -f $HOME/.config/fish/config.base.fish;
+then
+ source $HOME/.config/fish/config.base.fish
+fi
+";
+ };
+ programs.zsh = {
+ enable = true;
+ initExtra = "
+if [ -f $HOME/.config/zsh/.zshrc ];
+then
+ source $HOME/.config/zsh/.zshrc
+fi
+ };
Instead of configuring bunch of things through nix, we are simply going to delegate further configurations into respectful rc files. This allows us to keep using familiar configuration without needing to learn more on nix and it’s home-manager configuration structure.
References
All file changes can be found at: https://github.com/rexk/dotfiles/tree/nix-flake-install-stage-02