Problems with Configuring Custom Keyboard Layout as a Derivation

I am using a custom keyboard layout called gallium, and I would like to use it as a derivation, called in configuration.nix with (callPackage ./gallium.nix {}).

Here is the gallium.nix:

{ pkgs ? import <nixpkgs> {} }:
pkgs.stdenv.mkDerivation {
  name = "galliumv2";
  src = pkgs.fetchFromGitHub {
    owner = "GalileoBlues";
    repo = "Gallium";
    rev = "21a...1fe";
    sha256 = "JrK...Aw=";
  };
  installPhase = ''
    mkdir -p $out/share/keymaps/i386/gallium
    mkdir -p ${pkgs.xkeyboardconfig}/etc/X11/xkb
    cp ./Linux/console/gallium_rowstag.map $out/share/keymaps/i386/gallium/gallium.map
    cp ./Linux/xkb/gallium_rowstag ${pkgs.xkeyboardconfig}/etc/X11/xkb/gallium
  '';
}

I have tried setting the xkb keyboard layout to $out, but it seems like only keyboard layouts that are set by services.xserver.xkb are detected by wayland compositors, which is why I used pkgs.xkeyboardconfig as an out path. However, changing the out path for xkb to pkgs.xkeyboardconfig throws the error cp: cannot create regular file '/nix/store/7d...mhh-xkeyboard-config-2.47/etc/X11/xkb/gallium': Permission denied. If there is a way for me to specify custom keyboard layouts as in https://nixos.org/manual/nixos/stable/#custom-xkb-layouts in a derivation, please do tell me how.

I found out that only pkgs.xkeyboardconfig was allowed because xkbcommon threw the error

xkbcommon: ERROR: [XKB-338] Couldn't find file "symbols/gallium" in include paths
xkbcommon: ERROR: [XKB-338] 1 include paths searched:
xkbcommon: ERROR: [XKB-338]     /nix/store/7dh...mhh-xkeyboard-config-2.47/etc/X11/xkb
xkbcommon: ERROR: [XKB-338] 3 include paths could not be added:
xkbcommon: ERROR: [XKB-338]     /home/-/.config/xkb
xkbcommon: ERROR: [XKB-338]     /home/cube/.xkb
xkbcommon: ERROR: [XKB-338]     /etc/xkb
xkbcommon: ERROR: [XKB-661] Couldn't process include statement for 'gallium'
   ...

The reason I would like to use a derivation is so that I can update both console keymap and xkb keyboard layout at the same time, and I would prefer if console keymap does not use xkb keyboards.

You can’t just write wherever you want in a derivation. Derivations are declarative ways to produce a specific store object, whose location is in $out during execution. You can’t write anywhere else. (Some derivations have multiple outputs, but they still can only write into locations whose names were calculated by nix to be for that derivation.)

You need to use nixos configuration options to make the layout available. I strongly suspect this can be done with the services.xserver.xkb.extraLayouts.<name>.symbolsFile option, but I don’t have personal experience with this specific endeavor.

Looking a little deeper into this, I would just do this:

{ pkgs, lib, ... }:

let
  galliumSrc = pkgs.fetchFromGitHub {
    owner = "GalileoBlues";
    repo = "Gallium";
    rev = "21a...1fe";
    sha256 = "JrK...Aw=";
  };
in {
  ...
  console.keyMap = "${galliumSrc}/linux/console/gallium_rowstag.map";
  services.xserver.xkb.extraLayouts.gallium = {
   description = "something something gallium, fill in as desired";
   languages = [ "eng" ];
   symbolsFile = "${galliumSrc}/linux/xkb/gallium_rowstag";
  };
  ...
}

Hm… may I know how I would add this in my confguration.nix? callPackage does not seem to work, and adding it into import gives many errors.

That snippet was intended to be an abbreviated view of configuration.nix itself. Your other settings would fit in the ...'s.

You could also put it in its own file (without the ...'s) and add it to imports in configuration.nix.

This works perfectly, thank you! The problem I had was that I blindly copied your code and forgot to capitalise the L in Linux in the path. Great solution!

Oops. My bad, did it by eye and didn’t test it. Glad you got it working!