Reading the Arch wiki on how to make GDM set the resolution and refresh rate properly it says:
If you have your monitors setup as you like (resolution, refresh rate, orientation, scaling, primary and so on) in ~/.config/monitors.xml and want GDM to honor those settings:
cp ~/.config/monitors.xml /var/lib/gdm/.config/
I’ve been searching a bit here, but can’t really see anything related.
A learning moment, if I may - is it so that whoever is responsible for the GDM package must make the options for something like this? Like, they would have to make something like an option services.xserver.displayManager.gdm.monitorXML where this could be put?
Not necessarily! Modules will generally have their own maintainers. You can see the module associated with a NixOS option by clicking the ‘Declared in’ link, and in that module there is often a meta.maintainers entry.
In this case, though, it’s teams.gnome.members that are maintainers for both pkgs/desktops/gnome/core/gdm/default.nix the package and nixos/modules/services/x11/display-managers/gdm.nix the NixOS module.
But more importantly, anyone can submit a PR with a new option, not just the maintainers. You can see in the module that there are already a few conditional systemd.tmpfiles.rules entries added if certain options are enabled; you’d just be adding another one of those.
One thing that is easy to get wrong w.r.t. modules is that your configuration.nix is also a module just like the GDM module and can therefore also do anything that an upstream NixOS module could do. There’s nothing special about the modules in NixOS
This doesn’t need to be an upstream module, you can simply set it in your config. You could even make your own options in your config.
It’d be great to have this monitorXML option upstream though. Feel free to send a PR to Nixpkgs for that if you’re motivated; anyone can contribute.
All the more reason to have a dedicated NixOS option IMHO.
I spent quite a bit of time trying to configure GDM via /etc/gdm/ once and it just would not work. I had assumed GDM was buggy but TIL it’s actually a config quirk on our side.
A NixOS option would greatly help abstract such details.
Having to resort to home-manager to configure a system display-manager does not strike me as a sane solution.
Ok, so I think I am understanding this a bit more.
The path from the Arch doc is just the config dir under the home directory of GDM. So I just need to put the file in GDM’s home in NixOS, which is /run/gdm. And this can be done by:
Trying to make this work, but I’m struggling a bit. I’ve lost track of all the different ways I’ve tried up until now. This is where I am at at the moment, from configuration.nix:
monitorsxml = writeText {
name = "monitorsxml";
text = ''
(a lot of monitor text)
'';
};
systemd.tmpfiles.rules = [
"L /run/gdm/.config/monitors.xml - - - - ${monitorsxml}"
];
I am getting error: undefined variable 'monitorsxml'.
I’m sure it’s trivial… can anyone see my mistake?
Your understanding here is correct, the problem is with your Nix syntax.
You are probably defining monitorsxml as a NixOS option, which does not actually exist. Nor will it set a Nix variable your later option expects, causing the evaluation error.
The most common method of creating “variables” is a let expression. You would either use it at the top-level, so that the configuration attribute set is in the let … in body:
aha! let ... in of course.
I have tried both top-level and scoped down, but it doesn’t go through:
nixos-rebuild switch
building Nix...
building the system configuration...
error:
… while calling the 'head' builtin
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:1575:11:
1574| || pred here (elemAt values 1) (head values) then
1575| head values
| ^
1576| else
… while evaluating the attribute 'value'
at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:809:9:
808| in warnDeprecation opt //
809| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
| ^
810| inherit (res.defsFinal') highestPrio;
(stack trace truncated; use '--show-trace' to show the full trace)
error: cannot coerce a function to a string
I tried looking through both those files, but I have no idea what it means. The error must be from this:
Check the manual again: writeText wants to be applied to two strings, not an attribute set. (writeTextFile is the one that wants an attribute set. You can use either here, as long as you give whichever one you use the thing that it wants.)
This results in cannot coerce a function to a string because the result of applying writeText to one argument is a function—the function that would be applied to a second argument if there was one. Interpolating that function into the string literal in systemd.tmpfiles.rules causes the error.
Note that this will create an monitors attribute set with a single xml attribute (same as { monitors = { xml = ...; }; }). You may want to use monitorsXML instead.
The default behaviour for the user gdm on nixos is to have a temporary home directory at /run/gdm. I suspect that we can override the default and appoint for a static directory. Try repl on system flake, and inspect the property
I think the transient home directory is intentional since it was set by us from the start.
I would also say it is preferable since less persistent state means fewer problems, allowing Nix to actually shine. It is similar, in effect, to impermanence, except safe to enable by default since people are not typically expected to modify stuff in gdm’s home directory.