1 { config, lib, pkgs, ... }:
5 makeColor = i: lib.concatMapStringsSep "," (x: "0x" + lib.substring (2*i) 2 x);
7 isUnicode = lib.hasSuffix "UTF-8" (lib.toUpper config.i18n.defaultLocale);
9 optimizedKeymap = pkgs.runCommand "keymap" {
10 nativeBuildInputs = [ pkgs.buildPackages.kbd ];
11 LOADKEYS_KEYMAP_PATH = "${consoleEnv pkgs.kbd}/share/keymaps/**";
12 preferLocalBuild = true;
14 loadkeys -b ${lib.optionalString isUnicode "-u"} "${cfg.keyMap}" > $out
17 # Sadly, systemd-vconsole-setup doesn't support binary keymaps.
18 vconsoleConf = pkgs.writeText "vconsole.conf" ''
20 ${lib.optionalString (cfg.font != null) "FONT=${cfg.font}"}
23 consoleEnv = kbd: pkgs.buildEnv {
25 paths = [ kbd ] ++ cfg.packages;
39 enable = lib.mkEnableOption "virtual console" // {
44 type = with lib.types; nullOr (either str path);
46 example = "LatArCyrHeb-16";
48 The font used for the virtual consoles.
49 Can be `null`, a font name, or a path to a PSF font file.
51 Use `null` to let the kernel choose a built-in font.
52 The default is 8x16, and, as of Linux 5.3, Terminus 32 bold for display
53 resolutions of 2560x1080 and higher.
54 These fonts cover the [IBM437][] character set.
56 [IBM437]: https://en.wikipedia.org/wiki/Code_page_437
60 keyMap = lib.mkOption {
61 type = with lib.types; either str path;
65 The keyboard mapping table for the virtual consoles.
69 colors = lib.mkOption {
70 type = with lib.types; listOf (strMatching "[[:xdigit:]]{6}");
73 "002b36" "dc322f" "859900" "b58900"
74 "268bd2" "d33682" "2aa198" "eee8d5"
75 "002b36" "cb4b16" "586e75" "657b83"
76 "839496" "6c71c4" "93a1a1" "fdf6e3"
79 The 16 colors palette used by the virtual consoles.
80 Leave empty to use the default colors.
81 Colors must be in hexadecimal format and listed in
82 order from color 0 to color 15.
87 packages = lib.mkOption {
88 type = lib.types.listOf lib.types.package;
91 List of additional packages that provide console fonts, keymaps and
92 other resources for virtual consoles use.
96 useXkbConfig = lib.mkOption {
97 type = lib.types.bool;
100 If set, configure the virtual console keymap from the xserver
105 earlySetup = lib.mkOption {
107 type = lib.types.bool;
109 Enable setting virtual console options as early as possible (in initrd).
116 ###### implementation
118 config = lib.mkMerge [
119 { console.keyMap = with config.services.xserver;
120 lib.mkIf cfg.useXkbConfig
121 (pkgs.runCommand "xkb-console-keymap" { preferLocalBuild = true; } ''
122 '${pkgs.buildPackages.ckbcomp}/bin/ckbcomp' \
123 ${lib.optionalString (config.environment.sessionVariables ? XKB_CONFIG_ROOT)
124 "-I${config.environment.sessionVariables.XKB_CONFIG_ROOT}"
126 -model '${xkb.model}' -layout '${xkb.layout}' \
127 -option '${xkb.options}' -variant '${xkb.variant}' > "$out"
131 (lib.mkIf (!cfg.enable) {
133 "serial-getty@ttyS0".enable = false;
134 "serial-getty@hvc0".enable = false;
135 "getty@tty1".enable = false;
136 "autovt@".enable = false;
137 systemd-vconsole-setup.enable = false;
141 (lib.mkIf cfg.enable (lib.mkMerge [
142 { environment.systemPackages = [ pkgs.kbd ];
144 # Let systemd-vconsole-setup.service do the work of setting up the
146 environment.etc."vconsole.conf".source = vconsoleConf;
147 # Provide kbd with additional packages.
148 environment.etc.kbd.source = "${consoleEnv pkgs.kbd}/share";
150 boot.initrd.preLVMCommands = lib.mkIf (!config.boot.initrd.systemd.enable) (lib.mkBefore ''
151 kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
152 printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
153 loadkmap < ${optimizedKeymap}
155 ${lib.optionalString (cfg.earlySetup && cfg.font != null) ''
156 setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
160 boot.initrd.systemd.contents = {
161 "/etc/vconsole.conf".source = vconsoleConf;
162 # Add everything if we want full console setup...
163 "/etc/kbd" = lib.mkIf cfg.earlySetup { source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share"; };
164 # ...but only the keymaps if we don't
165 "/etc/kbd/keymaps" = lib.mkIf (!cfg.earlySetup) { source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share/keymaps"; };
167 boot.initrd.systemd.additionalUpstreamUnits = [
168 "systemd-vconsole-setup.service"
170 boot.initrd.systemd.storePaths = [
171 "${config.boot.initrd.systemd.package}/lib/systemd/systemd-vconsole-setup"
172 "${config.boot.initrd.systemd.package.kbd}/bin/setfont"
173 "${config.boot.initrd.systemd.package.kbd}/bin/loadkeys"
174 "${config.boot.initrd.systemd.package.kbd.gzip}/bin/gzip" # Fonts and keyboard layouts are compressed
175 ] ++ lib.optionals (cfg.font != null && lib.hasPrefix builtins.storeDir cfg.font) [
177 ] ++ lib.optionals (lib.hasPrefix builtins.storeDir cfg.keyMap) [
181 systemd.services.reload-systemd-vconsole-setup =
182 { description = "Reset console on configuration changes";
183 wantedBy = [ "multi-user.target" ];
184 restartTriggers = [ vconsoleConf (consoleEnv pkgs.kbd) ];
185 reloadIfChanged = true;
187 { RemainAfterExit = true;
188 ExecStart = "${pkgs.coreutils}/bin/true";
189 ExecReload = "/run/current-system/systemd/bin/systemctl restart systemd-vconsole-setup";
194 (lib.mkIf (cfg.colors != []) {
195 boot.kernelParams = [
196 "vt.default_red=${makeColor 0 cfg.colors}"
197 "vt.default_grn=${makeColor 1 cfg.colors}"
198 "vt.default_blu=${makeColor 2 cfg.colors}"
202 (lib.mkIf (cfg.earlySetup && cfg.font != null && !config.boot.initrd.systemd.enable) {
203 boot.initrd.extraUtilsCommands = ''
204 mkdir -p $out/share/consolefonts
205 ${if lib.substring 0 1 cfg.font == "/" then ''
208 font="$(echo ${consoleEnv pkgs.kbd}/share/consolefonts/${cfg.font}.*)"
210 if [[ $font == *.gz ]]; then
211 gzip -cd $font > $out/share/consolefonts/font.psf
213 cp -L $font $out/share/consolefonts/font.psf
221 (lib.mkRenamedOptionModule [ "i18n" "consoleFont" ] [ "console" "font" ])
222 (lib.mkRenamedOptionModule [ "i18n" "consoleKeyMap" ] [ "console" "keyMap" ])
223 (lib.mkRenamedOptionModule [ "i18n" "consoleColors" ] [ "console" "colors" ])
224 (lib.mkRenamedOptionModule [ "i18n" "consolePackages" ] [ "console" "packages" ])
225 (lib.mkRenamedOptionModule [ "i18n" "consoleUseXkbConfig" ] [ "console" "useXkbConfig" ])
226 (lib.mkRenamedOptionModule [ "boot" "earlyVconsoleSetup" ] [ "console" "earlySetup" ])
227 (lib.mkRenamedOptionModule [ "boot" "extraTTYs" ] [ "console" "extraTTYs" ])
228 (lib.mkRemovedOptionModule [ "console" "extraTTYs" ] ''
229 Since NixOS switched to systemd (circa 2012), TTYs have been spawned on
230 demand, so there is no need to configure them manually.