Skip to content

Instantly share code, notes, and snippets.

@bennofs
Last active January 6, 2023 19:09
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bennofs/bb41b17deeeb49e345904f2339222625 to your computer and use it in GitHub Desktop.
Save bennofs/bb41b17deeeb49e345904f2339222625 to your computer and use it in GitHub Desktop.
Overview of the NixOS X11 session modules

How X11 is started

In the following example, sddm will be used as a display manager. The process is however similar for other display managers in nixpkgs and a summary that applies to all nixpkgs display managers is given at the end.

  1. Systemd unit "display-manager.service" starts services.x11.displayManager.job.execCmd (the display manager)

    Code reference: <nixpkgs>/nixos/modules/services/x11/xserver.nix

  2. services.x11.displayManager.job.execCmd is set to the path of the sddm binary from the sddm package in the nix store. So SDDM will start and read its configuration from /etc/sddm.conf.

    Code reference: <nixpkgs>/nixos/modules/services/x11/display-managers/sddm.nix

  3. /etc/sddm.conf sets three important options:

    • it sets the path to the xserver executable to a wrapper script that prepares the environment. In particular, the wrapper will run services.x11.displayManager.xserverBin, adding the arguments services.x11.displayManager.xserverArgs before any additional arguments specified when running the wrapper. The wrapper will also export the environment variables specified in systemd.services."display-manager".environment before executing the xserver.
    • It sets the directory to search for sessions to services.x11.displayManager.desktops. This is an automatically generated directory that contains a ".desktop" file for each possible session with more information about the session. For each desktop file, the Exec option is set to ${services.x11.displayManager.session.script} <session name>, so that script will be executed when the session should be started.
    • It sets the script to launch a session to services.x11.displayManager.session.script. This script is executed to start the session on a successful user login. Because of the ability to choose between different sessions (for example, between a gnome and a kde session), this script is passed the value of the Exec option of the selected session as an argument.

    Code reference: <nixpkgs>/nixos/modules/services/x11/display-managers/sddm.nix

  4. After reading the configuration, SDDM will start the XServer using the command set in the configuration file explained above. SDDM will handle the authentication of users (how users are authenticated can be configured though PAM), and on successful logins, the session script will be executed after changing to the user's account. Thus, the session script does not need to handle starting of the XServer itself, since it simply gains access to the XServer that SDDM started already.

  5. The session script has a special case for when the argument is a path: in that case, it just executes the argument. So combined with point 3, that means when a session is started, the command specified in the Exec property of the session's desktop file is executed.

Summary (this applies to any display manager in nixpkgs)

After a successful login, the display manager will execute the following command as the user who was logged in:

 ${services.x11.displayManager.session.script} <session name>

where session name is the name of the session that you selected when logging in, which uniquely identifies the window manager and the desktop manager that shall be used for this session. For example, a typical session name looks like kde + xmonad. How these sessions are generated and what the session script does is explained in the next sections.

How sessions are generated

In nixpkgs, a session is always a combination of a window manager (such as xmonad, awesome, openbox, ...) and a desktop manager (such as kde, gnome, ...). Either of those may be "none", to signal that this session has no desktop manager or no window manager. The name of a session is <desktop manager name> + <window manager name>, where the + <window manager name> part is omitted if the window manager is "none".

The list of available window managers and desktop managers is stored in the nixos option services.x11.displayManager.session. Each entry in this list is a set with three attributes: name, manage (either "desktop" or "window") and start, which specifies the script that is executed to start this entry.

Code reference: <nixpkgs>/nixos/modules/x11/display-managers/default.nix

This list automatically the "none" desktop manager and window manager plus all enabled window managers (stored in services.x11.windowManager.session, to which each window manager adds itself if is enabled) and all enabled desktop managers (stored services.x11.desktopManager.session).

Code references:

What actually happens if a session is started is explained in the next section.

How a session is started

As explained in the first section, when a session is started, the session script will be executed. The full session script can be found at <nixpkgs>/nixos/modules/services/x11/display-manager/default.nix, the following text will summarize the most important parts.

  1. First, some general setup is performed. This includes sourcing /etc/profile, setting up logging (either to ~/.xsession-errors or to systemd journal if services.x11.displayManager.logToJournal is true), and parsing the arguments to get the name of the session to be started. You can look at the source to find out in detail what is happening in this phase.
  2. After setting up the environment, the commands in specified in the nixos option services.x11.displayManager.sessionCommands are executed.
  3. The file ~/.xprofile is sourced if it exists. If ~/.xsession exists, that file is exec'd, so the session script hands over control to that script. Otherwise, it continues.
  4. If the session name is either "default" or "custom", it is set to "".
  5. The name of the desktop manager and the name of the window manager is extracted from the name of the session. This is done by splitting the session name on the first + (enclosed by spaces), everything before that is considered the desktop manager name and everything after that is the window manager name. If after this, the desktop manager name is empty (this happens if the session name is "default" or "custom" and was thus in step 4 set to "" so the part before any "+" is empty), then it is set to the default, specified by nixos option services.x11.desktopManager.default. The same applies if the window manager name is empty (happens if the session name contains no +), in this case services.x11.windowManager.default specifies the default.
  6. Now, the script executes the start script of the extracted window manager and then the start script of the extracted desktop manager. After that, it waits till the process with the PID stored in the variable $waitPID exits, if $waitPID is set (this variable should be set by either the desktop manager or the window manager start script, if those scripts don't block till the session is finished).

Interesting consequences

  • The module never generates a session for starting a desktop manager without a window manager. The combination <desktop manager> + none is never generated, since none is stripped from the session name and it becomes <desktop manager> instead, which causes the default window manager to be used.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment