Ok, so there are a lot of things going on here. I think these are the issues:
- You’re very confused about the NixOS module system and how it works
- You’re severely over-engineering your overlays because the flakes book recommends something way over-the-top for your use case
- You’re unnecessarily trying to write an overlay system to add a package to your
nixosSystem
- You seem to have some kind of invisible UTF character in your args list or a non-standard argument in a derivation you’re
callPackage
-ing
- or the flakes book’s example is wrong, but I think their mess is barely still correct
Let’s start with 4. You say this is the error:
Note it says 'pkgs
? Did you write 'pkgs
instead of pkgs
in ./../../pkgs/GTK-Midnight/default.nix
?
If not, is there some weird character in front of the pkgs
in overlays/GTK-Midnight/default.nix
?
The code as you’ve written should be working otherwise. But you’re desperate, so let’s simplify.
Next up, 2. If you really only have this simple of an overlay, it’s completely overkill to go through all that effort. Just add this to your host config:
# ./hosts/asahi-mac/default.nix
# If you already use arguments for this module, keep them of course.
{ pkgs, ...}: {
nixpkgs.overlays = [
# Using prev: final: because that's a much clearer abstraction when
# you know what overlays do
(prev: final: {
# Using final because we want to use `callPackage` from the *final*
# nixpkgs, i.e., the one that comes out after all overlays were applied
gtk-midnight = final.callPackage ./../../pkgs/GTK-Midnight {};
})
# You can add more overlays here, if you like
];
environment.systemPackages = with pkgs; [
gtk-midnight
];
# Other contents of the file mostly don't matter for this example
}
Assuming your ./../../pkgs/GTK-Midnight/default.nix
file isn’t inherently broken, this should work.
Next up, 3. AIUI, you’re using an overlay to create pkgs.gtk-midnight
. This is not necessary - there’s no need to register your downstream package with pkgs
at all. Let’s just add your package to environment.systemPackages
and skip the overlay:
# ./hosts/asahi-mac
{ pkgs, ... }: {
environment.systemPackages = [
(pkgs.callPackage ./../../pkgs/GTK-Midnight {})
];
}
Since you’re using a flake, you could go a step further and create self.packages.${system}.gtk-midnight
, and then do something like this:
{ pkgs, self, ... }: {
environment.systemPackage = [
self.packages.${pkgs.system}.gtk-midnight
];
}
That would be by far the cleanest implementation. Happy to help with that if you need a hand.
Then, 1. 1 is more complex. I’ve explained this a couple of times over the years, but I can’t seem to find my big long posts on the topic, so here we go again:
Fundamentally, NixOS modules (i.e., the stuff you’re supposed to pass to modules
up there) are just attrsets (read: fancy JSON objects, or the stuff between {}
). NixOS takes all modules you define, and combines them into one big attrset, which it then uses as input to write a script that makes the system you defined.
Modules can be written like this:
{
imports = [
# Paths of other modules that should be merged into this one here
];
options = {
# Custom option definitions here
};
config = {
# Settings for defined options in this or other modules here
};
}
Alternatively, you can skip the options
definition, and only specify configuration settings:
{
imports = [
# Paths of other modules that should be merged into this one here
];
# Settings for defined options in this or other modules here
}
NixOS will also pass arguments to any modules that are defined as functions:
# Note the ellipsis (`...`) just means "don't error out if other arguments
# are given"
#
# NixOS will put any arguments in `_modules.args` in your module's function
# arguments. This includes things passed in via `specialArgs`, but also some
# default things like `pkgs` and `config`.
#
{config, lib, pkgs, ...}: {
imports = [
# Paths of other modules that should be merged into this one here
];
# Settings for defined options in this or other modules here
}
This is all there is to NixOS modules.
This is importantly very different from derivations (package definitions) or overlays. NixOS modules are their own little mini-ecosystem in the nix world, so their syntax and conventions are very different.
This is why the following won’t work:
If I rewrite that to look more like a module it’s something like this:
# We've replaced the attrset input with specific attrset components with a
# pure `args` variable we can't look inside of, but it's still given an
# attrset with the contents of `_module.args`
args: {
nixpkgs.overlays = [
import ./overlays/GTK-Midnight
];
}
Note that your overlays/GTK-Midnight/default.nix
file is also a module. You’re import
-ing it, which will make nix place the contents right in there:
# We've replaced the attrset input with specific attrset components with a
# pure `args` variable we can't look inside of, but it's still given an
# attrset with the contents of `_module.args`
#
# We could also write:
#
# { config, lib, pkgs, ...} @ args: {
args: {
nixpkgs.overlays = [
(
{ config, lib, pkgs, ... }:
(self: super: {
gtk-midnight = super.callPackage ./../../pkgs/GTK-Midnight {};
})
)
];
}
Obviously this doesn’t work, because nixpkgs.overlays
wants a list of overlays, not a list of modules.
We could make it work if we wanted to, by calling the first level of functions with the args
input (and thereby “consuming” the first level of indirection and giving nixpkgs.overlays
a function it knows what to do with):
args: {
nixpkgs.overlays = [
((
{ config, lib, pkgs, ... }:
(self: super: {
gtk-midnight = super.callPackage ./../../pkgs/GTK-Midnight {};
})
) args)
];
}
But you’re not even using the config, lib, pkgs
in your overlay, so I propose we just write a sane overlay instead and forget about the args:
{
nixpkgs.overlays = [
(self: super: {
gtk-midnight = super.callPackage ./../../pkgs/GTK-Midnight {};
})
];
}
Honestly IMO the flakes book you’re reading is making a huge mistake trying to turn overlays into quasi-modules by passing the module args into them. It’s no wonder you can’t keep the two concepts apart when they’re forcibly mixing them. Not to mention that unreadable auto-file-import function.
I’ll probably stop recommending that book, this is just insane - no newbie should reasonably be expected to deal with this.