diff options
Diffstat (limited to 'nixos/modules/services/x11/display-managers')
-rw-r--r-- | nixos/modules/services/x11/display-managers/auto.nix | 52 | ||||
-rw-r--r-- | nixos/modules/services/x11/display-managers/default.nix | 283 | ||||
-rw-r--r-- | nixos/modules/services/x11/display-managers/kdm.nix | 151 | ||||
-rw-r--r-- | nixos/modules/services/x11/display-managers/lightdm.nix | 119 | ||||
-rw-r--r-- | nixos/modules/services/x11/display-managers/slim.nix | 113 |
5 files changed, 718 insertions, 0 deletions
diff --git a/nixos/modules/services/x11/display-managers/auto.nix b/nixos/modules/services/x11/display-managers/auto.nix new file mode 100644 index 0000000000000..33d97e0e07a95 --- /dev/null +++ b/nixos/modules/services/x11/display-managers/auto.nix @@ -0,0 +1,52 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + cfg = dmcfg.auto; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.auto = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the fake "auto" display manager, which + automatically logs in the user specified in the + <option>user</option> option. This is mostly useful for + automated tests. + ''; + }; + + user = mkOption { + default = "root"; + description = "The user account to login automatically."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.displayManager.slim = { + enable = true; + autoLogin = true; + defaultUser = cfg.user; + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix new file mode 100644 index 0000000000000..c7599e245b059 --- /dev/null +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -0,0 +1,283 @@ +# This module declares the options to define a *display manager*, the +# program responsible for handling X logins (such as xdm, kdm, gdb, or +# SLiM). The display manager allows the user to select a *session +# type*. When the user logs in, the display manager starts the +# *session script* ("xsession" below) to launch the selected session +# type. The session type defines two things: the *desktop manager* +# (e.g., KDE, Gnome or a plain xterm), and optionally the *window +# manager* (e.g. kwin or twm). + +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver; + xorg = pkgs.xorg; + + vaapiDrivers = pkgs.buildEnv { + name = "vaapi-drivers"; + paths = cfg.vaapiDrivers; + # We only want /lib/dri, but with a single input path, we need "/" for it to work + pathsToLink = [ "/" ]; + }; + + # file provided by services.xserver.displayManager.session.script + xsession = wm: dm: pkgs.writeScript "xsession" + '' + #! /bin/sh + + . /etc/profile + cd "$HOME" + + # The first argument of this script is the session type. + sessionType="$1" + if [ "$sessionType" = default ]; then sessionType=""; fi + + ${optionalString (!cfg.displayManager.job.logsXsession) '' + exec > ~/.xsession-errors 2>&1 + ''} + + ${optionalString cfg.displayManager.desktopManagerHandlesLidAndPower '' + # Stop systemd from handling the power button and lid switch, + # since presumably the desktop environment will handle these. + if [ -z "$_INHIBITION_LOCK_TAKEN" ]; then + export _INHIBITION_LOCK_TAKEN=1 + exec ${config.systemd.package}/bin/systemd-inhibit --what=handle-lid-switch:handle-power-key "$0" "$sessionType" + fi + + ''} + + ${optionalString cfg.startOpenSSHAgent '' + if test -z "$SSH_AUTH_SOCK"; then + # Restart this script as a child of the SSH agent. (It is + # also possible to start the agent as a child that prints + # the required environment variabled on stdout, but in + # that mode ssh-agent is not terminated when we log out.) + export SSH_ASKPASS=${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass + exec ${pkgs.openssh}/bin/ssh-agent "$0" "$sessionType" + fi + ''} + + ${optionalString cfg.startGnuPGAgent '' + if test -z "$SSH_AUTH_SOCK"; then + # Restart this script as a child of the GnuPG agent. + exec "${pkgs.gnupg}/bin/gpg-agent" \ + --enable-ssh-support --daemon \ + --pinentry-program "${pkgs.pinentry}/bin/pinentry-gtk-2" \ + --write-env-file "$HOME/.gpg-agent-info" \ + "$0" "$sessionType" + fi + ''} + + # Handle being called by kdm. + if test "''${1:0:1}" = /; then eval exec "$1"; fi + + # Start PulseAudio if enabled. + ${optionalString (config.hardware.pulseaudio.enable) '' + ${optionalString (!config.hardware.pulseaudio.systemWide) + "${pkgs.pulseaudio}/bin/pulseaudio --start" + } + + # Publish access credentials in the root window. + ${pkgs.pulseaudio}/bin/pactl load-module module-x11-publish "display=$DISPLAY" + + # Keep track of devices. Mostly useful for Phonon/KDE. + ${pkgs.pulseaudio}/bin/pactl load-module module-device-manager "do_routing=1" + ''} + + # Load X defaults. + if test -e ~/.Xdefaults; then + ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults + fi + + export LIBVA_DRIVERS_PATH=${vaapiDrivers}/lib/dri + + # Speed up application start by 50-150ms according to + # http://kdemonkey.blogspot.nl/2008/04/magic-trick.html + rm -rf $HOME/.compose-cache + mkdir $HOME/.compose-cache + + ${cfg.displayManager.sessionCommands} + + # Allow the user to setup a custom session type. + if test -x ~/.xsession; then + exec ~/.xsession + else + if test "$sessionType" = "custom"; then + sessionType="" # fall-thru if there is no ~/.xsession + fi + fi + + # The session type is "<desktop-manager> + <window-manager>", so + # extract those. + windowManager="''${sessionType##* + }" + : ''${windowManager:=${cfg.windowManager.default}} + desktopManager="''${sessionType% + *}" + : ''${desktopManager:=${cfg.desktopManager.default}} + + # Start the window manager. + case $windowManager in + ${concatMapStrings (s: '' + (${s.name}) + ${s.start} + ;; + '') wm} + (*) echo "$0: Window manager '$windowManager' not found.";; + esac + + # Start the desktop manager. + case $desktopManager in + ${concatMapStrings (s: '' + (${s.name}) + ${s.start} + ;; + '') dm} + (*) echo "$0: Desktop manager '$desktopManager' not found.";; + esac + + test -n "$waitPID" && wait "$waitPID" + exit 0 + ''; + + mkDesktops = names: pkgs.runCommand "desktops" {} + '' + mkdir -p $out + ${concatMapStrings (n: '' + cat - > "$out/${n}.desktop" << EODESKTOP + [Desktop Entry] + Version=1.0 + Type=XSession + TryExec=${cfg.displayManager.session.script} + Exec=${cfg.displayManager.session.script} '${n}' + Name=${n} + Comment= + EODESKTOP + '') names} + ''; + +in + +{ + + options = { + + services.xserver.displayManager = { + + xauthBin = mkOption { + default = "${xorg.xauth}/bin/xauth"; + description = "Path to the <command>xauth</command> program used by display managers."; + }; + + xserverBin = mkOption { + default = "${xorg.xorgserver}/bin/X"; + description = "Path to the X server used by display managers."; + }; + + xserverArgs = mkOption { + default = []; + example = [ "-ac" "-logverbose" "-nolisten tcp" ]; + description = "List of arguments for the X server."; + apply = toString; + }; + + sessionCommands = mkOption { + default = ""; + example = + '' + xmessage "Hello World!" & + ''; + type = types.string; + description = "Shell commands executed just before the window or desktop manager is started."; + }; + + desktopManagerHandlesLidAndPower = mkOption { + default = true; + description = '' + Whether the display manager should prevent systemd from handling + lid and power events. This is normally handled by the desktop + environment's power manager. Turn this off when using a minimal + X11 setup without a full power manager. + ''; + }; + + session = mkOption { + default = []; + example = [ + { + manage = "desktop"; + name = "xterm"; + start = " + ${pkgs.xterm}/bin/xterm -ls & + waitPID=$! + "; + } + ]; + description = '' + List of sessions supported with the command used to start each + session. Each session script can set the + <varname>waitPID</varname> shell variable to make this script + wait until the end of the user session. Each script is used + to define either a windows manager or a desktop manager. These + can be differentiated by setting the attribute + <varname>manage</varname> either to <literal>"window"</literal> + or <literal>"desktop"</literal>. + + The list of desktop manager and window manager should appear + inside the display manager with the desktop manager name + followed by the window manager name. + ''; + apply = list: rec { + wm = filter (s: s.manage == "window") list; + dm = filter (s: s.manage == "desktop") list; + names = flip concatMap dm + (d: map (w: d.name + optionalString (w.name != "none") (" + " + w.name)) + (filter (w: d.name != "none" || w.name != "none") wm)); + desktops = mkDesktops names; + script = xsession wm dm; + }; + }; + + job = mkOption { + default = {}; + type = types.uniq types.optionSet; + description = "This option defines how to start the display manager."; + + options = { + + preStart = mkOption { + default = ""; + example = "rm -f /var/log/my-display-manager.log"; + description = "Script executed before the display manager is started."; + }; + + execCmd = mkOption { + example = "${pkgs.slim}/bin/slim"; + description = "Command to start the display manager."; + }; + + environment = mkOption { + default = {}; + example = { SLIM_CFGFILE = /etc/slim.conf; }; + description = "Additional environment variables needed by the display manager."; + }; + + logsXsession = mkOption { + default = false; + description = '' + Whether the display manager redirects the + output of the session script to + <filename>~/.xsession-errors</filename>. + ''; + }; + + }; + + }; + + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix new file mode 100644 index 0000000000000..229ab12c6e1ba --- /dev/null +++ b/nixos/modules/services/x11/display-managers/kdm.nix @@ -0,0 +1,151 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + cfg = dmcfg.kdm; + + inherit (pkgs.kde4) kdebase_workspace; + + defaultConfig = + '' + [Shutdown] + HaltCmd=${config.systemd.package}/sbin/shutdown -h now + RebootCmd=${config.systemd.package}/sbin/shutdown -r now + ${optionalString (config.system.boot.loader.id == "grub") '' + BootManager=${if config.boot.loader.grub.version == 2 then "Grub2" else "Grub"} + ''} + + [X-*-Core] + Xrdb=${pkgs.xlibs.xrdb}/bin/xrdb + SessionsDirs=${dmcfg.session.desktops} + Session=${dmcfg.session.script} + FailsafeClient=${pkgs.xterm}/bin/xterm + + [X-:*-Core] + ServerCmd=${dmcfg.xserverBin} ${dmcfg.xserverArgs} + # KDM calls `rm' somewhere to clean up some temporary directory. + SystemPath=${pkgs.coreutils}/bin + # The default timeout (15) is too short in a heavily loaded boot process. + ServerTimeout=60 + # Needed to prevent the X server from dying on logout and not coming back: + TerminateServer=true + ${optionalString (cfg.setupScript != "") + '' + Setup=${cfg.setupScript} + ''} + + [X-*-Greeter] + HiddenUsers=root,nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10 + PluginsLogin=${kdebase_workspace}/lib/kde4/kgreet_classic.so + ${optionalString (cfg.themeDirectory != "") + '' + UseTheme=true + Theme=${cfg.themeDirectory} + '' + } + + ${optionalString (cfg.enableXDMCP) + '' + [Xdmcp] + Enable=true + ''} + ''; + + kdmrc = pkgs.stdenv.mkDerivation { + name = "kdmrc"; + config = defaultConfig + cfg.extraConfig; + buildCommand = + '' + echo "$config" > $out + + # The default kdmrc would add "-nolisten tcp", and we already + # have that managed by nixos. Hence the grep. + cat ${kdebase_workspace}/share/config/kdm/kdmrc | grep -v nolisten >> $out + ''; + }; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.kdm = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the KDE display manager. + ''; + }; + + enableXDMCP = mkOption { + default = false; + description = '' + Whether to enable XDMCP, which allows remote logins. + ''; + }; + + themeDirectory = mkOption { + default = ""; + description = '' + The path to a KDM theme directory. This theme + will be used by the KDM greeter. + ''; + }; + + setupScript = mkOption { + default = ""; + description = '' + The path to a KDM setup script. This script is run as root just + before KDM starts. Can be used for setting up + monitors with xrandr, for example. + ''; + }; + + extraConfig = mkOption { + default = ""; + description = '' + Options appended to <filename>kdmrc</filename>, the + configuration file of KDM. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.displayManager.slim.enable = false; + + services.xserver.displayManager.job = + { execCmd = + '' + mkdir -m 0755 -p /var/lib/kdm + chown kdm /var/lib/kdm + ${(optionalString (config.system.boot.loader.id == "grub" && config.system.build.grub != null) "PATH=${config.system.build.grub}/sbin:$PATH ") + + "KDEDIRS=/run/current-system/sw exec ${kdebase_workspace}/bin/kdm -config ${kdmrc} -nodaemon"} + ''; + logsXsession = true; + }; + + security.pam.services = [ { name = "kde"; allowNullPassword = true; startSession = true; } ]; + + users.extraUsers = singleton + { name = "kdm"; + uid = config.ids.uids.kdm; + description = "KDM user"; + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix new file mode 100644 index 0000000000000..c2b90d239eaab --- /dev/null +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -0,0 +1,119 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + xEnv = config.systemd.services."display-manager".environment; + cfg = dmcfg.lightdm; + + inherit (pkgs) stdenv lightdm writeScript writeText; + + # lightdm runs with clearenv(), but we need a few things in the enviornment for X to startup + xserverWrapper = writeScript "xserver-wrapper" + '' + #! /bin/sh + ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} + exec ${dmcfg.xserverBin} ${dmcfg.xserverArgs} + ''; + + # The default greeter provided with this expression is the GTK greeter. + # Again, we need a few things in the environment for the greeter to run with + # fonts/icons. + wrappedGtkGreeter = stdenv.mkDerivation { + name = "lightdm-gtk-greeter"; + buildInputs = [ pkgs.makeWrapper ]; + + buildCommand = '' + ensureDir $out/gtk-3.0/ + + # This wrapper ensures that we actually get fonts + makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \ + $out/greeter \ + --set XDG_DATA_DIRS ${pkgs.gnome2.gnome_icon_theme}/share \ + --set FONTCONFIG_FILE /etc/fonts/fonts.conf \ + --set XDG_CONFIG_HOME $out/ + + # We need this to ensure that it actually tries to find icons from gnome-icon-theme + cat - > $out/gtk-3.0/settings.ini << EOF + [Settings] + gtk-icon-theme-name=gnome + EOF + + cat - > $out/lightdm-gtk-greeter.desktop << EOF + [Desktop Entry] + Name=LightDM Greeter + Comment=This runs the LightDM Greeter + Exec=$out/greeter + Type=Application + EOF + ''; + }; + + lightdmConf = writeText "lightdm.conf" + '' + [LightDM] + greeter-user = ${config.users.extraUsers.lightdm.name} + xgreeters-directory = ${cfg.greeter.package} + xsessions-directory = ${dmcfg.session.desktops} + + [SeatDefaults] + xserver-command = ${xserverWrapper} + session-wrapper = ${dmcfg.session.script} + greeter-session = ${cfg.greeter.name} + ''; + +in +{ + options = { + services.xserver.displayManager.lightdm = { + enable = mkOption { + default = false; + description = '' + Whether to enable lightdm as the display manager. + ''; + }; + + greeter = mkOption { + description = '' + The LightDM greeter to login via. The package should be a directory + containing a .desktop file matching the name in the 'name' option. + ''; + default = { + name = "lightdm-gtk-greeter"; + package = wrappedGtkGreeter; + }; + }; + }; + }; + + config = mkIf cfg.enable { + services.xserver.displayManager.job = { + logsXsession = true; + + # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH + execCmd = '' + export PATH=${lightdm}/sbin:$PATH + ${lightdm}/sbin/lightdm --log-dir=/var/log --run-dir=/run --config=${lightdmConf} + ''; + }; + + services.dbus.enable = true; + services.dbus.packages = [ lightdm ]; + + security.pam.services = [ + { name = "lightdm"; allowNullPassword = true; startSession = true; } + { name = "lightdm-greeter"; allowNullPassword = true; startSession = true; } + ]; + + users.extraUsers.lightdm = { + createHome = true; + home = "/var/lib/lightdm"; + group = "lightdm"; + uid = config.ids.uids.lightdm; + }; + + users.extraGroups.lightdm.gid = config.ids.gids.lightdm; + }; +} diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix new file mode 100644 index 0000000000000..9e8b9391f45f2 --- /dev/null +++ b/nixos/modules/services/x11/display-managers/slim.nix @@ -0,0 +1,113 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + cfg = dmcfg.slim; + + slimConfig = pkgs.writeText "slim.cfg" + '' + xauth_path ${dmcfg.xauthBin} + default_xserver ${dmcfg.xserverBin} + xserver_arguments ${dmcfg.xserverArgs} + sessions ${pkgs.lib.concatStringsSep "," (dmcfg.session.names ++ ["custom"])} + login_cmd exec ${pkgs.stdenv.shell} ${dmcfg.session.script} "%session" + halt_cmd ${config.systemd.package}/sbin/shutdown -h now + reboot_cmd ${config.systemd.package}/sbin/shutdown -r now + ${optionalString (cfg.defaultUser != "") ("default_user " + cfg.defaultUser)} + ${optionalString cfg.autoLogin "auto_login yes"} + ''; + + # Unpack the SLiM theme, or use the default. + slimThemesDir = + let + unpackedTheme = pkgs.stdenv.mkDerivation { + name = "slim-theme"; + buildCommand = '' + ensureDir $out + cd $out + unpackFile ${cfg.theme} + ln -s * default + ''; + }; + in if cfg.theme == null then "${pkgs.slim}/share/slim/themes" else unpackedTheme; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.slim = { + + enable = mkOption { + default = true; + description = '' + Whether to enable SLiM as the display manager. + ''; + }; + + theme = mkOption { + default = null; + example = pkgs.fetchurl { + url = http://download.berlios.de/slim/slim-wave.tar.gz; + sha256 = "0ndr419i5myzcylvxb89m9grl2xyq6fbnyc3lkd711mzlmnnfxdy"; + }; + description = '' + The theme for the SLiM login manager. If not specified, SLiM's + default theme is used. See <link + xlink:href='http://slim.berlios.de/themes01.php'/> for a + collection of themes. + ''; + }; + + defaultUser = mkOption { + default = ""; + example = "login"; + description = '' + The default user to load. If you put a username here you + get it automatically loaded into the username field, and + the focus is placed on the password. + ''; + }; + + autoLogin = mkOption { + default = false; + example = true; + description = '' + Automatically log in as the default user. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.displayManager.job = + { preStart = + '' + rm -f /var/log/slim.log + ''; + environment = + { SLIM_CFGFILE = slimConfig; + SLIM_THEMESDIR = slimThemesDir; + }; + execCmd = "exec ${pkgs.slim}/bin/slim"; + }; + + # Allow null passwords so that the user can login as root on the + # installation CD. + security.pam.services = [ { name = "slim"; allowNullPassword = true; startSession = true; } ]; + + }; + +} |