nix-community / home-manager

Manage a user environment using Nix [maintainer=@rycee]
https://nix-community.github.io/home-manager/
MIT License
6.91k stars 1.8k forks source link

[Question] Flakes on a non NixOS system #1510

Closed EdenEast closed 3 years ago

EdenEast commented 4 years ago

I have been looking for a way to convert my dotfiles repository over to nix and found home-manager to be a great way to accomplish this. My current dotfiles repository has the issue of supporting multiple different environments linux, wsl2, and windows. I would like to take advantage of flakes to create multiple flake outputs that I can build depending on where I am. I have not been able to find a way to create a flake file that does not depend on some nixos system dependencies.

I know that you can do something like this with nixos, Is there something similar you can do with just home-manager?

# flake.nix
{
  inputs = {
    # ...
  };

  outputs = {
    nixosConfigurations = {
      machine = lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          # ...
        ];
      };
    };

    machine = inputs.self.nixosConfigurations.machine.config.system.build.toplevel;
  };
}

nix build .#machine

cole-h commented 4 years ago

I believe that's what https://github.com/nix-community/home-manager/blob/9b1b55ba0264a55add4b7b4e022bdc2832b531f6/flake.nix#L10 is intended for, maybe? I've never actually used it, since I am on NixOS, but you might want to give it a shot and experiment.

bnjmnt4n commented 3 years ago

Did anyone ever successfully manage to get a working example of home-manager using flakes on a non-NixOS system? I'm pretty new to Nix and flakes, so I don't have much experience with this, but I will look into it and experiment soon.

cole-h commented 3 years ago

I think flakes on non-NixOS would require support in the home-manager script / tool. One could look to nixos-rebuild's flake support to draw inspiration, but I don't know how well it would translate.

mjlbach commented 3 years ago

This thread has a couple different approaches https://discourse.nixos.org/t/example-use-nix-flakes-with-home-manager-on-non-nixos-systems/10185

EdenEast commented 3 years ago

I have been able to get something working for my configuration a base example would be something like this

# flake.nix
{
  description = "Example home-manager from non-nixos system";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    home-manager = {
      url = "github:nix-community/home-manager/master";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, ... }@inputs: {
    homeConfigurations = {
      wsl = inputs.home-manager.lib.homeManagerConfiguration {
        configuration = ./home/hosts/wsl.nix;
        system = "x86_64-linux";
        homeDirectory = "/home/user";
        username = "user";
      };
    };

    wsl = self.homeConfigurations.wsl.activationPackage;
    defaultPackage.x86_64-linux = self.wsl;
  };
}
nix build .#wsl

For my personal configuration I have modeled it based on @davidtwco excellent configuration. His configuration is well structured and easy to understand. You can also look at my current work in progress configuration

TLATER commented 3 years ago

I suppose a home-manager switch --flake '.#' with a little bit of additional magic to assign the correct configuration from the flake path is all that's missing to make the above a little more user friendly?

Currently you need to manually run ./result/activate, and of course set the correct hostname, which isn't as ergonomic as it used to be.

terlar commented 3 years ago

I currently have a shell script that I add to the flakes devShell, then I hook up the devShell with direnv so I upon entering the project I will get it on my path. All I have to do is to run switch-home.

Here is the script: https://github.com/terlar/nix-config/blob/570134ba7007f68e058855e0d6a1677a9dc3fa27/lib/scripts.nix#L11-L29

  switchHome = writeShellScriptBin "switch-home" ''
    set -euo pipefail
    export PATH=${lib.makeBinPath [ gitMinimal jq nixUnstable ]}
    usr="''${1:-$USER}"

    1>&2 echo "Switching Home Manager configuration for: $usr"

    usrExists="$(nix eval --json .#homeManagerConfigurations --apply 'x: (builtins.any (n: n == "'$usr'") (builtins.attrNames x))' 2>/dev/null)"

    if [ "$usrExists" != "true" ]; then
      1>&2 echo "No configuration found, aborting..."
      exit 1
    fi

    1>&2 echo "Building configuration..."
    out="$(nix build --json ".#homeManagerConfigurations.$usr.activationPackage" | jq -r .[].outputs.out)"
    1>&2 echo "Activating configuration..."
    "$out"/activate
  '';
stale[bot] commented 3 years ago

Thank you for your contribution! I marked this issue as stale due to inactivity. If this remains inactive for another 7 days, I will close this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

If you have nothing of substance to add, please refrain from commenting and allow the bot close the issue. Also, don't be afraid to manually close an issue, even if it holds valuable information.

Closed issues stay in the system for people to search, read, cross-reference, or even reopen--nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

terlar commented 3 years ago

With the latest changes to flakes you can now do this:

{
  description = "Example flake for generic Linux Home Manager usage";

  inputs = {
    home-manager.url = "github:nix-community/home-manager";
  };

  outputs = { self, nixpkgs, home-manager, ... }: {
      apps.x86_64-linux.home-manager = {
        type = "app";
        program = "${home-manager.defaultPackage.x86_64-linux}/bin/home-manager";
      };

      homeConfigurations = {
        my-user = home-manager.lib.homeManagerConfiguration {
          # your config here ...
        };
      };
    };
}

Then you can run:

nix run .#home-manager -- switch --flake .

To switch to your my-user if that is your current user. It will also try $USER@hostname if you have configuration named like that. If you want to switch to a specific config just replace the . with .#nameOfConfig.

If you have Home Manager installed as a package you can run home-manager switch --flake . instead.

Another alternative to nix run is to add the package home-manager to a devShell, then you could run the home-manager command from there.

stale[bot] commented 3 years ago

Thank you for your contribution! I marked this issue as stale due to inactivity. If this remains inactive for another 7 days, I will close this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

If you have nothing of substance to add, please refrain from commenting and allow the bot close the issue. Also, don't be afraid to manually close an issue, even if it holds valuable information.

Closed issues stay in the system for people to search, read, cross-reference, or even reopen--nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.