Dealing with home manager

Hello.
I recently install NixOS and wanna set some configs into HOME directory and looks like home manager is perfect solution for this. But i can’t understand how i need to use only for setup configs?
For example, i want setup this theme for GTK application: Vortex-GTK - Gnome-look.org.
Or other example, i want to setup config for my wm (Bspwm) and some other applications (picom, feh).
There is my old config, that i use on arch for bspwm (bspwmrc):

#! /bin/sh

export _JAVA_AWT_WM_NONREPARENTING=1
export AWT_TOOLKIT=MToolkit

picom --config ~/.config/picom/picom.conf &

feh --bg-fill ~/wallpapers/first.png

polybar &
flameshot &
discord &

setxkbmap "us,ru" ",winkeys" "grp:caps_toggle" &

pgrep -x sxhkd > /dev/null || sxhkd &

bspc monitor -d 1 2 3 4 5 6

bspc config active_border_color '#5C9C5A'
bspc config normal_border_color '#3C663B'
bspc config focused_border_color '#5C9C5A'

bspc config border_width         2
bspc config window_gap          13

bspc config split_ratio          0.52
bspc config borderless_monocle   true
bspc config gapless_monocle      true

And it works good, but i setup it directly into Home folder not via Home manager. How i should setup something like this via home manager?

I setup my home manager as NixOS Module, like this:

{
  imports =
    [
      ...
      ./home-manager.nix
    ];
    ...
}

Here is home-manager config:

{ config, pkgs, ... }:
let
  home-manager = builtins.fetchTarball "https://github.com/nix-community/home-manager/archive/master.tar.gz";
in
{
  imports = [
    (import "${home-manager}/nixos")
  ];

  home-manager.users.zaksen = {
    home.stateVersion = "25.05";
    programs.home-manager.enable = true;
  };
}

Firstly, instead of setting up home-manager the way you do now, do this:

# configuration.nix
let
  home-manager = pkgs.fetchFromGitHub {
    owner = "nix-community";
    repo = "home-manager";
    # By the way, set this to release-25.05 if you're using stable
    rev = "master";
    # Update this when nix tells you the hash; whenever you update
    # your system, manually set it back to `lib.fakeHash` first
    hash = lib.fakeHash;
  };
in {
  # ...
  imports = [
    (import "${home-manager}/nixos")
  ];

  home-manager.users.zaksen = import ./home.nix;
}
# home.nix
{
    home.stateVersion = "25.05";
    programs.home-manager.enable = true;
}

With your configuration, due to your use of builtins.fetchTarball, your system will be rebuilt every two hours, and you simply cannot rely on it being reproducible because the source literally changes every two hours and there’s no reference to what version you actually fetched. Always specify hashes, and avoid using the builtin fetchers because they don’t give you newbie guardrails.

That said, this still risks you missing updates, or at least makes them tedious. What I’d really recommend is using niv to fetch home-manager instead of doing it manually, so that you can also reasonably update it. That, or just use the channel as instruced here: Home Manager Manual

Importing from a tarball is generally a hack, and should be avoided. It’s a newbie footgun, really, I hate that so many people recommend it just because they want to avoid explaining how to update systems.

I also suggest specifying home-manager modules in separate files rather than in-line in a NixOS module, because otherwise you’ll quickly run into issues with mixing _module.args between the different module systems. Hence the import above instead of what you’re doing.


Once you’ve fixed those glaring issues, all you need to do is move your bspwmrc to the directory home.nix lives in, and then just add it with xdg.configFile:

# home.nix
{
    home.stateVersion = "25.05";
    programs.home-manager.enable = true;
    xdg.configFile."bspwm/bspwmrc".source = ./bspwmrc;
}

There’s also home.file for stuff that doesn’t follow the XDG spec.

3 Likes

Thank you for such detailed answer. I will reconfigure Home Manager according to your answer. About builtins.fetchTarball, I found it in the Home Manager manual, so I used it as an example from there (Home Manager Manual).

new option. So sdg is preferred than $HOME? any reasons to prefer one over the pother?

XDG is prefered for files read by programs that support it.

1 Like

any advantages of using xdg over home.file?

Yes, given your application supports the XDG spec, it will still find its config as you change xdg.configHome.

1 Like

I can also change the $HOME to point elsewhere right?(assuming I can do it in home maager)
how xdg is better :thinking:

You should not change HOME from within HM. That will end in chaos!

Please go ahead and read about the XDG base directory spec, you will then understand the purpose of xdg.configFile. It does not put files to ~/.config, it puts them to xdg.configHome!

The difference might seem unintuitive at first, but the idea is that programs that support the XDG specification will resolve directory paths from the respective variables. xdg.configHome resolves the variable that apps will use. Sure, by convention usually this variable points to $HOME/.config, but it doesn’t have to. That’s why the difference is subtle but important. If XDG_CONFIG_HOME=$HOME/.cfg, then linking into $HOME/.config is meaningless for XDG compliant programs.