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 = types.str;
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 '';
54 };
55
56 keyMap = mkOption {
57 type = with types; either str path;
58 default = "us";
59 example = "fr";
60 description = ''
61 The keyboard mapping table for the virtual consoles.
62 '';
63 };
64
65 colors = mkOption {
66 type = types.listOf types.str;
67 default = [];
68 example = [
69 "002b36" "dc322f" "859900" "b58900"
70 "268bd2" "d33682" "2aa198" "eee8d5"
71 "002b36" "cb4b16" "586e75" "657b83"
72 "839496" "6c71c4" "93a1a1" "fdf6e3"
73 ];
74 description = ''
75 The 16 colors palette used by the virtual consoles.
76 Leave empty to use the default colors.
77 Colors must be in hexadecimal format and listed in
78 order from color 0 to color 15.
79 '';
80
81 };
82
83 packages = mkOption {
84 type = types.listOf types.package;
85 default = [ ];
86 description = ''
87 List of additional packages that provide console fonts, keymaps and
88 other resources for virtual consoles use.
89 '';
90 };
91
92 useXkbConfig = mkOption {
93 type = types.bool;
94 default = false;
95 description = ''
96 If set, configure the virtual console keymap from the xserver
97 keyboard settings.
98 '';
99 };
100
101 earlySetup = mkOption {
102 default = false;
103 type = types.bool;
104 description = ''
105 Enable setting virtual console options as early as possible (in initrd).
106 '';
107 };
108
109 };
110
111
112 ###### implementation
113
114 config = mkMerge [
115 { console.keyMap = with config.services.xserver;
116 mkIf cfg.useXkbConfig
117 (pkgs.runCommand "xkb-console-keymap" { preferLocalBuild = true; } ''
118 '${pkgs.ckbcomp}/bin/ckbcomp' -model '${xkbModel}' -layout '${layout}' \
119 -option '${xkbOptions}' -variant '${xkbVariant}' > "$out"
120 '');
121 }
122
123 (mkIf (!setVconsole) {
124 systemd.services.systemd-vconsole-setup.enable = false;
125 })
126
127 (mkIf setVconsole (mkMerge [
128 { environment.systemPackages = [ pkgs.kbd ];
129
130 # Let systemd-vconsole-setup.service do the work of setting up the
131 # virtual consoles.
132 environment.etc."vconsole.conf".source = vconsoleConf;
133 # Provide kbd with additional packages.
134 environment.etc.kbd.source = "${consoleEnv}/share";
135
136 boot.initrd.preLVMCommands = mkBefore ''
137 kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
138 printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
139 loadkmap < ${optimizedKeymap}
140
141 ${optionalString cfg.earlySetup ''
142 setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
143 ''}
144 '';
145
146 systemd.services.reload-systemd-vconsole-setup =
147 { description = "Reset console on configuration changes";
148 wantedBy = [ "multi-user.target" ];
149 restartTriggers = [ vconsoleConf consoleEnv ];
150 reloadIfChanged = true;
151 serviceConfig =
152 { RemainAfterExit = true;
153 ExecStart = "${pkgs.coreutils}/bin/true";
154 ExecReload = "/run/current-system/systemd/bin/systemctl restart systemd-vconsole-setup";
155 };
156 };
157 }
158
159 (mkIf (cfg.colors != []) {
160 boot.kernelParams = [
161 "vt.default_red=${makeColor 0 cfg.colors}"
162 "vt.default_grn=${makeColor 1 cfg.colors}"
163 "vt.default_blu=${makeColor 2 cfg.colors}"
164 ];
165 })
166
167 (mkIf cfg.earlySetup {
168 boot.initrd.extraUtilsCommands = ''
169 mkdir -p $out/share/consolefonts
170 ${if substring 0 1 cfg.font == "/" then ''
171 font="${cfg.font}"
172 '' else ''
173 font="$(echo ${consoleEnv}/share/consolefonts/${cfg.font}.*)"
174 ''}
175 if [[ $font == *.gz ]]; then
176 gzip -cd $font > $out/share/consolefonts/font.psf
177 else
178 cp -L $font $out/share/consolefonts/font.psf
179 fi
180 '';
181 })
182 ]))
183 ];
184
185 imports = [
186 (mkRenamedOptionModule [ "i18n" "consoleFont" ] [ "console" "font" ])
187 (mkRenamedOptionModule [ "i18n" "consoleKeyMap" ] [ "console" "keyMap" ])
188 (mkRenamedOptionModule [ "i18n" "consoleColors" ] [ "console" "colors" ])
189 (mkRenamedOptionModule [ "i18n" "consolePackages" ] [ "console" "packages" ])
190 (mkRenamedOptionModule [ "i18n" "consoleUseXkbConfig" ] [ "console" "useXkbConfig" ])
191 (mkRenamedOptionModule [ "boot" "earlyVconsoleSetup" ] [ "console" "earlySetup" ])
192 (mkRenamedOptionModule [ "boot" "extraTTYs" ] [ "console" "extraTTYs" ])
193 (mkRemovedOptionModule [ "console" "extraTTYs" ] ''
194 Since NixOS switched to systemd (circa 2012), TTYs have been spawned on
195 demand, so there is no need to configure them manually.
196 '')
197 ];
198}