Make home-manager not use `nix-env -i` for packages

TL;DR: Tired of home-manager being incompatible with nix profile? I didn’t fix that. I just made it also incompatible with nix-env.

I don’t use nix-env for its package management, at all, but home-manager in standalone mode seems to be based on the design that users would still be able to use it for imperative package management. It’s not a bad decision, but I thought to myself, can I get rid of this anyway?

Turns out, yes you can.

{ config, lib, ... }:

{
  home.activation.installPackages = {
    data = lib.mkForce "";
    before = lib.mkForce [];
    after = lib.mkForce [];
  };

  home.file.nix-profile = {
    source = config.home.path;
    target = ".nix-profile";
  };
}

I basically just found the code that’s responsible for nix-env -i and got rid of it (https://github.com/nix-community/home-manager/blob/d119cea3763977801ad66330668c1ab4346cb7f7/modules/home-environment.nix#L587) and replaced it with a simple home.file symlink.

During the switch, I just temporarily removed the .nix-profile symlink. My important packages are on my NixOS system config anyway. What I meant was, nix was in my NixOS configuration, so I was able to nix run home-manager to switch despite not having my ~/.nix-profile for a few minutes, and this didn’t turn out to be a problem.

Now there’s no imperative package management on my machine at all, and package management goes through either home-manager or NixOS, without the help of nix-env -i

3 Likes

HM doesn’t use nix-env for package management, but for profile management.

It is fine that nix-env is used like that.

And even though I’d like to have a choice about nix-env or nix profile being used, completely removing package install through HM is a no go for me, as the majority of my packages are managed per user profiles. There is no reason that my wife and son have to even see Emacs or other very specific stuff in their PATH.

I think there was a misunderstanding.

What I meant is that home-manager builds its own path and uses nix-env -i to merge it into ~/.nix-profile. This way, but it means it unnecessarily uses another profile.

So I decided to cut out this process in the middle and let home-manager directly manage the symlink that is ~/.nix-profile

$ ls -l ~/.nix-profile
lrwxrwxrwx 1 dram users 75 Mar  5 20:02 /home/dram/.nix-profile -> /nix/store/[hash]-home-manager-files/.nix-profile

Packages installed through home.packages still end up in ~/.nix-profile. If anything, this removes package installation that don’t through HM.

By the way I love how nix-env for profiles and generations work. Just a few symlinks, and we have 90% of what’s needed for atomic switching between generations.

I made use of this patch to get home-manager to play nicely with nix (after having run nix profile install ...).
https://github.com/FlorianFranzen/home-manager/commit/4e97b01b2737bb0f39c18a65d87dd98659391b97

My understanding from looking at this patch is it more/less replaces calls of nix-env -i with nix profile install (e.g. in modules/home-environment.nix), in addition to nix-env --profile ... --set ....

The intro for this post is hilarious, and I appreciate it. :joy:

1 Like

I dodged this problem using this function:

nix ()
{
    local subcommand;
    if (( "$#" == 0 )); then
        command nix;
        return;
    fi;
    subcommand=$1;
    shift;
    case $subcommand in
        profile)
            command nix "$subcommand" "$@" --profile $HOME/.nix-profile-new
        ;;
        *)
            command nix "$subcommand" "$@"
        ;;
    esac
}

Basically HM still gets to use ~/.nix-profile and nix profile uses ~/.nix-profile-new. Not ideal, but works for me.

How exactly do you use it ?
– noob