at master 8.7 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.console; 9 10 makeColor = i: lib.concatMapStringsSep "," (x: "0x" + lib.substring (2 * i) 2 x); 11 12 isUnicode = lib.hasSuffix "UTF-8" (lib.toUpper config.i18n.defaultLocale); 13 14 optimizedKeymap = 15 pkgs.runCommand "keymap" 16 { 17 nativeBuildInputs = [ pkgs.buildPackages.kbd ]; 18 LOADKEYS_KEYMAP_PATH = "${consoleEnv pkgs.kbd}/share/keymaps/**"; 19 preferLocalBuild = true; 20 } 21 '' 22 loadkeys -b ${lib.optionalString isUnicode "-u"} "${cfg.keyMap}" > $out 23 ''; 24 25 # Sadly, systemd-vconsole-setup doesn't support binary keymaps. 26 vconsoleConf = pkgs.writeText "vconsole.conf" '' 27 KEYMAP=${cfg.keyMap} 28 ${lib.optionalString (cfg.font != null) "FONT=${cfg.font}"} 29 ''; 30 31 consoleEnv = 32 kbd: 33 pkgs.buildEnv { 34 name = "console-env"; 35 paths = [ kbd ] ++ cfg.packages; 36 pathsToLink = [ 37 "/share/consolefonts" 38 "/share/consoletrans" 39 "/share/keymaps" 40 "/share/unimaps" 41 ]; 42 }; 43in 44 45{ 46 ###### interface 47 48 options.console = { 49 enable = lib.mkEnableOption "virtual console" // { 50 default = true; 51 }; 52 53 font = lib.mkOption { 54 type = with lib.types; nullOr (either str path); 55 default = null; 56 example = "LatArCyrHeb-16"; 57 description = '' 58 The font used for the virtual consoles. 59 Can be `null`, a font name, or a path to a PSF font file. 60 61 Use `null` to let the kernel choose a built-in font. 62 The default is 8x16, and, as of Linux 5.3, Terminus 32 bold for display 63 resolutions of 2560x1080 and higher. 64 These fonts cover the [IBM437][] character set. 65 66 [IBM437]: https://en.wikipedia.org/wiki/Code_page_437 67 ''; 68 }; 69 70 keyMap = lib.mkOption { 71 type = with lib.types; either str path; 72 default = "us"; 73 example = "fr"; 74 description = '' 75 The keyboard mapping table for the virtual consoles. 76 ''; 77 }; 78 79 colors = lib.mkOption { 80 type = with lib.types; listOf (strMatching "[[:xdigit:]]{6}"); 81 default = [ ]; 82 example = [ 83 "002b36" 84 "dc322f" 85 "859900" 86 "b58900" 87 "268bd2" 88 "d33682" 89 "2aa198" 90 "eee8d5" 91 "002b36" 92 "cb4b16" 93 "586e75" 94 "657b83" 95 "839496" 96 "6c71c4" 97 "93a1a1" 98 "fdf6e3" 99 ]; 100 description = '' 101 The 16 colors palette used by the virtual consoles. 102 Leave empty to use the default colors. 103 Colors must be in hexadecimal format and listed in 104 order from color 0 to color 15. 105 ''; 106 107 }; 108 109 packages = lib.mkOption { 110 type = lib.types.listOf lib.types.package; 111 default = [ ]; 112 description = '' 113 List of additional packages that provide console fonts, keymaps and 114 other resources for virtual consoles use. 115 ''; 116 }; 117 118 useXkbConfig = lib.mkOption { 119 type = lib.types.bool; 120 default = false; 121 description = '' 122 If set, configure the virtual console keymap from the xserver 123 keyboard settings. 124 ''; 125 }; 126 127 earlySetup = lib.mkOption { 128 default = false; 129 type = lib.types.bool; 130 description = '' 131 Enable setting virtual console options as early as possible (in initrd). 132 ''; 133 }; 134 135 }; 136 137 ###### implementation 138 139 config = lib.mkMerge [ 140 { 141 console.keyMap = 142 with config.services.xserver; 143 lib.mkIf cfg.useXkbConfig ( 144 pkgs.runCommand "xkb-console-keymap" { preferLocalBuild = true; } '' 145 '${pkgs.buildPackages.ckbcomp}/bin/ckbcomp' \ 146 ${ 147 lib.optionalString ( 148 config.environment.sessionVariables ? XKB_CONFIG_ROOT 149 ) "-I${config.environment.sessionVariables.XKB_CONFIG_ROOT}" 150 } \ 151 -model '${xkb.model}' -layout '${xkb.layout}' \ 152 -option '${xkb.options}' -variant '${xkb.variant}' > "$out" 153 '' 154 ); 155 } 156 157 (lib.mkIf cfg.enable ( 158 lib.mkMerge [ 159 { 160 environment.systemPackages = [ pkgs.kbd ]; 161 162 # Let systemd-vconsole-setup.service do the work of setting up the 163 # virtual consoles. 164 environment.etc."vconsole.conf".source = vconsoleConf; 165 # Provide kbd with additional packages. 166 environment.etc.kbd.source = "${consoleEnv pkgs.kbd}/share"; 167 168 boot.initrd.preLVMCommands = lib.mkIf (!config.boot.initrd.systemd.enable) ( 169 lib.mkBefore '' 170 kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console 171 printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console 172 loadkmap < ${optimizedKeymap} 173 174 ${lib.optionalString (cfg.earlySetup && cfg.font != null) '' 175 setfont -C /dev/console $extraUtils/share/consolefonts/font.psf 176 ''} 177 '' 178 ); 179 180 boot.initrd.systemd.contents = { 181 "/etc/vconsole.conf".source = vconsoleConf; 182 # Add everything if we want full console setup... 183 "/etc/kbd" = lib.mkIf cfg.earlySetup { 184 source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share"; 185 }; 186 # ...but only the keymaps if we don't 187 "/etc/kbd/keymaps" = lib.mkIf (!cfg.earlySetup) { 188 source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share/keymaps"; 189 }; 190 }; 191 boot.initrd.systemd.additionalUpstreamUnits = [ 192 "systemd-vconsole-setup.service" 193 ]; 194 boot.initrd.systemd.storePaths = [ 195 "${config.boot.initrd.systemd.package}/lib/systemd/systemd-vconsole-setup" 196 "${config.boot.initrd.systemd.package.kbd}/bin/setfont" 197 "${config.boot.initrd.systemd.package.kbd}/bin/loadkeys" 198 ] 199 ++ lib.optionals (cfg.font != null && lib.hasPrefix builtins.storeDir cfg.font) [ 200 "${cfg.font}" 201 ] 202 ++ lib.optionals (lib.hasPrefix builtins.storeDir cfg.keyMap) [ 203 "${cfg.keyMap}" 204 ]; 205 206 systemd.additionalUpstreamSystemUnits = [ 207 "systemd-vconsole-setup.service" 208 ]; 209 210 systemd.services.reload-systemd-vconsole-setup = { 211 description = "Reset console on configuration changes"; 212 wantedBy = [ "multi-user.target" ]; 213 restartTriggers = [ 214 vconsoleConf 215 (consoleEnv pkgs.kbd) 216 ]; 217 reloadIfChanged = true; 218 serviceConfig = { 219 RemainAfterExit = true; 220 ExecStart = "${pkgs.coreutils}/bin/true"; 221 ExecReload = "/run/current-system/systemd/bin/systemctl restart systemd-vconsole-setup"; 222 }; 223 }; 224 } 225 226 (lib.mkIf (cfg.colors != [ ]) { 227 boot.kernelParams = [ 228 "vt.default_red=${makeColor 0 cfg.colors}" 229 "vt.default_grn=${makeColor 1 cfg.colors}" 230 "vt.default_blu=${makeColor 2 cfg.colors}" 231 ]; 232 }) 233 234 (lib.mkIf (cfg.earlySetup && cfg.font != null && !config.boot.initrd.systemd.enable) { 235 boot.initrd.extraUtilsCommands = '' 236 mkdir -p $out/share/consolefonts 237 ${ 238 if lib.substring 0 1 cfg.font == "/" then 239 '' 240 font="${cfg.font}" 241 '' 242 else 243 '' 244 font="$(echo ${consoleEnv pkgs.kbd}/share/consolefonts/${cfg.font}.*)" 245 '' 246 } 247 if [[ $font == *.gz ]]; then 248 gzip -cd $font > $out/share/consolefonts/font.psf 249 else 250 cp -L $font $out/share/consolefonts/font.psf 251 fi 252 ''; 253 }) 254 ] 255 )) 256 ]; 257 258 imports = [ 259 (lib.mkRenamedOptionModule [ "i18n" "consoleFont" ] [ "console" "font" ]) 260 (lib.mkRenamedOptionModule [ "i18n" "consoleKeyMap" ] [ "console" "keyMap" ]) 261 (lib.mkRenamedOptionModule [ "i18n" "consoleColors" ] [ "console" "colors" ]) 262 (lib.mkRenamedOptionModule [ "i18n" "consolePackages" ] [ "console" "packages" ]) 263 (lib.mkRenamedOptionModule [ "i18n" "consoleUseXkbConfig" ] [ "console" "useXkbConfig" ]) 264 (lib.mkRenamedOptionModule [ "boot" "earlyVconsoleSetup" ] [ "console" "earlySetup" ]) 265 (lib.mkRenamedOptionModule [ "boot" "extraTTYs" ] [ "console" "extraTTYs" ]) 266 (lib.mkRemovedOptionModule [ "console" "extraTTYs" ] '' 267 Since NixOS switched to systemd (circa 2012), TTYs have been spawned on 268 demand, so there is no need to configure them manually. 269 '') 270 ]; 271}