veken.io

Home

Background

My journey towards using Home Manager (HA) started years ago when I wanted an easy way to set up all my programs and configuratoin when I got reset my laptop. This started out as bash script, since that is what you use when you want to automate commands. But this became unwieldly. I ported the script to ansible and added a vagrant box to test it with. This worked well for a while. I had it setup my shell, installed programming languages, and general applications like firefox. But this too was annoying, especially when a task depends on changes to the shell that the previous task made. Finally I came across Home Manager.

I had used nix briefly at a previous job. The team responsible for the cloud infrastructure used Nix to make sure everyone had the same version of everything. I kind of knew what Nix did in a hand wavy sort of way. Declerative environments with only the dependencies you need. At the time I found it cumbersome. But after trying to write a setup script for my laptop, the thought of if it works once it will work always was appealing.

How I use Home Manager

At the time of writing I am running EndeavourOS with Nix and HA to manage my setup.

My HA config lives in a git repository that I clone to the default HA location of ~/.config/home-manager/. Because HA manages my shell, I need to change the default shell of my user.

# /etc/shells
/bin/sh
/bin/bash
/bin/rbash
/usr/bin/sh
/usr/bin/bash
/usr/bin/rbash
/usr/bin/git-shell
/home/<user>/.nix-profile/bin/zsh # <-- Add this

After adding nix’ zsh as a valid system shell you change it with the chsh command.

chsh -s /home/user/.nix-profile/bin/zsh

Now log out and log back in and I’m all set! The last time I did this install it took me around 15 minutes to get all my programs installed and up and running with my configs.

Now because I still don’t know how Nix works, and have yet too look into flakes, the main home.nix will propbably look messy to someone who knows better. But this has been working for me. I\ve removed all examples and default configuration and just left the interesting parts.

 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# home.nix
{ config, pkgs, ... }:

{
  home.stateVersion = "23.05"; 

  # Install unfree programs like spotify, obsidian
  nixpkgs.config.allowUnfree = true;
  
  # Allow home manager to manage font config
  fonts.fontconfig.enable = true;
  
  # Add installed programs to application launcher
  targets.genericLinux.enable = true;
  
  home.packages = [
    pkgs.htop
    pkgs.yt-dlp
    pkgs.hugo
    pkgs.pandoc
    pkgs.typst
    # Applications
    pkgs.obsidian
    pkgs.vlc
    # Programming languages
    pkgs.python312
    pkgs.go
    # Programming utilities
    pkgs.poetry
    # Language servers
    pkgs.nil
    pkgs.taplo
    pkgs.nodePackages.pyright
    pkgs.gopls
    pkgs.delve
    # Fonts
    pkgs.noto-fonts-emoji
    (pkgs.nerdfonts.override { fonts = [ "FiraCode" ]; })
  ];

  imports = [
    ./programs/starship/starship.nix
    ./programs/zsh/zsh.nix
    ./programs/helix/helix.nix
    ./programs/direnv/direnv.nix
    ./programs/zoxide/zoxide.nix
    ./programs/git/git.nix
    ./programs/vscode/vscode.nix
    ./programs/beets/beets.nix
    ./services/syncthing/syncthing.nix
  ];
}

I’ve only run into one issue when using this setup. I wanted to update the packages so I updated the channel and ran home-manager switch and got an error. The channels were out of sync and refused to build. After much fiddling the fix turned out to be locking the version to 23.05, you can see this on line 2. I will at some point put update it to a later version, and feel confident in doing so because I was able to recover from an error like this without having to start from scratch. The ability to rollback really saved me here!

Next there are some one off configurations allowing for non-free programs, allowing HA to manage fonts, and adding the applications it installs to the launcher. Then the list of packages. I put all the packages that don’t have a HA config here.

Finally all the programs that come with HA. I have split these up into their own directories to bundle the nix file with related dotfiles. For example here is the config for starship.

1
2
3
4
5
6
7
8
{
	programs.starship = {
		enable = true;
		enableZshIntegration = true;
	};

	xdg.configFile."starship.toml".source = ./starship.toml;
}

All of this configuration is written without really knowing Nix. I just follow what Appendix A. says. The language is not that complicated if you just use if for configuration.

Future plans

I am getting a new laptop once frame.work decides to ship my framework 16 preorder. I think I will stay on EndeavourOS for a little while, but I do want to try out nixos at some point. Maybe I will migrate my vps once I make the time to move it to Hetzner.

I also want to figure out what flakes are and rewrite my HA config to be one.