1
2{ config, lib, pkgs, ... }:
3
4with lib;
5
6let
7 cfg = config.console;
8
9 makeColor = i: concatMapStringsSep "," (x: "0x" + substring (2*i) 2 x);
10
11 isUnicode = hasSuffix "UTF-8" (toUpper config.i18n.defaultLocale);
12
13 optimizedKeymap = pkgs.runCommand "keymap" {
14 nativeBuildInputs = [ pkgs.buildPackages.kbd ];
15 LOADKEYS_KEYMAP_PATH = "${consoleEnv}/share/keymaps/**";
16 preferLocalBuild = true;
17 } ''
18 loadkeys -b ${optionalString isUnicode "-u"} "${cfg.keyMap}" > $out
19 '';
20
21 # Sadly, systemd-vconsole-setup doesn't support binary keymaps.
22 vconsoleConf = pkgs.writeText "vconsole.conf" ''
23 KEYMAP=${cfg.keyMap}
24 FONT=${cfg.font}
25 '';
26
27 consoleEnv = pkgs.buildEnv {
28 name = "console-env";
29 paths = [ pkgs.kbd ] ++ cfg.packages;
30 pathsToLink = [
31 "/share/consolefonts"
32 "/share/consoletrans"
33 "/share/keymaps"
34 "/share/unimaps"
35 ];
36 };
37
38 setVconsole = !config.boot.isContainer;
39in
40
41{
42 ###### interface
43
44 options.console = {
45 font = mkOption {
46 type = with types; either str path;
47 default = "Lat2-Terminus16";
48 example = "LatArCyrHeb-16";
49 description = ''
50 The font used for the virtual consoles. Leave empty to use
51 whatever the <command>setfont</command> program considers the
52 default font.
53 Can be either a font name or a path to a PSF font file.
54 '';
55 };
56
57 keyMap = mkOption {
58 type = with types; either str path;
59 default = "us";
60 example = "fr";
61 description = ''
62 The keyboard mapping table for the virtual consoles.
63 '';
64 };
65
66 colors = mkOption {
67 type = types.listOf types.str;
68 default = [];
69 example = [
70 "002b36" "dc322f" "859900" "b58900"
71 "268bd2" "d33682" "2aa198" "eee8d5"
72 "002b36" "cb4b16" "586e75" "657b83"
73 "839496" "6c71c4" "93a1a1" "fdf6e3"
74 ];
75 description = ''
76 The 16 colors palette used by the virtual consoles.
77 Leave empty to use the default colors.
78 Colors must be in hexadecimal format and listed in
79 order from color 0 to color 15.
80 '';
81
82 };
83
84 packages = mkOption {
85 type = types.listOf types.package;
86 default = [ ];
87 description = ''
88 List of additional packages that provide console fonts, keymaps and
89 other resources for virtual consoles use.
90 '';
91 };
92
93 useXkbConfig = mkOption {
94 type = types.bool;
95 default = false;
96 description = ''
97 If set, configure the virtual console keymap from the xserver
98 keyboard settings.
99 '';
100 };
101
102 earlySetup = mkOption {
103 default = false;
104 type = types.bool;
105 description = ''
106 Enable setting virtual console options as early as possible (in initrd).
107 '';
108 };
109
110 };
111
112
113 ###### implementation
114
115 config = mkMerge [
116 { console.keyMap = with config.services.xserver;
117 mkIf cfg.useXkbConfig
118 (pkgs.runCommand "xkb-console-keymap" { preferLocalBuild = true; } ''
119 '${pkgs.buildPackages.ckbcomp}/bin/ckbcomp' \
120 ${optionalString (config.environment.sessionVariables ? XKB_CONFIG_ROOT)
121 "-I${config.environment.sessionVariables.XKB_CONFIG_ROOT}"
122 } \
123 -model '${xkbModel}' -layout '${layout}' \
124 -option '${xkbOptions}' -variant '${xkbVariant}' > "$out"
125 '');
126 }
127
128 (mkIf (!setVconsole) {
129 systemd.services.systemd-vconsole-setup.enable = false;
130 })
131
132 (mkIf setVconsole (mkMerge [
133 { environment.systemPackages = [ pkgs.kbd ];
134
135 # Let systemd-vconsole-setup.service do the work of setting up the
136 # virtual consoles.
137 environment.etc."vconsole.conf".source = vconsoleConf;
138 # Provide kbd with additional packages.
139 environment.etc.kbd.source = "${consoleEnv}/share";
140
141 boot.initrd.preLVMCommands = mkBefore ''
142 kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
143 printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
144 loadkmap < ${optimizedKeymap}
145
146 ${optionalString cfg.earlySetup ''
147 setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
148 ''}
149 '';
150
151 systemd.services.reload-systemd-vconsole-setup =
152 { description = "Reset console on configuration changes";
153 wantedBy = [ "multi-user.target" ];
154 restartTriggers = [ vconsoleConf consoleEnv ];
155 reloadIfChanged = true;
156 serviceConfig =
157 { RemainAfterExit = true;
158 ExecStart = "${pkgs.coreutils}/bin/true";
159 ExecReload = "/run/current-system/systemd/bin/systemctl restart systemd-vconsole-setup";
160 };
161 };
162 }
163
164 (mkIf (cfg.colors != []) {
165 boot.kernelParams = [
166 "vt.default_red=${makeColor 0 cfg.colors}"
167 "vt.default_grn=${makeColor 1 cfg.colors}"
168 "vt.default_blu=${makeColor 2 cfg.colors}"
169 ];
170 })
171
172 (mkIf cfg.earlySetup {
173 boot.initrd.extraUtilsCommands = ''
174 mkdir -p $out/share/consolefonts
175 ${if substring 0 1 cfg.font == "/" then ''
176 font="${cfg.font}"
177 '' else ''
178 font="$(echo ${consoleEnv}/share/consolefonts/${cfg.font}.*)"
179 ''}
180 if [[ $font == *.gz ]]; then
181 gzip -cd $font > $out/share/consolefonts/font.psf
182 else
183 cp -L $font $out/share/consolefonts/font.psf
184 fi
185 '';
186 })
187 ]))
188 ];
189
190 imports = [
191 (mkRenamedOptionModule [ "i18n" "consoleFont" ] [ "console" "font" ])
192 (mkRenamedOptionModule [ "i18n" "consoleKeyMap" ] [ "console" "keyMap" ])
193 (mkRenamedOptionModule [ "i18n" "consoleColors" ] [ "console" "colors" ])
194 (mkRenamedOptionModule [ "i18n" "consolePackages" ] [ "console" "packages" ])
195 (mkRenamedOptionModule [ "i18n" "consoleUseXkbConfig" ] [ "console" "useXkbConfig" ])
196 (mkRenamedOptionModule [ "boot" "earlyVconsoleSetup" ] [ "console" "earlySetup" ])
197 (mkRenamedOptionModule [ "boot" "extraTTYs" ] [ "console" "extraTTYs" ])
198 (mkRemovedOptionModule [ "console" "extraTTYs" ] ''
199 Since NixOS switched to systemd (circa 2012), TTYs have been spawned on
200 demand, so there is no need to configure them manually.
201 '')
202 ];
203}