at master 6.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.services.getty; 12 13 baseArgs = [ 14 "--login-program" 15 "${cfg.loginProgram}" 16 ] 17 ++ optionals (cfg.autologinUser != null && !cfg.autologinOnce) [ 18 "--autologin" 19 cfg.autologinUser 20 ] 21 ++ optionals (cfg.loginOptions != null) [ 22 "--login-options" 23 cfg.loginOptions 24 ] 25 ++ cfg.extraArgs; 26 27 gettyCmd = args: "${lib.getExe' pkgs.util-linux "agetty"} ${escapeShellArgs baseArgs} ${args}"; 28 29 autologinScript = '' 30 otherArgs="--noclear --keep-baud $TTY 115200,38400,9600 $TERM"; 31 ${lib.optionalString cfg.autologinOnce '' 32 autologged="/run/agetty.autologged" 33 if test "$TTY" = tty1 && ! test -f "$autologged"; then 34 touch "$autologged" 35 exec ${gettyCmd "$otherArgs --autologin ${cfg.autologinUser}"} 36 fi 37 ''} 38 exec ${gettyCmd "$otherArgs"} 39 ''; 40 41in 42 43{ 44 45 ###### interface 46 47 imports = [ 48 (mkRenamedOptionModule [ "services" "mingetty" ] [ "services" "getty" ]) 49 (mkRemovedOptionModule [ "services" "getty" "serialSpeed" ] 50 ''set non-standard baudrates with `boot.kernelParams` i.e. boot.kernelParams = ["console=ttyS2,1500000"];'' 51 ) 52 ]; 53 54 options = { 55 56 services.getty = { 57 58 autologinUser = mkOption { 59 type = types.nullOr types.str; 60 default = null; 61 description = '' 62 Username of the account that will be automatically logged in at the console. 63 If unspecified, a login prompt is shown as usual. 64 ''; 65 }; 66 67 autologinOnce = mkOption { 68 type = types.bool; 69 default = false; 70 description = '' 71 If enabled the automatic login will only happen in the first tty 72 once per boot. This can be useful to avoid retyping the account 73 password on systems with full disk encrypted. 74 ''; 75 }; 76 77 loginProgram = mkOption { 78 type = types.path; 79 default = "${pkgs.shadow}/bin/login"; 80 defaultText = literalExpression ''"''${pkgs.shadow}/bin/login"''; 81 description = '' 82 Path to the login binary executed by agetty. 83 ''; 84 }; 85 86 loginOptions = mkOption { 87 type = types.nullOr types.str; 88 default = null; 89 description = '' 90 Template for arguments to be passed to 91 {manpage}`login(1)`. 92 93 See {manpage}`agetty(1)` for details, 94 including security considerations. If unspecified, agetty 95 will not be invoked with a {option}`--login-options` 96 option. 97 ''; 98 example = "-h darkstar -- \\u"; 99 }; 100 101 extraArgs = mkOption { 102 type = types.listOf types.str; 103 default = [ ]; 104 description = '' 105 Additional arguments passed to agetty. 106 ''; 107 example = [ "--nohostname" ]; 108 }; 109 110 greetingLine = mkOption { 111 type = types.str; 112 description = '' 113 Welcome line printed by agetty. 114 The default shows current NixOS version label, machine type and tty. 115 ''; 116 }; 117 118 helpLine = mkOption { 119 type = types.lines; 120 default = ""; 121 description = '' 122 Help line printed by agetty below the welcome line. 123 Used by the installation CD to give some hints on 124 how to proceed. 125 ''; 126 }; 127 128 }; 129 130 }; 131 132 ###### implementation 133 134 config = mkIf config.console.enable { 135 # Note: this is set here rather than up there so that changing 136 # nixos.label would not rebuild manual pages 137 services.getty.greetingLine = mkDefault ''<<< Welcome to ${config.system.nixos.distroName} ${config.system.nixos.label} (\m) - \l >>>''; 138 services.getty.helpLine = mkIf ( 139 config.documentation.nixos.enable && config.documentation.doc.enable 140 ) "\nRun 'nixos-help' for the NixOS manual."; 141 142 systemd.additionalUpstreamSystemUnits = [ 143 "getty.target" 144 "getty-pre.target" 145 "getty@.service" 146 "serial-getty@.service" 147 "console-getty.service" 148 "container-getty@.service" 149 ]; 150 151 # We can't just rely on 'Conflicts=autovt@tty1.service' because 152 # 'switch-to-configuration switch' will start 'autovt@tty1.service' 153 # and kill the display manager. 154 systemd.targets.getty.wants = 155 lib.mkIf (!(config.systemd.services.display-manager.enable or false)) 156 [ 157 "autovt@tty1.service" 158 ]; 159 160 systemd.services."getty@" = { 161 serviceConfig.ExecStart = [ 162 # override upstream default with an empty ExecStart 163 "" 164 (pkgs.writers.writeDash "getty" autologinScript) 165 ]; 166 environment.TTY = "%I"; 167 restartIfChanged = false; 168 }; 169 170 systemd.services."serial-getty@" = { 171 serviceConfig.ExecStart = [ 172 "" # override upstream default with an empty ExecStart 173 (gettyCmd "%I --keep-baud $TERM") 174 ]; 175 restartIfChanged = false; 176 }; 177 178 systemd.services."autovt@" = { 179 serviceConfig.ExecStart = [ 180 "" # override upstream default with an empty ExecStart 181 (gettyCmd "--noclear %I $TERM") 182 ]; 183 restartIfChanged = false; 184 }; 185 186 systemd.services."container-getty@" = { 187 serviceConfig.ExecStart = [ 188 "" # override upstream default with an empty ExecStart 189 (gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM") 190 ]; 191 restartIfChanged = false; 192 }; 193 194 systemd.services.console-getty = { 195 serviceConfig.ExecStart = [ 196 "" # override upstream default with an empty ExecStart 197 (gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM") 198 ]; 199 serviceConfig.Restart = "always"; 200 restartIfChanged = false; 201 enable = mkDefault config.boot.isContainer; 202 }; 203 204 environment.etc.issue = mkDefault { 205 # Friendly greeting on the virtual consoles. 206 source = pkgs.writeText "issue" '' 207 208 ${config.services.getty.greetingLine} 209 ${config.services.getty.helpLine} 210 211 ''; 212 }; 213 214 }; 215 216 meta.maintainers = with maintainers; [ RossComputerGuy ]; 217}