Example: Use nix-flakes with home-manager on non-nixos systems

Hi all,

I just finished converting my system configuration to use flakes. A lot of the help/discourse around flakes has involved using home-manager’s nixos module. This is unfortunately not an ideal solution for those of us that use nix on Fedora, Arch, Ubuntu, etc. I’m using a variant of ryantm’s home-manager template with eelco’s flake-compat in order to use flakes in a way slightly more flexible than setting NIX_PATH in dev-shell.

https://github.com/mjlbach/nix-dotfiles/tree/flakes_home_manager_template

I’ve also redone them in a style using the home-manager built-in helper functions, which is a little more direct
https://github.com/mjlbach/nix-dotfiles/tree/master

2 Likes

if you own the dotfiles and no one will be depending on your Nix expressions; what’s the benefit of Flakes at all?

The benefit of Flakes is in sharing expressions; it makes everything as if it was wrapped in callPackage and you can have specificity of your Nixpkgs commit. I don’t see the cost for home-manager though where you are the sole consumer.

Niv or specificying the nixpkgs commit inline get you as much bang for your buck in home-manager configs.*

  • edit

Personally, I used to use niv to version my nixpkgs checkout, my overlays, etc. Flakes can subsume this functionality, and I think it’s more ergonomic to boot. Not to mention, significantly faster in my experience. It’s also buying into the future direction of the nix ecosystem, and makes integrating with other flakes easier.

This was also something I’d seen asked about on IRC, discourse, discord.

3 Likes

Not sure how ergonomic it is given how complex the solutions are so far :stuck_out_tongue_winking_eye:

In all seriousness, niv so far feels very ergonomic and for cases where I don’t plan to share the derivation feels sufficient.

I oddly find myself very wary to adopt flakes whereas I’m normally the gung-ho person to be on bleeding edge.

(Maybe NixOS itself fills that quota in general lol)

I pretty strongly disagree. Flakes have benefits without requiring sharing code, I think this seen in the number of people converting their personal repos to flakes.

Pure evals, locally fully specified inputs, actual portable reproducability. These have every day benefits beyond idealism. Nearly every other day I see an issue that requires more back and forth and confusion than if flakes were simply being used (the most recent is the one who wants to “reinstall” but wasn’t sure what nixpkgs rev they were on. Just … never an issue with flakes).

Not sure how ergonomic it is given how complex the solutions are so far :stuck_out_tongue_winking_eye:

I can’t figure out what this means?

(And knowing your nixpkgs rev isn’t actually sufficient. You can have random impure imports. You’re affected by local nix configuration and local overlay configurations. This is exactly why flakes is useful and powerful.)

Your example just boils down to fetchUrl with a commit for nixpkgs or niv to manage dependencies.

I see the benefits for shared repositories in defining what’s included (modules vs attributes) but my original claim was that it’s diminishing returns for home-manager.

Sure, and then I specifically listed a number of other flakes features, all of which (can) apply to home-manager builds, all of which come up regularly in the course of supporting users in IRC/Discourse… that are not usually found in non-flake builds.

I’m still curious what is “cost” is that you refer to, or what is “complex” about flakes; I really just don’t understand. It’s the same info you give niv with extra benefits?

I know that a number of people switched to flakes specifically because pure evals lead to faster iteration on configurations.

I will sit down and give nix flakes an honest shot once it makes it into the 2.0 release.
I guess I’m just being grumpy about it :slight_smile:

The “cost” i was referring to is that there is a lot of discussion on how to adopt a pattern that I still can’t point to a single documentation page or blog entry that really spells out the full value add.

3 Likes

I think you can call nix build .#homeManagerConfigurations.<name>.activationPackage to build the package that would be called by home-manager switch

That leaves a ./result/activate you can call to do the switch “manually”.

The flake looks like this:

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  inputs.homeManager.url = "github:nix-community/home-manager";
  inputs.homeManager.inputs.nixpkgs.follows = "nixpkgs";

  outputs = { self, nixpkgs, homeManager }: {
    homeManagerConfigurations = {
      andrew = homeManager.lib.homeManagerConfiguration {
        configuration = { pkgs, lib, ... }: {
          imports = [ ./andrew/home.nix ];
          nixpkgs = {
            overlays = [ emacs.overlay ];
            config = { allowUnfree = true; };
          };
        };
        system = "x86_64-linux";
        homeDirectory = "/home/andrew";
        username = "andrew";
      };
    };
  };
}

Suggests that a home-manager switch --flake is in the pipe at some point, but might be reasonable for now :man_shrugging:

7 Likes

This is a good approach to point out, and I’ve seen this in use. Could you clarify a bit on how you’re structuring overlays that are pass to home-manager? I don’t see where emacs is defined in your inputs, and I also have several non-flake overlays.

Ah yeah that one slipped out of what I pasted in.

emacs is a flake, and is defined as:

inputs.emacs.url = "github.com:nix-community/emacs-overlay";

In a elixir project, I am using nix-elixir, which does not have a flake and took a bit to work out, but it seemed the trick was roughly the following:

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.nix-elixir = {
    url = "github:hauleth/nix-elixir";
    flake = false;
  };

  outputs = { self, nixpkgs, flake-utils, nix-elixir }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          # It seems non-flake inputs should be imported, but this default.nix file contains only an overlay
          overlays = [ (import nix-elixir) ];
        };
2 Likes

Thanks! I provided an example too with some convenient shell functions for switching profiles on upgrades

1 Like