23 Aug 2024 |
mr-qubo | I'm trying to write nixos config where I can set nixos options from home-manager modules. But I can't get around infinite recursion errors. I wrote this nixos module, I though this should work, but I'm still getting infinite recursion error, which I don't know how to debug.
{ lib, options, ... }:
with builtins; with lib;
let
hmModuleBase = with options.home-manager.users.type.nestedTypes.elemType.functor.payload; evalModules {
inherit class specialArgs;
modules = modules ++ [{
options.MrQubo = {
osConfigs = {
type = options.raw;
};
};
}];
};
evalHmModule = module:
hmModuleBase.extendModules { modules = [ module ]; };
isImportableNV = { name, value }:
(value == "regular" && match ".*\\.nix" name != null) || (value == "directory" && (readDir "${localOverlays}/${name}") ? "default.nix");
parseNV = { name, value }: rec {
username = removeSuffix ".nix" name;
module = evalHmModule ../users/${name};
};
userModules = map parseNV (filter isImportableNV (attrsToList (readDir ../users)));
osConfigs = flatten (map (attrs: attrs.module.MrQubo.osConfigs) userModules);
hmUsersConfig = {
home-manager.users = listToAttrs (map (attrs: { name = attrs.username; value = attrs.module; }) userModules);
};
in mkMerge (osConfigs ++ [ hmUsersConfig ])
| 13:15:22 |
25 Aug 2024 |
Matt Sturgeon | Robert Hensing (roberth) thanks for your thoughts here, I figured I'd reply here to save derailing that PR's discussion 😁
I just had a quick look in the repl, and highestPrio seems to be 1500 when an option is undefined such that it is using it's default value.
So we could have an isOptionDefault , but it wouldn't be able to distinguish between a default passed to mkOption and a config definition wrapped using mkOptionDefault .
Maybe that'd be the intended behavior though? 🤔
This also begs the question of how an override priority above 1500 should be handled, though I guess that's off-topic!
| 14:53:57 |
Matt Sturgeon | * Robert Hensing (roberth) thanks for your thoughts here, I figured I'd reply here to save derailing that PR's discussion 😁
An isDefinedExplicitly option attr, true when isDefined , but without using the default .
This can also be achieved with a function from option to bool, by looking at the highestPrio attribute.
I just had a quick look in the repl, and highestPrio seems to be 1500 when an option is undefined such that it is using it's default value.
So we could have an isOptionDefault , but it wouldn't be able to distinguish between a default passed to mkOption and a config definition wrapped using mkOptionDefault .
Maybe that'd be the intended behavior though? 🤔
This also begs the question of how an override priority above 1500 should be handled, though I guess that's off-topic!
| 14:54:18 |
26 Aug 2024 |
nbp | The infinite recursion comes from the fact that osConfigs might contain home-manager user configurations.
I suggest to explicitly the top-level attributes that can be set to exclude users ;
osConfigs' = flatten …;
# Generate an error if `users` is set.
osConfigs = ({programs? {}, services? {}}: {
inherit programs services;
}) osConfigs';
| 09:46:27 |
nbp | * The infinite recursion comes from the fact that osConfigs might contain home-manager user configurations.
I suggest to explicitly the top-level attributes that can be set to exclude users ;
osConfigs' = flatten …;
# Generate an error if `users` is set.
osConfigs = ({programs? {}, services? {}}: {
inherit programs services;
}) osConfigs';
| 09:46:35 |
nbp | * The infinite recursion comes from the fact that osConfigs might contain home-manager user configurations.
I suggest to explicit the top-level attributes that can be set to exclude users ;
osConfigs' = flatten …;
# Generate an error if `users` is set.
osConfigs = ({programs? {}, services? {}}: {
inherit programs services;
}) osConfigs';
| 09:46:57 |
27 Aug 2024 |
Matt Sturgeon | removeAttrs osConfigs [ "users" ] may also work? | 21:00:47 |
30 Aug 2024 |
| (artur 'manuel) joined the room. | 08:11:32 |
mr-qubo | In reply to @mr-qubo:matrix.org
I'm trying to write nixos config where I can set nixos options from home-manager modules. But I can't get around infinite recursion errors. I wrote this nixos module, I though this should work, but I'm still getting infinite recursion error, which I don't know how to debug.
{ lib, options, ... }:
with builtins; with lib;
let
hmModuleBase = with options.home-manager.users.type.nestedTypes.elemType.functor.payload; evalModules {
inherit class specialArgs;
modules = modules ++ [{
options.MrQubo = {
osConfigs = {
type = options.raw;
};
};
}];
};
evalHmModule = module:
hmModuleBase.extendModules { modules = [ module ]; };
isImportableNV = { name, value }:
(value == "regular" && match ".*\\.nix" name != null) || (value == "directory" && (readDir "${localOverlays}/${name}") ? "default.nix");
parseNV = { name, value }: rec {
username = removeSuffix ".nix" name;
module = evalHmModule ../users/${name};
};
userModules = map parseNV (filter isImportableNV (attrsToList (readDir ../users)));
osConfigs = flatten (map (attrs: attrs.module.MrQubo.osConfigs) userModules);
hmUsersConfig = {
home-manager.users = listToAttrs (map (attrs: { name = attrs.username; value = attrs.module; }) userModules);
};
in mkMerge (osConfigs ++ [ hmUsersConfig ])
My second attempt:
{ lib, ... }:
with builtins; with lib;
let
isImportable = { name, value }:
(value == "regular" && match ".*\\.nix" name != null) || (value == "directory" && (readDir "${localOverlays}/${name}") ? "default.nix");
parseUser = { name, value }: rec {
username = removeSuffix ".nix" name;
module = ../users/${name};
};
users = map parseUser (filter isImportable (attrsToList (readDir ../users)));
evalHmModule = { username, module, config, pkgs, ... }:
(import <home-manager/modules> {
configuration = {
options.MrQubo = {
osConfig.services = mkOption {
type = types.raw;
};
};
config = {
submoduleSupport.enable = true;
submoduleSupport.externalPackageInstall = false;
home.username = config.users.users.${username}.name;
home.homeDirectory = config.users.users.${username}.home;
# Make activation script use same version of Nix as system as a whole.
# This avoids problems with Nix not being in PATH.
nix.package = config.nix.package;
};
};
inherit pkgs;
}).extendModules {
modules = [
{
MrQubo.osConfig.services = config.services;
}
module
];
};
osConfigModules = flip map users (user: { pkgs, config, ... }:
{ config.services = (evalHmModule ({ inherit pkgs config; } // user)).config.MrQubo.osConfig.services; }
);
in {
imports = osConfigModules;
}
It still doesn't work, even with just "services" option. I get
… while evaluating the option `services.sftpgo.user':
error: infinite recursion encountered
| 11:26:33 |
nbp | mr-qubo: I do not have enough information with what you copied to give you any answer, apart that I do not see any reasons for an infinite recursion in this file. | 12:47:17 |
mr-qubo | In reply to @nbp:mozilla.org mr-qubo: I do not have enough information with what you copied to give you any answer, apart that I do not see any reasons for an infinite recursion in this file. I run it with nixos-rebuild -I nixos-config=$(pwd)/users-impl.nix dry-build --show-trace . ./user-impl.nix is the name of the file contents which I pasted. You also need to put some file in ../users/ dir. I have nix.nix file with those contents:
{
home.stateVersion = "23.11";
}
home.stateVersion is needed, otherwise there's a different error from home-manager.
| 16:33:27 |
mr-qubo | In reply to @nbp:mozilla.org mr-qubo: I do not have enough information with what you copied to give you any answer, apart that I do not see any reasons for an infinite recursion in this file. * I run it with nixos-rebuild -I nixos-config=$(pwd)/users-impl.nix dry-build --show-trace . ./user-impl.nix is the name of the file contents which I pasted. You also need to put some file in ../users/ dir. I have nix.nix file with those contents:
{
home.stateVersion = "23.11";
}
home.stateVersion is needed, otherwise there's a different error from home-manager. And you also need <home-manager> channel.
| 16:34:21 |
mr-qubo | * I run it with nixos-rebuild -I nixos-config=$(pwd)/users-impl.nix dry-build --show-trace . ./user-impl.nix is the name of the file, contents which I pasted. You also need to put some file in ../users/ dir. I have nix.nix file with those contents:
{
home.stateVersion = "23.11";
}
home.stateVersion is needed, otherwise there's a different error from home-manager. And you also need <home-manager> channel.
| 16:37:23 |
mr-qubo | * I run it with nixos-rebuild -I nixos-config=$(pwd)/users-impl.nix dry-build --show-trace . ./user-impl.nix is the name of the file, contents which I pasted. You also need to put some file in ../users/ dir. I have nix.nix file with those contents:
{
home.stateVersion = "23.11";
}
home.stateVersion is needed, otherwise there's a different error from home-manager. And you also need <home-manager> channel (nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager ).
| 16:39:46 |
mr-qubo | * I've made more minimal example:
{ lib, ... }:
let
users = [
{
username = "nix";
module = {
home.stateVersion = "23.11";
# MrQubo.osConfig.services.logrotate.enable = false;
};
}
];
evalHmModule = { username, module, config, pkgs, ... }:
(import <home-manager/modules> {
configuration = {
options.MrQubo = {
osConfig.services = lib.mkOption {
type = lib.types.raw;
};
};
config = {
submoduleSupport.enable = true;
submoduleSupport.externalPackageInstall = false;
home.username = config.users.users.${username}.name;
home.homeDirectory = config.users.users.${username}.home;
# Make activation script use same version of Nix as system as a whole.
# This avoids problems with Nix not being in PATH.
nix.package = config.nix.package;
};
};
inherit pkgs;
}).extendModules {
modules = [
{
MrQubo.osConfig.services = config.services;
}
module
];
};
osConfigModules = lib.flip map users (user: { pkgs, config, ... }:
{ config.services = (evalHmModule ({ inherit pkgs config; } // user)).config.MrQubo.osConfig.services; }
);
in {
imports = osConfigModules;
}
# vim: sts=2 sw=2 ts=60 et:
You also need <home-manager> channel, which can be added with nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager . The configuration can be run with nixos-rebuild -I nixos-config=$(pwd)/users.nix dry-build --show-trace .
| 16:47:04 |
mr-qubo | * I've made more minimal example:
{ lib, ... }:
let
users = [
{
username = "nix";
module = {
home.stateVersion = "23.11";
# MrQubo.osConfig.services.logrotate.enable = false;
};
}
];
evalHmModule = { username, module, config, pkgs, ... }:
(import <home-manager/modules> {
configuration = {
options.MrQubo = {
osConfig.services = lib.mkOption {
type = lib.types.raw;
};
};
config = {
submoduleSupport.enable = true;
submoduleSupport.externalPackageInstall = false;
home.username = config.users.users.${username}.name;
home.homeDirectory = config.users.users.${username}.home;
# Make activation script use same version of Nix as system as a whole.
# This avoids problems with Nix not being in PATH.
nix.package = config.nix.package;
};
};
inherit pkgs;
}).extendModules {
modules = [
{
MrQubo.osConfig.services = config.services;
}
module
];
};
osConfigModules = lib.flip map users (user: { pkgs, config, ... }:
{ config.services = (evalHmModule ({ inherit pkgs config; } // user)).config.MrQubo.osConfig.services; }
);
in {
imports = osConfigModules;
}
You also need <home-manager> channel, which can be added with nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager . The configuration can be run with nixos-rebuild -I nixos-config=$(pwd)/users.nix dry-build --show-trace .
| 16:47:19 |
mr-qubo | * I've made more minimal example:
users.nix :
{ lib, ... }:
let
users = [
{
username = "nix";
module = {
home.stateVersion = "23.11";
# MrQubo.osConfig.services.logrotate.enable = false;
};
}
];
evalHmModule = { username, module, config, pkgs, ... }:
(import <home-manager/modules> {
configuration = {
options.MrQubo = {
osConfig.services = lib.mkOption {
type = lib.types.raw;
};
};
config = {
submoduleSupport.enable = true;
submoduleSupport.externalPackageInstall = false;
home.username = config.users.users.${username}.name;
home.homeDirectory = config.users.users.${username}.home;
# Make activation script use same version of Nix as system as a whole.
# This avoids problems with Nix not being in PATH.
nix.package = config.nix.package;
};
};
inherit pkgs;
}).extendModules {
modules = [
{
MrQubo.osConfig.services = config.services;
}
module
];
};
osConfigModules = lib.flip map users (user: { pkgs, config, ... }:
{ config.services = (evalHmModule ({ inherit pkgs config; } // user)).config.MrQubo.osConfig.services; }
);
in {
imports = osConfigModules;
}
You also need <home-manager> channel, which can be added with nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager . The configuration can be run with nixos-rebuild -I nixos-config=$(pwd)/users.nix dry-build --show-trace .
| 16:47:45 |
3 Sep 2024 |
| @djacu:matrix.org left the room. | 23:29:30 |
4 Sep 2024 |
| SomeoneSerge (utc+3) changed their display name from SomeoneSerge (UTC+3) to SomeoneSerge (nix.camp). | 21:49:17 |
5 Sep 2024 |
| lingo5080 joined the room. | 15:56:06 |
7 Sep 2024 |
| throwachimera joined the room. | 11:56:03 |
| Kamilla 'ova joined the room. | 12:21:15 |
8 Sep 2024 |
| jakehamilton joined the room. | 01:02:45 |
| cafkafk joined the room. | 05:21:48 |
9 Sep 2024 |
| cdepillabout joined the room. | 00:57:13 |
| Pandapip1 joined the room. | 03:45:55 |
10 Sep 2024 |
| (artur 'manuel) changed their display name from (lambda (u) (format nil "~A lost their email!" u)) "Artur Manuel" to Artur Manuel (on break). | 17:32:40 |
| (artur 'manuel) changed their profile picture. | 17:35:01 |
| (artur 'manuel) changed their display name from Artur Manuel (on break) to (lambda (u) (format nil "~A is not using Matrix right now." u)) "Artur Manuel". | 17:36:41 |
12 Sep 2024 |
| (artur 'manuel) changed their display name from (lambda (u) (format nil "~A is not using Matrix right now." u)) "Artur Manuel" to (lambda (u) (format nil "~a ~a")) "Artur" "Manuel". | 01:49:04 |