Simplifying Development Environments with Nix and Home-Manager

This article is for [Wano Group Advent Calendar 2024](https://qiita.com/advent-calendar/2024/wano-group), published on Fri, Dec 18.
The previous article was written by @gibom , [Making office comfortable with sound masking, report on YAMAHA VSP-2 installation](https://qiita.com/gibom/items/05ddee0ece9d38354d32) (Japanese, the original name is サウンドマスキングでオフィスを快適に！YAMAHA VSP-2導入レポ).

---

Managing a development environment can be challenging, especially on macOS. While macOS is indeed a developer-friendly platform in many respects, setting up and maintaining tools, libraries, and dependencies required for software development can quickly become tedious and error-prone.

One tool that simplifies this process is **Nix**, a powerful package manager similar to `apt` or `dnf`. Although this article won’t dive deeply into the inner workings of Nix, it will demonstrate how to use it in conjunction with **Home-Manager** to create a streamlined and reproducible development setup.
### Getting Started with Nix

Installing Nix itself is straightforward—simply execute the command provided on the [Nix website](https://nixos.org/download/).
### Install home-manager
There are multiple ways to install Home-Manager, but for maximum flexibility, I recommend a standalone installation. Here’s how to do it:
```shell
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
```
The examples below focus on macOS, but Home-Manager also works seamlessly on Linux.
### Managing Programs with Home-Manager
Home-Manager functions similarly to NixOS but operates at the user level. This allows you to manage your environment declaratively, ensuring consistency across devices and simplifying future adjustments.

To install and configure applications, add the following content to `$HOME/.config/home-manager/home.nix`, then run:
```shell
home-manager switch
```
Here’s an example configuration:
```nix
{
  home.packages = (with pkgs; [
    iterm2
    vscodium
    python3
  ]);
}
```
After running the above, you’ll find iTerm2 and VSCodium in your Launchpad, and the Python 3 binary available at `$HOME/.nix-profile/bin/python3`, automatically added to your `PATH`.
#### How to use the example configuration
If you are new to nix, you should put them into braces and merge with the config object.
With example above, suppose your old configuration has content:
```nix
{ config, pkgs, ... }:
{
  ...
}
```
And your new configuration should be:
```nix
{ config, pkgs, ... }:
{
  ...

  home.packages = (with pkgs; [
    iterm2
    vscodium
    python3
  ]);
}
```
### Managing Background Services with Launchd
Home-Manager can also manage macOS background services (`launchd` agents). Here’s an example configuration for running PostgreSQL as a background service:
```nix
let
prefix = "${config.home.homeDirectory}/.nixdata";
in
{
  launchd.enable = true;
  launchd.agents."postgresql".enable = true;
  launchd.agents."postgresql".config.ProgramArguments = [
    "${pkgs.postgresql}/bin/postgres"
    "-D"
    "${prefix}/var/lib/postgresql/${pkgs.postgresql.psqlSchema}"
  ];
  launchd.agents."postgresql".config.RunAtLoad = true;
}
```
This makes it easy to manage and configure background services declaratively.
### Managing Environment Variables
Home-Manager can also handle environment variables, shell aliases, and session paths. For example:
```nix
{
  home.sessionPath = [
    "$HOME/bin"
    "$HOME/.local/bin"
  ];
  home.sessionVariables = {
    "EDITOR" = "vim";
  };
  home.shellAliases = {
    "ls" = "ls --color";
  };
}
```
This ensures a consistent environment across your setups.
### Configuring Programs and Files

Home-Manager supports configuration files for various programs. For instance, here’s how you can configure Git:

```
{
  programs.git.enable = true;
  programs.git.userName = "Your Name";
  programs.git.userEmail = "youremail@example.com";
}
```
This generates a `$HOME/.config/git/config` file with the following content:
```ini
[user]
        email = "youremail@example.com"
        name = "Your Name"
```
Additionally, you can generate any custom configuration file using the [`home.file`](https://nix-community.github.io/home-manager/options.xhtml#opt-home.file) attribute.

### Conclusion
Home-Manager combined with Nix transforms managing your development environment into a simple, declarative process. By centralising and standardising your configurations, you can ensure a consistent and reproducible setup across devices, saving time and reducing frustration.