Nix language newbie here. After some struggle and looking at a lot of places, I was able to create an initial, single flake.nix file with a basic home-manager configuration for myself, that downloads and install a simple flake from github:
Itās apparently working, but I have some questions, mostly related to the language:
Is there a way to avoid repeating the execpermfix reference? I put it in the inputs, but then I have to bring it over in 3 places.
Is there a way to make this system-agnostic? I wonder if I could just put the same file in a raspberry pi and get the same environment.
Is there a way to explicitly define home inside modules instead of creating a variable and referencing it? I think in most places that sequence has been kept in a separate file and imported - Iām wondering if we could do the exact opposite.
So to answer the questions 1 and 3, sure. You just need to repeat execpermfix in the input ando output function, the other ones can be removed. extraSpecialArgs is only useful in you load a module from another file. Here since the variable is defined above in the file (or closure to be more precise) you can just refer to it without using any variable. And for 3, yes, just do it This way you can simplify the above file like this (not tested):
Regarding the second question, you cannot directly make the homeConfiguration system-agnostic as pointed out in this issue. However, you can āfake itā by creating a loop to create an entry myuser-${system} for instance. This flake makes it particularly easy to do by providing a list of systems. So your code would become like this (not tested, I hope I donāt have too much typos):
Until the above issue is resolved I donāt think we can get a much better solution (at most you can also certainly write .#x86_64-linux.myuser if you prefer a doc by modifying accordingly homeConfigurations.${system}.myuser). Note that I canāt test this right now but I see no reasons for a failure except minor typos.
Since recently Iām happily using this āhackā (which may be over-engineered a bit but the objective is to be able to let other users on my systems manage their own home configs (later) without admin rights):
In the flake:
homeConfigurations = (
import ./home/hm-builder.nix {
inherit (inputs) nixpkgs nurpkgs nixpkgsUnstable home-manager;
inherit (nixpkgs) lib;
inherit (home-manager);
# TODO:See this: https://discourse.nixos.org/t/nixos-custom-module-configuration-with-flakes-and-home-manager/17360/5
# This means we don't need this hocus pocus? Or is this only valid if HM is used as a NixOS module, which we don't do
# to support users independently updating their own HM config (without root access)
systemConfigs = inputs.self.nixosConfigurations /* // inputs.self.darwinConfigurations*/;
}
).getHMConfigs; # all top level user names (dirs) under ./home will be used and paired with hostnames if the user is defined in the host definition
hm-builder:
homeConfigurations = (
import ./home/hm-builder.nix {
inherit (inputs) nixpkgs nurpkgs nixpkgsUnstable home-manager;
inherit (nixpkgs) lib;
inherit (home-manager);
# TODO:See this: https://discourse.nixos.org/t/nixos-custom-module-configuration-with-flakes-and-home-manager/17360/5
# This means we don't need this hocus pocus? Or is this only valid if HM is used as a NixOS module, which we don't do
# to support users independently updating their own HM config (without root access)
systemConfigs = inputs.self.nixosConfigurations /* // inputs.self.darwinConfigurations*/;
}
).getHMConfigs; # all top level user names (dirs) under ./home will be used and paired with hostnames if the user is defined in the host definition
home.nix in this is not a per-user file, but more of a common ālibraryā that scans all configs in the home/<user>/<hostname> directory and builds the userās config from that. The reason to do this is that a user can link common configs between different <hostname> dirs as necessary, as well as using host-specific settings simply by having a file defining these in the correct place.
{ pkgs
, unstable
, username
, homeDirectory /* ? pkgs.config.homeDirectory */
, hostname
, lib ? pkgs.lib
, ... }:
let
inherit (import ../util.nix { inherit lib; }) listFilesRecFollow;
# simply find the first (most specific) match for the config tree
cfgsrcroot = with builtins; base: host: user:
head (filter (p: pathExists p) [
(base + "/${user}/${host}")
# TODO: handle host profile first (before default)
# These should probably be incremental? I.e. use mkDefault and be overriden by host-specific attributes?
# In fact, we could also do this for the user default, which is then a common config, and we only symlink and/or add
# specific configs for overriding or adding it. This avoids making a large number of symlinks, at the slight cost of some transparency
(base + "/${user}/default")
]);
in
{
imports = [
./switch.nix # put the switch script (to apply this flake for system and HM config) in the user's ${HOME}/.local/bin
] ++
# just "linearly" import all default.nix under the config dir.
# This implies that default.nix may not import another default.nix in the same config root
/* lib.debug.traceValSeq */ (with builtins; (filter (f: (baseNameOf f) == "default.nix" ) (listFilesRecFollow (cfgsrcroot ./. hostname username))));
# ++ (map (key: lib.getAttr key pkgs.extraModules) (lib.attrNames pkgs.extraModules)); # include extraModules used in overlay (for vscode-server)
home.sessionPath = [ "${homeDirectory}/bin" ]; # add to PATH
home.sessionVariables = {
NIX_PATH = "nixpkgs=${pkgs.outPath}:unstable=${unstable.outPath}";
};
fonts.fontconfig.enable = true;
home.username = username;
home.homeDirectory = homeDirectory;
home.stateVersion = "21.11";
}