Hello I’m using home manager and trying to import all my separate files in one go with the following script inside my home.nix:
imports = [
''etc/nixos/apps/*nix''
];
If I do them one by one it works but not with *
Hello I’m using home manager and trying to import all my separate files in one go with the following script inside my home.nix:
imports = [
''etc/nixos/apps/*nix''
];
If I do them one by one it works but not with *
Import does no globbing. What you wrote expects a file with the name *nix
.
What you want is implemented e.g. by Haumea: Haumea - Filesystem-based module system for Nix
Hello, I know this may have come as “Feed me the answer with a silver spoon” but I’m quite new at nix space. From what I understand (which is probably wrong) I need a thing called flakes to use Haumea and I haven’t got to using flakes yet. Can you explain the steps I should take a little further? Even if I don’t need to use flakes I still didn’t get the gist of Haumea thingy.
Well, Haumea itself does not rely on Flakes, but Flakes are the most comfortable way to pull Haumea in as a dependency.
Assuming you have imported Haumea (e.g. from its default.nix
) as haumea
, essentially you would start with something like
apps = haumea.lib.load {
src = /etc/nixos/apps/;
inputs = {
inherit (nixpkgs); # or whatever you pass to your individual nix files
};
};
# now apps is an attribute set mapping filenames to what you would have gotten from individual imports
# to flatten it to a list: (map (key: getAttr key apps) (attrNames apps));
@figsoda @blaggacao You can likely provide more insight on using Haumea without flakes and using the imports.
the only difference is that without flakes, all the stuff are directly under default.nix
instead of lib
, so it would be haumea.load
instead of haumea.lib.load
in the haumea repository, import ./. { }
is roughly equivalent to (builtins.getFlake (toString ./.)).lib
No actually I couldn’t even get to importing part since the documentation literally starts with flakes. In fact everything on the documentation is about flakes… I really don’t know what to do.
I really wish there was a way to do regular expressions without Haumea.
you can basically load the nix files with builtins.readDir. builtins.attrNames will result in a list of files of a directory.
So my may get something like that.
nix-repl> builtins.attrNames (builtins.readDir ./profiles/nixos)
[ "base.nix" "desktop.nix" "gaming.nix" "nix.nix" "optimized.nix" "server.nix" "telegraf.nix" "user-config.nix" ]
Which is some logic i am using to load modules in a similar way you are asking for.
So if you dont want do trag in Haumea that may be also a way of doing that.
You can find my thing here. (be aware that i am using flake-parts and that logic is inside some parts glue code)
My usecase is that i want to export modules to the flakes top level, without naming them in some default.nix, as i keep forgetting to update those, to i tried to eliminate that thing.
I highly recommend to not copy random code from the internet (as thats kind of untrustful code ).
Also i am not generally recommending my code here, but it works super fine for me.
Do:
haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) {} ;
# haumea.load ...
Well, technically you can do this without Haumea, but you would have to implement the functionality on your own,…
(you would then probably end up with something similar to this: https://github.com/nix-community/haumea/blob/79fc9824f06bbd80e3f994716c600ba299aafd17/src/load.nix)
I need you to be a little more specific than that, do that to where?
I tried to put the line haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) {} ;
anywhere in my configuration.nix file where I see fit yet none of them worked.
Also you said, # haumea.load ...
so am I supposed to do that on just a rooted terminal?
You need to put that in a let block or make your configuration a recursive attribute set, then you can put that statement in your configuration.
No. You would use the load function in your configuration as I suggested above.
That said, keep the individual listing of files and focus on enjoying working with Nix/NixOS. Once you are more familiar with Nix as a programming language come back to this topic.
Okey so, I had to remove last slash from here because it gave an error:
Also lib didn’t existed so I just removed it and changed it into haumea.load
Yet I’m still having the following error:
error: The option `home-manager.users.user.apps' does not exist. Definition values:
- In `/etc/nixos/configuration.nix':
{
micro = {
programs = {
micro = {
enable = true;
...
I should add none of the lines are in configuration.nix so I’m royally confused.
Could you show us what your configuration.nix
and home.nix
look like now? I feel like we can’t debug this properly if we don’t see the full setup.
For sure!
configuration.nix:
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
<home-manager/nixos>
];
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "nixos"; # Define your hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Enable networking
networking.networkmanager.enable = true;
# Set your time zone.
time.timeZone = "mytimezone";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "en_GB.UTF-8";
LC_IDENTIFICATION = "en_GB.UTF-8";
LC_MEASUREMENT = "en_GB.UTF-8";
LC_MONETARY = "en_GB.UTF-8";
LC_NAME = "en_GB.UTF-8";
LC_NUMERIC = "en_GB.UTF-8";
LC_PAPER = "en_GB.UTF-8";
LC_TELEPHONE = "en_GB.UTF-8";
LC_TIME = "en_GB.UTF-8";
};
# Enable the X11 windowing system.
services.xserver.enable = true;
# Enable the KDE Plasma Desktop Environment.
services.xserver.displayManager.sddm.enable = true;
services.xserver.displayManager.sddm.theme = "sddm-theme-dialog";
services.xserver.desktopManager.plasma5.enable = true;
services.xserver.windowManager.openbox.enable = true;
# Configure keymap in X11
services.xserver = {
layout = "--";
xkbVariant = "";
};
# Configure console keymap
console.keyMap = "--";
# Enable CUPS to print documents.
services.printing.enable = true;
# Enable sound with pipewire.
sound.enable = true;
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
jack.enable = true;
# use the example session manager (no others are packaged yet so this is enabled by default,
# no need to redefine it in your config for now)
#media-session.enable = true;
};
# Enable touchpad support (enabled default in most desktopManager).
# services.xserver.libinput.enable = true;
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users.user = {
isNormalUser = true;
description = "user";
extraGroups = [ "networkmanager" "wheel" ];
packages = with pkgs; [
firefox
kate
musescore
openbox
ly
nix-prefetch
nix-prefetch-github
git
# thunderbird
];
};
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
users.user = import ./home.nix;
};
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
(callPackage /home/user/Downloads/sddm-theme-dialog.nix {}).sddm-theme-dialog
# vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
# services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It‘s perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
}
home.nix:
{ config, pkgs, ... }:
let
haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) {} ;
in
{
apps = haumea.load {
src = /etc/nixos/apps;
inputs = {
inherit (nixpkgs);
};
};
home.username = "user";
home.homeDirectory = "/home/user";
home.stateVersion = "23.05";
home.packages = with pkgs; [
htop
micro
];
}
I changed some data such as, username and region so they are not actually broken It’s just for privacy reasons.
Ahhh right I see. I think the confusion comes from what haumea.load
actually returns and what you wanted to do with it.
This is entirely accurate, that option doesn’t exist in home-manger, but nix is evaluated lazily, so the error message triggers later than you might expect. Specifically:
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
users.user = import ./home.nix;
};
The last line here just tells Nix that home-manager.users.user
should evaluate to whatever is in home.nix
. But this happens before Nix tries to find out what home.nix
even contains. home.nix
is not fully evaluated on import. This is a little surprising, but luckily we know that home-manager.users.user.apps
is not defined in configuration.nix
, but home.nix
, so we can look for the issue there.
So, what does haumea.load
actually return? I would really recommend you try this stuff out yourself so you can get a better understanding of how the language works, but just for illustration, I created a small example:
$ tree haumea-test
haumea-test
├── a-set.nix
├── first.nix
├── second.nix
└── somepkgs.nix
$ for f in haumea-test/*; do echo "$f:"; cat $f; echo; done
haumea-test/a-set.nix:
{ }: { help = "Please talk to your manager."; truth = "1+1=2"; }
haumea-test/first.nix:
1
haumea-test/second.nix:
{ }: 2
haumea-test/somepkgs.nix:
{ pkgs }:
with pkgs; [
vim
hello
jq
]
And now, I’ll import this with haumea in nix repl
so we can inspect it a little bit:
$ nix repl '<nixpkgs>'
warning: future versions of Nix will require using `--file` to load a file
Welcome to Nix 2.15.1. Type :? for help.
Loading installable ''...
Added 16207 variables.
nix-repl> haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) { inherit lib; }
nix-repl> x = haumea.load { src = ./haumea-test; inputs = { inherit pkgs lib; }; }
Note that at this point, haumea wasn’t even downloaded yet! This is a great example of lazy evaluation.
The variable haumea
exists and we have defined what it should contain, but we never looked at it. We also defined x
which will evaluate to the result of calling haumea.load
, but we never looked at that result either, so Nix had no need to actually check what haumea.load
even is. This is the reason that a huge Nix expression like nixpkgs can even exist, and the reason why Nix has its own language as opposed to re-using an existing language.
Anyway, let’s continue and actually evaluate x
now (output formatted manually):
nix-repl> :p x
{
a-set = {
help = "Please talk to your manager.";
truth = "1+1=2";
};
first = 1;
second = 2;
somepkgs = [
«derivation /nix/store/n3xngbhk3adgfmn2y75gi7n581jyiach-vim-9.0.1562.drv»
«derivation /nix/store/8rgfc52k0529kypam0jy5p1a4jsj4dbq-hello-2.12.1.drv»
«derivation /nix/store/chx4kpsg2wahdmzv80gzfn4hnxfafvqr-jq-1.6.drv»
];
}
So as you can see, haumea basically takes all .nix
files in the directory you specify, and put the results of evaluating them into a set, where the key for each result is the name of the file it came from. If the file evaluates to a function, it will call that function with the arguments you supplied via inputs
. In your case, that definition was also erroneous:
This evaluates to an empty set, see “Inheriting Attributes”.
I don’t know what the structure of your files in /etc/nixos/apps
is, but I assume they are also functions that take some inputs, potentially pkgs
and lib
?
You wrote in your initial post that you’re just trying to import the files:
So I assume instead of setting the option apps
, you set imports
. Just make it clear, while it doesn’t look like it, adding a string to imports
basically works the same as if you imported the file directly. So we now have two options:
haumea.load
into a list so imports
understands ithaumea.load
so it only outputs the paths for each fileWhile the second can be achieved, the first is much simpler now that we’ve got haumea.load
to work; we can just use builtins.attrValues
. And so the final code in your home.nix
would look like this:
{ config, pkgs, lib, ... }:
let
haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) { inherit lib; } ;
apps = haumea.load {
src = /etc/nixos/apps;
inputs = {
inherit pkgs; # Not sure if this is correct, see below
};
};
in
{
imports = builtins.attrValues apps;
home.username = "user";
home.homeDirectory = "/home/user";
home.stateVersion = "23.05";
home.packages = with pkgs; [
htop
micro
];
}
As I said, I don’t know what the structure of the files in /etc/nixos/apps
is, so potentially you need to change how inputs
is specified.
Finally, if you’re wondering how the hell you should’ve figured this out yourself, I want to point you at two awesome resources: MyNixOS where you can search for home-manager and NixOS options easily, and noogle, which will help you find useful functions like the builtins.attrValues
we used above.
Hope this helps! Stay strong in your learning journey, it’s absolutely worth it!
Thank you! Just had to type:
{ config, pkgs, lib, ... }:
instead of:
{ config, pkgs, ... }:
and change:
haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) { inherit lib; } ;
to:
haumea = import (builtins.fetchGit https://github.com/nix-community/haumea?rev=v0.2.2) { inherit pkgs.lib; } ;
I hope this will be helpful for everyone!
Also thanks for noogle and mynixos, they certainly will come in handy.
I guess you mean the other way around? But yeah, good point, what I wrote wasn’t syntactically correct. I edited my post.
Alternatively, you could use
haumea = import (builtins.fetchGit ...) { inherit (pkgs) lib; } ;
Anyway, glad to hear that it’s working now!