---
title: "Nix Home Manager"
date: "2022-09-19T21:49:46+02:00"
author: "$HUMANOID"
tags: ["nix", "linux"]
description: "Basics of using the Nix Home Manager in a way that makes sense to me and probably just me"
draft: false
toc: true
---

# The Home Manager

The Nix Home Manager is a way to work with Nix in a declarative environment to manage your dotfiles and user environment packages.
This can be used on any system running the Nix packagemanager.
Personally, I've started to dabble around with it a bit after installing the Nix packagemanager in my Alpine installation.
Since I've already dabbled with Nix on a few systems through NixOS, I already knew the basics of functionally managing packages (or derivations) with the Nix packagemanager.
Hence I really quickly got sick of installing packages the imperative way.
After looking around for a bit, I found some post mentioning that managing packages in a functional environment outside of NixOS is a bit of a hack.
The post referred to some other sources, one of which used a custom meta package and another referred to the [Home Manager](https://nix-community.github.io/home-manager/).

I had messed around with the Nix Home Manager a tiny bit before, but never _really_ gave it a chance to shine as I didn't really understand it.
This time around, I decided to look up some tutorials and see how it worked.
When going through the instructions of either tutorial I used, I quickly came to the realisation why I had never _really_ looked at it.
Both tutorials took a lot of unnecessary steps according to the author's will and assumed that everyone following their tutorials had the same preferences as them.
I obviously don't.
So here's my take on installing the Home Manager outside of NixOS.

# Actually using Home Manager

Assuming you're continuing from [my previous article on Nix](/rambles/nix-on-other-distros-packagemanagers), the first step is to go to the Home Manager github page and go to the [page regarding the standalone installation](https://nix-community.github.io/home-manager/index.html#sec-install-standalone).

From there, things will be quite self explanatory if you're used to the (bare) basics of NixOS.
Though instead of using `/etc/nixos/configuration.nix` you'll be using `$HOME/.config/nixpkgs/home.nix` by default.
A basic Home Manager installation will leave you with a `home.nix` file with the following content:

```nix
{ config, pkgs, ... }:

{
  # Home Manager needs a bit of information about you and the
  # paths it should manage.
  home.username = "$USER";
  home.homeDirectory = "/home/$USER";

  # This value determines the Home Manager release that your
  # configuration is compatible with. This helps avoid breakage
  # when a new Home Manager release introduces backwards
  # incompatible changes.
  #
  # You can update Home Manager without changing this value. See
  # the Home Manager release notes for a list of state version
  # changes in each release.
  home.stateVersion = "22.05";

  # Let Home Manager install and manage itself.
  programs.home-manager.enable = true;
}
```

After making any changes to your `home.nix` file, you can apply them with:
```sh
home-manager switch
```
If you first want to see whether you build is going to be successful or not, run:
```sh
home-manager build
```

## Installing packages

To add some packages, you'll need to add them to the `home.packages` array.
On my Alpine installation I have the following:

```nix
...
  home.packages = with pkgs; [
    brave
    vscodium
  ];
...
```
Notice the `with pkgs;` section.
This prevents you from having to add the `pkgs` prefix to every package you want to add.
I don't think this is the idiomatic way of adding packages to your configuration, but it allows me to be a bit lazier and it hasn't caused any breakages yet.


## Managing dotfiles and configuration

Another amazing thing the Home Manager can do is manage your dotfiles.
And this in turn can be managed with Git.
More on this later.

### Git configuration

For instance, I have it manage my Git config using the git module.
To do this, I have the something like the following in my `home.nix`:
```nix
...
  programs.git = {
    enable = true;
    ignores = [ "*.swp" ]; # I don't need to see that I still have a file open in vim
    signing = {
      key = "<gpg-fingerprint>";
      signByDefault = false; # it would probably be better for security to have this be true, but doing so gets annoying really fast
    };
    userEmail = "<user-email>";
    userName = "<user-name>";
    extraConfig = {
      init = {
        defaultBranch = "main";
      };
    };
  };
...
```

Here's the [list of options](https://nix-community.github.io/home-manager/options.html#opt-programs.git.enable) supported by the git module.

I _strongly_ recommend digging through the documentation, looking for things that interest you in your current situation and setup.

### Integrating existing (dot)files

The Home Manager can also manage arbitrary (dot)files for you.
I have it link my `.zshrc` into place with the following line:
```nix
...
  home.file.".zshrc".source = ./zshrc;
...
```
This looks for a file called `zshrc` in the same directory as `home.nix`.
From there, it symlinks it to `~/.zshrc`

It can also manage recursive file structures.
I have it keep track of my `sxiv` configuration with the following few lines:
```nix
...
  home.file.".config/sxiv" = {
    source = ./sxiv;
    recursive = true;
  };
...
```
The interesting portion of this snippet is the `recursive` boolean.
Because of this, Home Manager will recreate the directory structure found in `./sxiv` in `~/.config/sxiv` and symlinks the files found inside into place.

# Git integration

Since all the Home Manager requires is (at least) a single text file to manage your dotfiles and Nix environment packages, it's really easy to keep track of your configuration using Git.
To that end, I have a bare repository on one of my home servers over at `/srv/git/nix/<nix-configuration>.git`
As a remote, I have pointed my repo in `$HOME/.config/nixpkgs/` to `<server-name>:/srv/git/nix/<nix-configuration>.git`.
This works over ssh.
My `$HOME/.ssh/config` contains the following lines to make the preceding work:

```ssh
Host <server-name>
	Hostname <ip-address>
	User git
	Identityfile ~/.ssh/<private-key>
	Port 4242
	IdentitiesOnly yes # this makes using an ssh agent a bit easier when using multiple keys on the same host
```
