NixOS Custom XKB Layout: Fixing Broken Modifier Layers with extraLayouts
When the layout loads but the modifier layers stay silent
You’ve done the hard part — the five XKB files are wired into extraLayouts, the build succeeds, Plasma lists the layout. Then you press AltGr or Shift into a layer and nothing happens. This is one of those situations where everything is technically correct except one small piece of wiring that NixOS can’t infer on its own.
What extraLayouts actually does (and doesn’t do)
The services.xserver.xkb.extraLayouts option copies your symbol, type, compat, keycodes, and geometry files into the Nix store’s XKB database at build time. After nixos-rebuild switch, the layout is discoverable — Plasma can find it because the file is in the right place in the store. That part works fine.
What extraLayouts does not do is bind any modifier keys. If your layout expects a LevelThree modifier (the AltGr layer), you have to tell XKB which physical key activates it. Without that binding, pressing AltGr does nothing at all, and neither does anything above Level2.
The fix: bind LevelThree to a physical key
Add an options entry at the same level as extraLayouts:
services.xserver.xkb = {
layout = "optimot_iso_18";
options = "lv3:ralt_switch";
extraLayouts.optimot_iso_18 = {
description = "France - Optimot ISO v1.8.0";
languages = [ "fr" ];
typesFile = /home/youruser/xkb/optimot_types;
symbolsFile = /home/youruser/xkb/optimot_symbols;
compatFile = /home/youruser/xkb/optimot_compat;
keycodesFile = /home/youruser/xkb/optimot_keycodes;
geometryFile = /home/youruser/xkb/optimot_geometry;
};
};
lv3:ralt_switch maps the right Alt key to LevelThree. Optimot’s type definitions reference LevelThree throughout — in FOUR_LEVEL_CONTROL, FOUR_LEVEL_ALPHABETIC_CONTROL, and FOUR_LEVEL_SEMIALPHABETIC_CONTROL — so this one line unlocks those entire key-type tables.
Alternatives: lv3:lalt_switch uses left Alt, lv3:menu_switch uses the application menu key. Check Optimot’s documentation to see which key the author intended for the layout.
Plasma on Wayland: a small catch
On a Wayland session, Plasma loads XKB configuration through libxkbcommon rather than through Xorg. The NixOS xkb options still apply — libxkbcommon reads from the same Nix store path — but the configuration is cached at session start.
After nixos-rebuild switch, a full log-out and log-in is required. Restarting Plasma’s shell or toggling the layout in System Settings is not enough; the input daemon needs to reinitialise.
Also worth knowing: setxkbmap and related X11 tools only affect the X session. Running them in a Wayland terminal has no effect on what Plasma is actually using. Don’t use them to diagnose Wayland behaviour.
Validating the XKB files themselves
The types file in the original post looks structurally fine. The include "complete" at the top brings in standard types, and the three custom types extend them correctly. One thing to check: the types file should contain only the xkb_types { ... } block, with no leading keywords like partial. Some export tools prepend partial, which the type parser rejects silently.
Use this to validate all five files before rebuilding:
xkbcli compile-keymap --layout optimot_iso_18
Parse errors surface here without needing to reload anything. If the command isn’t available, it’s in the xkeyboard-config package or in libxkbcommon depending on your distro.
Absolute paths and silent failures
Paths like /home/user/xkb/optimot_types in a Nix configuration are evaluated at build time, not at activation time. If the file doesn’t exist at that path when you run nixos-rebuild, Nix silently skips it rather than erroring out, and your layout ends up with an empty or default file.
The safer approach is to use a path relative to your configuration directory:
typesFile = ./xkb/optimot_types;
This makes Nix track the file as a dependency. If it’s missing, the build fails loudly instead of succeeding with a broken layout.
Confirming the active keymap
On X11, dump the current keymap with:
xkbcli export-keymap | grep -A5 "FOUR_LEVEL_CONTROL"
If your custom type names are absent, the typesFile isn’t being loaded. On Wayland with Plasma, check System Settings → Input Devices → Keyboard → Advanced — the AltGr binding should appear there under “Key to choose 3rd level”.
