iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🏵

Managing dotfiles with WSL and home-manager: Comparison and usage of 4 methods

に公開
2025/08/09
2件

Introduction

Nix is a package manager known for its high reproducibility, and home-manager is a tool for managing user environments using Nix.

Recently, I have been building a development environment using Nix.
In the process, I wanted to easily manage tools commonly used across most projects, such as git, with Nix, so I introduced home-manager.

This is just my personal impression...
Although the official manual provides configuration examples for git and other tools, I found it unclear how to write configurations for a package you are encountering for the first time.

Therefore, in this article, I will explain how to use and the differences in behavior of four introduction methods, using git as an example.

  1. home.packages
  2. programs.<name>
  3. home.file.<name>.source
  4. home.file.<name>.text

Target Readers

  • Already have Nix installed
  • Have read Nix入門 and Nix入門: ハンズオン編

https://zenn.dev/asa1984/books/nix-introduction

https://zenn.dev/asa1984/books/nix-hands-on

Verification Environment

  • Windows 11
  • WSL2
    • Ubuntu 22.04.5 LTS
  • nix (Determinate Nix 3.8.2) 2.30.1
  • home-manager 25.11-pre
Details
> wsl -l -v
  NAME              STATE           VERSION
  NixEnv            Running         2

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.5 LTS
Release:        22.04
Codename:       jammy

$ nix --version
nix (Determinate Nix 3.8.2) 2.30.1

$ home-manager --version
25.11-pre

$ nix-channel --list
home-manager https://github.com/nix-community/home-manager/archive/master.tar.gz

References

https://qiita.com/suin/items/809236c1a6235ca012d7

https://zenn.dev/kuu/articles/20250204_introduce-home-manager

Preparing home-manager

Installation

Multiple methods are available, but for WSL environments, Standalone installation is the only option.

https://nix-community.github.io/home-manager/index.xhtml#sec-install-standalone

Execute the following commands one by one:

bash
nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
nix-channel --update
nix-shell '<home-manager>' -A install

home.nix and Activating the Environment

After installation, home.nix is generated in the following directory:

~/.config/home-manager/home.nix

In home.nix, you can specify the packages you want to use in your user environment and configure package options.

Then, with the following command, the environment is built and activated based on home.nix:

bash
home-manager switch

Now, let's actually write configurations for git and other tools in home.nix.

From here on, I will explain various configuration methods using git as an example.

Characteristics and Usage of the Main Package Introduction Methods

Method Use Case
1 home.packages Just want to install the package
2 programs.<name> Want to install the package and generate configuration files at the same time
3 home.file.<name>.source Want to reuse existing configuration files via symbolic links
4 home.file.<name>.text Want to write the configuration file content directly in home.nix as text

Personal Impression

For packages that don't need configuration, home.packages is fine; if configuration is needed, programs.<name> or home.file.<name>.source seems good.

Choosing between programs.<name> and home.file.<name>.source is a matter of preference, but I felt that home.file.<name>.source is more reliable.

(programs.<name> lets home-manager generate configuration files nicely; looking at it critically, there is a risk of errors caused by home-manager's processing.)

As for home.file.<name>.text, readability decreases as the number of configuration files increases, so home.file.<name>.source seems easier to manage with appropriate separation.

Check behavior when package is not installed

To make clear what changes when editing home.nix, let's first see the state without the git package installed.

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

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

  home.stateVersion = "25.05";

  programs.home-manager.enable = true;
}

Activating the environment, of course, means git installed outside Nix via normal methods is being used.

bash
$ home-manager switch
$ which git
/usr/bin/git

Method 1 home.packages - Package Installation

First, let's look at the most basic method to make git available with Nix.

Write the packages you want to use in home.packages.

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

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

  home.stateVersion = "25.05";

  home.packages = [
    pkgs.git
  ];

  programs.home-manager.enable = true;
}

Now you can use git managed by Nix.

bash
$ home-manager switch
$ which git
/home/ryu/.nix-profile/bin/git

Let's check which .gitconfig is being referenced.

bash
$ git config --list --show-origin
file:/home/ryu/.gitconfig       user.name=MyName
file:/home/ryu/.gitconfig       user.email=MyMail

The .gitconfig that was used when git was installed outside Nix is being referenced.

Next, let's manage this .gitconfig with home-manager as well.

Method 2 programs.git - Package Installation & Configuration

If you want to configure settings at the same time as installing the package, use programs.<package name>.

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

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

  home.stateVersion = "25.05";

  programs.git = {
    enable = true;
    userName = "MyNixName";
    userEmail = "MyEmail@example.com";
  };

  programs.home-manager.enable = true;
}

Now, what happened to .gitconfig?

bash
$ git config --list --show-origin
file:/home/ryu/.config/git/config       user.email=MyEmail@example.com
file:/home/ryu/.config/git/config       user.name=MyNixName
file:/home/ryu/.gitconfig       user.name=MyName
file:/home/ryu/.gitconfig       user.email=MyMail

/home/ryu/.config/git/config was generated by home.nix.
Meanwhile, /home/ryu/.gitconfig is the original file.

The configuration files are duplicated, so delete the latter.
(Although I'm deleting it here, it's safer to back it up by renaming it.)

bash
$ rm ~/.gitconfig
$ git config --list --show-origin
file:/home/ryu/.config/git/config       user.email=MyEmail@example.com
file:/home/ryu/.config/git/config       user.name=MyNixName

Behavior When Conflicting with Existing Config Files

If a file already exists where home-manager places the git config, an error like the following occurs:

bash
$ home-manager switch
…
Activating checkLinkTargets
Existing file '/home/jdoe/.config/git/config' is in the way
Please move the above files and try again

From the official manual:

To configure programs and services Home Manager must write various things to your home directory. To prevent overwriting any existing files when switching to a new generation, Home Manager will attempt to detect collisions between existing files and generated files. If any such collision is detected the activation will terminate before changing anything on your computer.

Method 3 home.file source - Symbolic Link for .gitconfig

This method creates a .gitconfig in advance and creates a symbolic link.

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

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

  home.stateVersion = "25.05";

  home.packages = [
    pkgs.git
  ];

  home.file = {
    ".gitconfig".source = git/.gitconfig;
  };

  programs.home-manager.enable = true;
}

In this example, since git is only being installed as a package, home.packages is used.

home.file.<FileName>.source = <FilePath> specifies which file to create a symbolic link to.

home.nix
  home.file = {
    ".gitconfig".source = git/.gitconfig;
  };

Method 4 home.file text - Write .gitconfig Directly in home.nix as Text

This method writes the content of .gitconfig directly in home.nix as text.

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

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

  home.stateVersion = "25.05";

  home.packages = [
    pkgs.git
  ];

  home.file = {
    ".gitconfig".text = ''
      [user]
        name = MyName
        email = MyMail
    '';
  };

  programs.home-manager.enable = true;
}

home.file.<FileName>.text = <ConfigText> allows you to directly write the content of <FileName> as text.

home.nix
  home.file = {
    ".gitconfig".text = ''
      [user]
        name = MyName
        email = MyMail
    '';
  };

Checking the actual behavior, it confirms that .gitconfig is generated and placed upon environment activation.

bash
$ cat /home/ryu/.gitconfig
cat: /home/ryu/.gitconfig: No such file or directory

$ home-manager switch

$ cat /home/ryu/.gitconfig
[user]
  name = MyName
  email = MyMail

(Bonus Explanation) How to Find Parameters for programs.git

Where did the userName and userEmail used in Method 2's programs.git come from?

I'll explain three methods to find each parameter.

  • A. Search with Home Manager - Option Search
  • B. Search the official manual
  • C. Read the git.nix file

Basically, A. Home Manager - Option Search is easy to use and recommended.

From the perspective of "how to find primary sources," I'll also introduce B. Search the official manual and C. Read the git.nix file.

You can search for available options in home-manager at the following site:

https://home-manager-options.extranix.com/

https://github.com/mipmip/home-manager-option-search

Search results for git on Home Manager - Option Search

B. Search the official manual

Options confirmed in Home Manager - Option Search can also be checked in the official manual.

https://nix-community.github.io/home-manager/options.xhtml#opt-programs.git.enable

Search results for git in the official manual

C. Read the git.nix file

When you check programs.git.enable on Home Manager - Option Search or the official manual, there is a link at the bottom saying Declared by: <home-manager/modules/programs/git.nix>.

For packages like git that have many options and many similarly named options (making it hard to narrow down by search), I personally find it easier to get a comprehensive overview of available parameters by reading the nix file directly.

https://github.com/nix-community/home-manager/blob/master/modules/programs/git.nix

The parameters defined in options starting from line 101 onwards are the parameters available for programs.git in home.nix.

Sample 1 userName

For example, looking at userName, you can see that the default is null, and a str type is expected.
The description will also be valuable information.

git.nix
  options = {
    programs.git = {
      ...
      userName = mkOption {
        type = types.nullOr types.str;
        default = null;
        description = "Default user name to use.";
      };
      ...

Sample 2 extraConfig

Let's also check a more complex parameter.

git.nix
  options = {
    programs.git = {
      ...
      extraConfig = mkOption {
        type = types.either types.lines gitIniType;
        default = { };
        example = {
          core = {
            whitespace = "trailing-space,space-before-tab";
          };
          url."ssh://git@host".insteadOf = "otherhost";
        };
        description = ''
          Additional configuration to add. The use of string values is
          deprecated and will be removed in the future.
        '';
      };
      ...

It may seem harder to understand with more information, but what you need to do is quite simple.

Let's compare the writing methods in .gitconfig and nix.home, using the core whitespace example from the example section.

The values set are directly from the example in the git documentation below.

https://git-scm.com/book/ja/v2/Git-のカスタマイズ-Git-の設定

Comparison

Although detailed definitions are omitted, I think the writing rules are visually understandable.

If you check how to write in .gitconfig in the git documentation, you can infer how to write it in home.nix.

# .gitconfig
[core]
	whitespace = trailing-space,space-before-tab,indent-with-non-tab

# home.nix
    extraConfig = {
      core = {
        whitespace = "trailing-space,space-before-tab,indent-with-non-tab";
      };
    };

For reference, the code used during verification is listed below.

.gitconfig

bash
git config --global core.whitespace trailing-space,space-before-tab,indent-with-non-tab
.gitconfig
[core]
	whitespace = trailing-space,space-before-tab,indent-with-non-tab

home.nix

home.nix
  programs.git = {
    enable = true;
    userName = "MyNixName";
    userEmail = "MyEmail@example.com";
    extraConfig = {
      core = {
        whitespace = "trailing-space,space-before-tab,indent-with-non-tab";
      };
    };
  };
Verification of configuration application

For verification purposes, I have recreated the .gitconfig that was deleted in the previous session.

bash
$ git config --list --show-origin
file:/home/ryu/.config/git/config       core.whitespace=trailing-space,space-before-tab,indent-with-non-tab
file:/home/ryu/.gitconfig       core.whitespace=trailing-space,space-before-tab,indent-with-non-tab

(Bonus Explanation) How to Find What Other Packages Can Be Introduced Besides git

You can search for packages available in Nix on this site.

https://search.nixos.org/packages

For example, searching for vim gives the following:

Search results for vim on nix search

You can determine that pkgs.vim is available.

At this point, you know that any method other than Method 2 can introduce it.

  • Method 1 home.packages
  • Method 3 home.file.<name>.source
  • Method 4 home.file.<name>.text

On the other hand, Method 2 is a technique provided by home-manager, so you need to check home-manager's options.

https://home-manager-options.extranix.com/

Search results for vim on Home Manager - Option Search

This time we found it, so we can determine that vim can be managed with Method 2 as well.

  • Method 2 programs.<name>

Update History

2025/8/8

I was introduced to a site called Home Manager - Option Search in a comment. It allows you to easily search for options available in home-manager.

  • Added Home Manager - Option Search to the session (Bonus Explanation) How to Find Parameters for programs.git
  • Added the relevant site to references
  • Adjusted minor wording in each session following the addition
Comment (Titles omitted)
satler

You can search for Home Manager options on a site called Home Manager Option Search! Please check it out!

Discussion