How should I manage my packages with nix on NixOS/non-NixOS

Hi,

I’m a bit overwhelmed on how to use Nix package manager on my system. Now that might sound silly, but bear with me :slight_smile:

I absolutely love Nix and don’t want to spark any holy war here. My approach is purely practical and I use what is more convenient regardless whether it solves actual problems or brings other issues.

I want to manage my nix packages on non-NixOS using a single git repo that controls what is installed, gives me a convenient way to customize packages (overrides, like PAM shimming) and for some packages allow to configure them declaratively. My rough understanding of options I have is below:

  • nix-env - this is the “rolling-distro” channel way to do it - can I just have a repo to declare my packages with just nix-env?
  • flakes - this is just nix profile and dependency lock (like rust Cargo.lock, requirements.txt in python etc). I immediately went this way because of how nix shell works (I understand that nix-shell is for development and requires reproducible bash env, but I’m looking for a way to run a temporary package I don’t want to keep and I want it to run in my comfy zsh setup). My current flow is I have a repo with my poor man’s flake, that declares a bunch of packages, a bunch of overrides. whenever I modify this flake I issue nix profile upgrade myflake and changes are reflected in my system. this mostly works fine, but I have no idea how can I manage configuration of each package this way and from time to time I issue nix profile add nixpkgs#something and forget about it :smiley:
  • home manager - I havent tried this approach for two reasons: first I don’t want to manage all my dotfiles with nix (yet). too much overhead to port them. another reason is that even Home Manager docs mention it brings some serious complexity to the table and debugging is non-trivial often.

I’m looking both for advice which way is more optimal and for examples of how you guys do this.

Is anyone using a single flake to manage nix packages as with Home Manager? I’d love to have a peek :slight_smile:

Are you doing same thing without flakes and find it optimal - please show me!

Anyone rocking a home manager setup that takes care of just a couple of dotfiles and rest is managed old fashioned way (git repo, homesick etc)?

It’s a weird item in the docs. I believe it’s just there because home-manager is practically unmaintained from a vision perspective; the original maintainer doesn’t really seem to have the time these days, so the docs stay pretty much untouched. The note would make sense if there were legitimate alternatives, but there are none (besides arguably hejm, but I’m trying to send you down the trodden path, not the confusing homebrew or cutting edge options that will make you hate nix).

The other two approaches will run you down the path of implementing home-manager from scratch; that certainly isn’t any easier. nix-env is famously a bundle of footguns, and even nix profile is very imperative and will eventually give you headaches.

Just try out home-manager; you don’t have to manage all your dotfiles with it, you can stick to only using the home.packages option. Removing it is easy if you don’t like it.

Remember not to overlook the note that says you need to source a shell script in your .bashrc if you don’t want to manage your shell init with home-manager; this is necessary to pull your home-manager binaries into $PATH and such.

4 Likes

Thanks! I’ll give it a try then!

Minimalist option (mostly works for me):

  • No flakes, home-manager, whatever
  • By default dotfiles live in their own repository as static files and get symlinked into their target locations
  • buildEnv is used to construct the environment with all the software
  • If I need to inject a store path in to config, fine, I do some kind of cheap templating (Nix eval time or sed at build time) to create a trivial virtual package to provide this config (and then I manually symlink it to the target location)
  • Actually I build multiple environments to be able to update some stuff quickly without the heavy stuff delaying the update
1 Like

I already ran into issues with home-manager. official install uses channels and then home-manager complains about version mismatch with nixpkgs. Since I don’t want to remove all my flakes (I’m actively using niri for example) I added it to flakes, but then home-manager binary is nowhere to be found.

Initially I thought of Nix as of neovim. Everybody uses a more or less complex config. If you want you can start from scratch and minimal or use a ready framework like home-manager. But I’m already overwhelmed with complexity and haven’t even started configuring home-manager.

I asked LLM how to add it so I added this to my flake:

inputs = {
(...)
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";  # This ensures version alignment
    }; 
}

  outputs = { self, nixpkgs, pam-shim, home-manager, noctalia, ... }: 
    let
      homeConfigurations."myactualusername" = home-manager.lib.homeManagerConfiguration {
        pkgs = nixpkgs.legacyPackages.x86_64-linux;  # adjust architecture if needed
        modules = [ ./home.nix ];
      };
(...)
      packages.${system}.default = pkgs.buildEnv {
        name = "my-shit";
        paths = with pkgs; [
(...)
home-manager
(...)
];
}
(...)

I don’t mind reimplementing some home manager functionality just to better understand Nix, but damn I just don’t know where to start and the easiest way would be to look at similar configs of other people.

I was hoping for a flow that works like this: clone the repo with flake/config. run command → everything is set up. But now I need to run several commands just to get home-manager up and running etc. How do you solve this guys?

Also what is really problematic is that there is nothing like std lib for Nix language. People just refer some modules out of nowhere. I wish there were docs similar to Rust ones, where you can just search symbol name and you get the info what it does.

Not exactly, the docs are just badly structured. The llm is giving you silliness, don’t use that code as-is.

See this heading for a flake-based setup with a template: Home Manager Manual (anchor link, see the URL if it doesn’t put you deep down in the document).

Note you always want the “standalone” docs.

Once you’re set up it should basically just look like (assuming you use stable):

$ nix run home-manager/release-25.11 -- switch --flake github:tlater/my-repo 

This also auto-clones your repo. If you want to edit it locally, you’ll have to clone it somewhere and replace the github: link with its location on disk or .# if you’re in the project directory.

If you use unstable, replace the release-25.11 with master. But this is when you’re set up, you’ll first have to get your configuration in a state that makes this possible - the template should get you almost all the way there.

You’d be having the same issues with a buildEnv-based setup; you just don’t understand the ecosystem well enough to know how to bootstrap yet, it’s quite simple once you grok it.


There is. We have something similar to Rust’s core in builtins: Built-ins - Nix 2.33.1 Reference Manual

The closest to std is nixpkgs.lib.

Ask and ye shall receive: https://noogle.dev/

Though the docs are of much lower quality, as historically there were no doc comments, and the work of adding them to everything hasn’t been completed. Often you’ll just need to click the source link and read the code.

Nix predates Rust by a good decade, people didn’t have development figured out as well yet back then.

4 Likes

Wow, this is awesome! It bootstrapped a flake and home.nix in ~/.config/home-manager and the command that installs it and grabs from repo is even better than I thought (no need to clone stuff first)!

Thanks for being so patient man! Reference is great, I’m ok with reading the code - it’s fun <3 OMG, this should be a tutorial on Nix frontpage as a gateway drug for people :smiley:

1 Like

I can’t express how awesome and liberating home manager + flake is. I stumbled upon this “starter config” and moved overlays to separate module. I even added bubblewrap sandbox wrapper as overlay to several packages with nix-bwrapper. I’m getting same “this must be alien technology” vibes as when I first dug into Rust - brilliant!

Now I’m sure I’ll migrate everything to NixOS, but before this happens I’ll be in this dual-distro-scenario - some systems are NixOS whereas others are other distro with Nix. I would like to be able to configure any my system with this single unit of a flake and I’ve seen some examples of flakes that do just that. The only thing I can’t grasp is to how to make this flake dual-use so it will do full system config on NixOS, but will only do home-manager config on non-NixOS. I’d be super grateful for pointing me in the right direction :slight_smile:

Can’t you have single-use home-manager-configuring flake, and NixOS-configuring flake that uses it?

1 Like

It’s a little more tricky because home-manager.lib returns a standalone configuration, but you need a module for NixOS. The solution is simply to import the same module from both entrypoints, though.

1 Like

Absolutely - I’m just asking you what is your take, since I’m inexperienced :slight_smile: this was my mistake with rust - there is no single place with design patterns that you can refer to and I did not ask people around and my first programs could have been much better :slight_smile:

Ah, right - since the entrypoint in both usecases is different - nixos-rebuilt does not use homeConfiguratons."myuser" unless I pass it as ‘hash variable’, but it will use the module?

Like on NixOS I would:
sudo nixos-rebuild switch --flake .#nix-os-host

and on other distro:
home-manager switch --flake .#myuser

?

That’s the plan.

I don’t know what you mean by this term.

I meant .#nix-os-host part :slight_smile:

Sorry, forgot about this thread.

nixos-rebuild will only look at the entries that are in nixosConfiguration. It will not use the home-manager module in homeManagerModules - you have to import the module separately with home.users.<username>.

Actually, as long as you name the attribute correctly you can skip the attribute name in both cases:

nixos-rebuild switch  --flake .# --sudo
home-manager switch --flake .#

nixos-rebuild will automatically use the nixosConfigurations.<hostname>, while home-manager will automatically use homeManagerConfigurations.<username>.

home-manager is also smart enough to include the hostname, but I forget the exact syntax.

1 Like