1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.getty;
7
8 baseArgs = [
9 "--login-program" "${pkgs.shadow}/bin/login"
10 ] ++ optionals (cfg.autologinUser != null) [
11 "--autologin" cfg.autologinUser
12 ] ++ optionals (cfg.loginOptions != null) [
13 "--login-options" cfg.loginOptions
14 ] ++ cfg.extraArgs;
15
16 gettyCmd = args:
17 "@${pkgs.util-linux}/sbin/agetty agetty ${escapeShellArgs baseArgs} ${args}";
18
19in
20
21{
22
23 ###### interface
24
25 imports = [
26 (mkRenamedOptionModule [ "services" "mingetty" ] [ "services" "getty" ])
27 ];
28
29 options = {
30
31 services.getty = {
32
33 autologinUser = mkOption {
34 type = types.nullOr types.str;
35 default = null;
36 description = ''
37 Username of the account that will be automatically logged in at the console.
38 If unspecified, a login prompt is shown as usual.
39 '';
40 };
41
42 loginOptions = mkOption {
43 type = types.nullOr types.str;
44 default = null;
45 description = ''
46 Template for arguments to be passed to
47 <citerefentry><refentrytitle>login</refentrytitle>
48 <manvolnum>1</manvolnum></citerefentry>.
49
50 See <citerefentry><refentrytitle>agetty</refentrytitle>
51 <manvolnum>1</manvolnum></citerefentry> for details,
52 including security considerations. If unspecified, agetty
53 will not be invoked with a <option>--login-options</option>
54 option.
55 '';
56 example = "-h darkstar -- \\u";
57 };
58
59 extraArgs = mkOption {
60 type = types.listOf types.str;
61 default = [ ];
62 description = ''
63 Additional arguments passed to agetty.
64 '';
65 example = [ "--nohostname" ];
66 };
67
68 greetingLine = mkOption {
69 type = types.str;
70 description = ''
71 Welcome line printed by agetty.
72 The default shows current NixOS version label, machine type and tty.
73 '';
74 };
75
76 helpLine = mkOption {
77 type = types.lines;
78 default = "";
79 description = ''
80 Help line printed by agetty below the welcome line.
81 Used by the installation CD to give some hints on
82 how to proceed.
83 '';
84 };
85
86 serialSpeed = mkOption {
87 type = types.listOf types.int;
88 default = [ 115200 57600 38400 9600 ];
89 example = [ 38400 9600 ];
90 description = ''
91 Bitrates to allow for agetty's listening on serial ports. Listing more
92 bitrates gives more interoperability but at the cost of long delays
93 for getting a sync on the line.
94 '';
95 };
96
97 };
98
99 };
100
101
102 ###### implementation
103
104 config = {
105 # Note: this is set here rather than up there so that changing
106 # nixos.label would not rebuild manual pages
107 services.getty.greetingLine = mkDefault ''<<< Welcome to NixOS ${config.system.nixos.label} (\m) - \l >>>'';
108
109 systemd.services."getty@" =
110 { serviceConfig.ExecStart = [
111 "" # override upstream default with an empty ExecStart
112 (gettyCmd "--noclear --keep-baud %I 115200,38400,9600 $TERM")
113 ];
114 restartIfChanged = false;
115 };
116
117 systemd.services."serial-getty@" =
118 let speeds = concatStringsSep "," (map toString config.services.getty.serialSpeed); in
119 { serviceConfig.ExecStart = [
120 "" # override upstream default with an empty ExecStart
121 (gettyCmd "%I ${speeds} $TERM")
122 ];
123 restartIfChanged = false;
124 };
125
126 systemd.services."container-getty@" =
127 { serviceConfig.ExecStart = [
128 "" # override upstream default with an empty ExecStart
129 (gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM")
130 ];
131 restartIfChanged = false;
132 };
133
134 systemd.services.console-getty =
135 { serviceConfig.ExecStart = [
136 "" # override upstream default with an empty ExecStart
137 (gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM")
138 ];
139 serviceConfig.Restart = "always";
140 restartIfChanged = false;
141 enable = mkDefault config.boot.isContainer;
142 };
143
144 environment.etc.issue =
145 { # Friendly greeting on the virtual consoles.
146 source = pkgs.writeText "issue" ''
147
148 [1;32m${config.services.getty.greetingLine}[0m
149 ${config.services.getty.helpLine}
150
151 '';
152 };
153
154 };
155
156}