1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7let
8 inherit (lib)
9 mkIf
10 mkEnableOption
11 mkOption
12 mkPackageOption
13 optional
14 optionals
15 types
16 ;
17
18 cfg = config.services.kmscon;
19
20 autologinArg = lib.optionalString (cfg.autologinUser != null) "-f ${cfg.autologinUser}";
21
22 configDir = pkgs.writeTextFile {
23 name = "kmscon-config";
24 destination = "/kmscon.conf";
25 text = cfg.extraConfig;
26 };
27in
28{
29 options = {
30 services.kmscon = {
31 enable = mkEnableOption ''
32 kmscon as the virtual console instead of gettys.
33 kmscon is a kms/dri-based userspace virtual terminal implementation.
34 It supports a richer feature set than the standard linux console VT,
35 including full unicode support, and when the video card supports drm
36 should be much faster
37 '';
38
39 package = mkPackageOption pkgs "kmscon" { };
40
41 hwRender = mkEnableOption "3D hardware acceleration to render the console";
42
43 fonts = mkOption {
44 description = "Fonts used by kmscon, in order of priority.";
45 default = null;
46 example = lib.literalExpression ''[ { name = "Source Code Pro"; package = pkgs.source-code-pro; } ]'';
47 type =
48 with types;
49 let
50 fontType = submodule {
51 options = {
52 name = mkOption {
53 type = str;
54 description = "Font name, as used by fontconfig.";
55 };
56 package = mkOption {
57 type = package;
58 description = "Package providing the font.";
59 };
60 };
61 };
62 in
63 nullOr (nonEmptyListOf fontType);
64 };
65
66 useXkbConfig = mkEnableOption "" // {
67 description = "Whether to configure keymap from xserver keyboard settings.";
68 };
69
70 extraConfig = mkOption {
71 description = "Extra contents of the kmscon.conf file.";
72 type = types.lines;
73 default = "";
74 example = "font-size=14";
75 };
76
77 extraOptions = mkOption {
78 description = "Extra flags to pass to kmscon.";
79 type = types.separatedString " ";
80 default = "";
81 example = "--term xterm-256color";
82 };
83
84 autologinUser = mkOption {
85 type = types.nullOr types.str;
86 default = null;
87 description = ''
88 Username of the account that will be automatically logged in at the console.
89 If unspecified, a login prompt is shown as usual.
90 '';
91 };
92 };
93 };
94
95 config = mkIf cfg.enable {
96 systemd.packages = [ cfg.package ];
97
98 systemd.services."kmsconvt@" = {
99 after = [
100 "systemd-logind.service"
101 "systemd-vconsole-setup.service"
102 ];
103 requires = [ "systemd-logind.service" ];
104
105 serviceConfig.ExecStart = [
106 ""
107 ''
108 ${cfg.package}/bin/kmscon "--vt=%I" ${cfg.extraOptions} --seats=seat0 --no-switchvt --configdir ${configDir} --login -- ${pkgs.shadow}/bin/login -p ${autologinArg}
109 ''
110 ];
111
112 restartIfChanged = false;
113 aliases = [ "autovt@.service" ];
114 };
115
116 systemd.suppressedSystemUnits = [ "autovt@.service" ];
117
118 systemd.services.systemd-vconsole-setup.enable = false;
119 systemd.services.reload-systemd-vconsole-setup.enable = false;
120
121 services.kmscon.extraConfig =
122 let
123 xkb = optionals cfg.useXkbConfig (
124 lib.mapAttrsToList (n: v: "xkb-${n}=${v}") (
125 lib.filterAttrs (
126 n: v:
127 builtins.elem n [
128 "layout"
129 "model"
130 "options"
131 "variant"
132 ]
133 && v != ""
134 ) config.services.xserver.xkb
135 )
136 );
137 render = optionals cfg.hwRender [
138 "drm"
139 "hwaccel"
140 ];
141 fonts =
142 optional (cfg.fonts != null)
143 "font-name=${lib.concatMapStringsSep ", " (f: f.name) cfg.fonts}";
144 in
145 lib.concatLines (xkb ++ render ++ fonts);
146
147 hardware.graphics.enable = mkIf cfg.hwRender true;
148
149 fonts = mkIf (cfg.fonts != null) {
150 fontconfig.enable = true;
151 packages = map (f: f.package) cfg.fonts;
152 };
153 };
154}