Automatic login with startx and systemd
Vincent Bernat
If your workstation is using full-disk encryption, you may want to jump directly to your desktop environment after entering the passphrase to decrypt the disk. Many display managers like GDM and LightDM have an autologin feature. However, only GDM can run Xorg with standard user privileges.
Here is an alternative using startx and a systemd service:
[Unit] Description=X11 session for bernat After=graphical.target systemd-user-sessions.service [Service] User=bernat WorkingDirectory=~ PAMName=login Environment=XDG_SESSION_TYPE=x11 TTYPath=/dev/tty8 StandardInput=tty UnsetEnvironment=TERM UtmpIdentifier=tty8 UtmpMode=user StandardOutput=journal ExecStartPre=/usr/bin/chvt 8 ExecStart=/usr/bin/startx -- vt8 -keeptty -verbose 3 -logfile /dev/null Restart=no [Install] WantedBy=graphical.target
Let me explain each block:
- 
The unit starts after
systemd-user-sessions.service, which enables user logins after boot by removing the/run/nologinfile. - 
With
User=bernat, the unit is started with the identity of the specified user. This implies thatXorgdoes not run with elevated privileges. - 
With
PAMName=login, the executed process is registered as a PAM session for theloginservice, which includes pam_systemd. This module registers the session to the systemd login manager. To be effective, we also need to allocate a TTY withTTYPath=/dev/tty8. When the TTY is active, the user is granted additional access to local devices—notably display, sound, keyboard, mouse. These additional rights are needed to get Xorg working rootless.1 TheTERMenvironment variable is unset because it would be set tolinuxby systemd as a result of attaching the standard input to the TTY. Moreover, we informpam_systemdwe want an X11 session withEnvironment=XDG_SESSION_TYPE=x11. Otherwise,logindconsiders the session idle unless it receives input on the TTY. Software relying on the idle hint fromlogindwould be ineffective.2 - 
The
UtmpIdentifier=tty8andUtmpMode=userdirectives are just a nice addition to register the session in/var/run/utmp. - 
The last step is to execute
Xorgthroughstartx. Forlogindto allowXorgto take control of the local devices,chvt 8switches to the allocated TTY.3StandardOutput=journal, combined with the-verbose 3 -logfile /dev/nullflags forXorg, puts the logs from the X server into the journal instead of using a file. While equal to the default value, theRestart=nodirective highlights we do not want this unit to be restarted. This ensures the loginless session is only available on boot. By default,startxrunsxinitrc. If you want to run Kodi instead, add/usr/bin/kodi-standalonebetweenstartxand--. 
Drop this unit in /etc/systemd/system/x11-autologin.service and
enable it with systemctl enable x11-autologin.service. Xorg is now
running rootless and logging into the journal. After using it for a
few months, I didn’t notice any regression compared to LightDM with
autologin.
- 
For more information on how
logindprovides access to devices, see this blog post. The method names do not match the current implementation, but the concepts are still correct.Xorgtakes control of the session when the TTY is active. ↩︎ - 
Xorg could change the type of the session itself after taking control of it, but it does not. ↩︎
 - 
There is some code in Xorg to do that, but it is executed too late and fails with:
xf86OpenConsole: VT_ACTIVATE failed: Operation not permitted. ↩︎