summary refs log tree commit diff
path: root/nixos/modules/config/console.nix
blob: f662ed62d31dc003101348df51462708a3212903 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
{ config, lib, pkgs, ... }:

with lib;

let
  cfg = config.console;

  makeColor = i: concatMapStringsSep "," (x: "0x" + substring (2*i) 2 x);

  isUnicode = hasSuffix "UTF-8" (toUpper config.i18n.defaultLocale);

  optimizedKeymap = pkgs.runCommand "keymap" {
    nativeBuildInputs = [ pkgs.buildPackages.kbd ];
    LOADKEYS_KEYMAP_PATH = "${consoleEnv}/share/keymaps/**";
    preferLocalBuild = true;
  } ''
    loadkeys -b ${optionalString isUnicode "-u"} "${cfg.keyMap}" > $out
  '';

  # Sadly, systemd-vconsole-setup doesn't support binary keymaps.
  vconsoleConf = pkgs.writeText "vconsole.conf" ''
    KEYMAP=${cfg.keyMap}
    FONT=${cfg.font}
  '';

  consoleEnv = pkgs.buildEnv {
    name = "console-env";
    paths = [ pkgs.kbd ] ++ cfg.packages;
    pathsToLink = [
      "/share/consolefonts"
      "/share/consoletrans"
      "/share/keymaps"
      "/share/unimaps"
    ];
  };

  setVconsole = !config.boot.isContainer;
in

{
  ###### interface

  options.console  = {
    font = mkOption {
      type = types.str;
      default = "Lat2-Terminus16";
      example = "LatArCyrHeb-16";
      description = ''
        The font used for the virtual consoles.  Leave empty to use
        whatever the <command>setfont</command> program considers the
        default font.
      '';
    };

    keyMap = mkOption {
      type = with types; either str path;
      default = "us";
      example = "fr";
      description = ''
        The keyboard mapping table for the virtual consoles.
      '';
    };

    colors = mkOption {
      type = types.listOf types.str;
      default = [];
      example = [
        "002b36" "dc322f" "859900" "b58900"
        "268bd2" "d33682" "2aa198" "eee8d5"
        "002b36" "cb4b16" "586e75" "657b83"
        "839496" "6c71c4" "93a1a1" "fdf6e3"
      ];
      description = ''
        The 16 colors palette used by the virtual consoles.
        Leave empty to use the default colors.
        Colors must be in hexadecimal format and listed in
        order from color 0 to color 15.
      '';

    };

    packages = mkOption {
      type = types.listOf types.package;
      default = with pkgs.kbdKeymaps; [ dvp neo ];
      defaultText = ''with pkgs.kbdKeymaps; [ dvp neo ]'';
      description = ''
        List of additional packages that provide console fonts, keymaps and
        other resources for virtual consoles use.
      '';
    };

    extraTTYs = mkOption {
      default = [];
      type = types.listOf types.str;
      example = ["tty8" "tty9"];
      description = ''
        TTY (virtual console) devices, in addition to the consoles on
        which mingetty and syslogd run, that must be initialised.
        Only useful if you have some program that you want to run on
        some fixed console.  For example, the NixOS installation CD
        opens the manual in a web browser on console 7, so it sets
        <option>console.extraTTYs</option> to <literal>["tty7"]</literal>.
      '';
    };

    useXkbConfig = mkOption {
      type = types.bool;
      default = false;
      description = ''
        If set, configure the virtual console keymap from the xserver
        keyboard settings.
      '';
    };

    earlySetup = mkOption {
      default = false;
      type = types.bool;
      description = ''
        Enable setting virtual console options as early as possible (in initrd).
      '';
    };

  };


  ###### implementation

  config = mkMerge [
    { console.keyMap = with config.services.xserver;
        mkIf cfg.useXkbConfig
          (pkgs.runCommand "xkb-console-keymap" { preferLocalBuild = true; } ''
            '${pkgs.ckbcomp}/bin/ckbcomp' -model '${xkbModel}' -layout '${layout}' \
              -option '${xkbOptions}' -variant '${xkbVariant}' > "$out"
          '');
    }

    (mkIf (!setVconsole) {
      systemd.services.systemd-vconsole-setup.enable = false;
    })

    (mkIf setVconsole (mkMerge [
      { environment.systemPackages = [ pkgs.kbd ];

        # Let systemd-vconsole-setup.service do the work of setting up the
        # virtual consoles.
        environment.etc."vconsole.conf".source = vconsoleConf;
        # Provide kbd with additional packages.
        environment.etc.kbd.source = "${consoleEnv}/share";

        boot.initrd.preLVMCommands = mkBefore ''
          kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
          printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
          loadkmap < ${optimizedKeymap}

          ${optionalString cfg.earlySetup ''
            setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
          ''}
        '';

        systemd.services.systemd-vconsole-setup =
          { before = [ "display-manager.service" ];
            after = [ "systemd-udev-settle.service" ];
            restartTriggers = [ vconsoleConf consoleEnv ];
          };
      }

      (mkIf (cfg.colors != []) {
        boot.kernelParams = [
          "vt.default_red=${makeColor 0 cfg.colors}"
          "vt.default_grn=${makeColor 1 cfg.colors}"
          "vt.default_blu=${makeColor 2 cfg.colors}"
        ];
      })

      (mkIf cfg.earlySetup {
        boot.initrd.extraUtilsCommands = ''
          mkdir -p $out/share/consolefonts
          ${if substring 0 1 cfg.font == "/" then ''
            font="${cfg.font}"
          '' else ''
            font="$(echo ${consoleEnv}/share/consolefonts/${cfg.font}.*)"
          ''}
          if [[ $font == *.gz ]]; then
            gzip -cd $font > $out/share/consolefonts/font.psf
          else
            cp -L $font $out/share/consolefonts/font.psf
          fi
        '';
      })
    ]))
  ];

  imports = [
    (mkRenamedOptionModule [ "i18n" "consoleFont" ] [ "console" "font" ])
    (mkRenamedOptionModule [ "i18n" "consoleKeyMap" ] [ "console" "keyMap" ])
    (mkRenamedOptionModule [ "i18n" "consoleColors" ] [ "console" "colors" ])
    (mkRenamedOptionModule [ "i18n" "consolePackages" ] [ "console" "packages" ])
    (mkRenamedOptionModule [ "i18n" "consoleUseXkbConfig" ] [ "console" "useXkbConfig" ])
    (mkRenamedOptionModule [ "boot" "earlyVconsoleSetup" ] [ "console" "earlySetup" ])
    (mkRenamedOptionModule [ "boot" "extraTTYs" ] [ "console" "extraTTYs" ])
  ];
}