nixpkgs-suyu/nixos/modules/services/x11/display-managers/sddm.nix
Eduard Bachmakov 45a6488f9c nixos/sddm + nixos/plasma5: switch PAM service to login.
GDM and LightDM are already using this approach. It also allows us to
enable Kwallet integration more globally without generating stray PAM
services.

The default configuration of login service includes both options sddm
was setting explicitly.
2023-02-21 22:48:09 +01:00

275 lines
8 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
xcfg = config.services.xserver;
dmcfg = xcfg.displayManager;
cfg = dmcfg.sddm;
xEnv = config.systemd.services.display-manager.environment;
sddm = pkgs.libsForQt5.sddm;
iniFmt = pkgs.formats.ini { };
xserverWrapper = pkgs.writeShellScript "xserver-wrapper" ''
${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)}
exec systemd-cat -t xserver-wrapper ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} "$@"
'';
Xsetup = pkgs.writeShellScript "Xsetup" ''
${cfg.setupScript}
${dmcfg.setupCommands}
'';
Xstop = pkgs.writeShellScript "Xstop" ''
${cfg.stopScript}
'';
defaultConfig = {
General = {
HaltCommand = "/run/current-system/systemd/bin/systemctl poweroff";
RebootCommand = "/run/current-system/systemd/bin/systemctl reboot";
Numlock = if cfg.autoNumlock then "on" else "none"; # on, off none
# Implementation is done via pkgs/applications/display-managers/sddm/sddm-default-session.patch
DefaultSession = optionalString (dmcfg.defaultSession != null) "${dmcfg.defaultSession}.desktop";
};
Theme = {
Current = cfg.theme;
ThemeDir = "/run/current-system/sw/share/sddm/themes";
FacesDir = "/run/current-system/sw/share/sddm/faces";
};
Users = {
MaximumUid = config.ids.uids.nixbld;
HideUsers = concatStringsSep "," dmcfg.hiddenUsers;
HideShells = "/run/current-system/sw/bin/nologin";
};
X11 = {
MinimumVT = if xcfg.tty != null then xcfg.tty else 7;
ServerPath = toString xserverWrapper;
XephyrPath = "${pkgs.xorg.xorgserver.out}/bin/Xephyr";
SessionCommand = toString dmcfg.sessionData.wrapper;
SessionDir = "${dmcfg.sessionData.desktops}/share/xsessions";
XauthPath = "${pkgs.xorg.xauth}/bin/xauth";
DisplayCommand = toString Xsetup;
DisplayStopCommand = toString Xstop;
EnableHiDPI = cfg.enableHidpi;
};
Wayland = {
EnableHiDPI = cfg.enableHidpi;
SessionDir = "${dmcfg.sessionData.desktops}/share/wayland-sessions";
};
} // lib.optionalAttrs dmcfg.autoLogin.enable {
Autologin = {
User = dmcfg.autoLogin.user;
Session = autoLoginSessionName;
Relogin = cfg.autoLogin.relogin;
};
};
cfgFile =
iniFmt.generate "sddm.conf" (lib.recursiveUpdate defaultConfig cfg.settings);
autoLoginSessionName =
"${dmcfg.sessionData.autologinSession}.desktop";
in
{
imports = [
(mkRemovedOptionModule
[ "services" "xserver" "displayManager" "sddm" "themes" ]
"Set the option `services.xserver.displayManager.sddm.package' instead.")
(mkRenamedOptionModule
[ "services" "xserver" "displayManager" "sddm" "autoLogin" "enable" ]
[ "services" "xserver" "displayManager" "autoLogin" "enable" ])
(mkRenamedOptionModule
[ "services" "xserver" "displayManager" "sddm" "autoLogin" "user" ]
[ "services" "xserver" "displayManager" "autoLogin" "user" ])
(mkRemovedOptionModule
[ "services" "xserver" "displayManager" "sddm" "extraConfig" ]
"Set the option `services.xserver.displayManager.sddm.settings' instead.")
];
options = {
services.xserver.displayManager.sddm = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to enable sddm as the display manager.
'';
};
enableHidpi = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
Whether to enable automatic HiDPI mode.
'';
};
settings = mkOption {
type = iniFmt.type;
default = { };
example = {
Autologin = {
User = "john";
Session = "plasma.desktop";
};
};
description = lib.mdDoc ''
Extra settings merged in and overwriting defaults in sddm.conf.
'';
};
theme = mkOption {
type = types.str;
default = "";
description = lib.mdDoc ''
Greeter theme to use.
'';
};
autoNumlock = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Enable numlock at login.
'';
};
setupScript = mkOption {
type = types.str;
default = "";
example = ''
# workaround for using NVIDIA Optimus without Bumblebee
xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto
'';
description = lib.mdDoc ''
A script to execute when starting the display server. DEPRECATED, please
use {option}`services.xserver.displayManager.setupCommands`.
'';
};
stopScript = mkOption {
type = types.str;
default = "";
description = lib.mdDoc ''
A script to execute when stopping the display server.
'';
};
# Configuration for automatic login specific to SDDM
autoLogin = {
relogin = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
If true automatic login will kick in again on session exit (logout), otherwise it
will only log in automatically when the display-manager is started.
'';
};
minimumUid = mkOption {
type = types.ints.u16;
default = 1000;
description = lib.mdDoc ''
Minimum user ID for auto-login user.
'';
};
};
};
};
config = mkIf cfg.enable {
assertions = [
{
assertion = xcfg.enable;
message = ''
SDDM requires services.xserver.enable to be true
'';
}
{
assertion = dmcfg.autoLogin.enable -> autoLoginSessionName != null;
message = ''
SDDM auto-login requires that services.xserver.displayManager.defaultSession is set.
'';
}
];
services.xserver.displayManager.job = {
environment = {
# Load themes from system environment
QT_PLUGIN_PATH = "/run/current-system/sw/" + pkgs.qt5.qtbase.qtPluginPrefix;
QML2_IMPORT_PATH = "/run/current-system/sw/" + pkgs.qt5.qtbase.qtQmlPrefix;
};
execCmd = "exec /run/current-system/sw/bin/sddm";
};
security.pam.services = {
sddm.text = ''
auth substack login
account include login
password substack login
session include login
'';
sddm-greeter.text = ''
auth required pam_succeed_if.so audit quiet_success user = sddm
auth optional pam_permit.so
account required pam_succeed_if.so audit quiet_success user = sddm
account sufficient pam_unix.so
password required pam_deny.so
session required pam_succeed_if.so audit quiet_success user = sddm
session required pam_env.so conffile=/etc/pam/environment readenv=0
session optional ${config.systemd.package}/lib/security/pam_systemd.so
session optional pam_keyinit.so force revoke
session optional pam_permit.so
'';
sddm-autologin.text = ''
auth requisite pam_nologin.so
auth required pam_succeed_if.so uid >= ${toString cfg.autoLogin.minimumUid} quiet
auth required pam_permit.so
account include sddm
password include sddm
session include sddm
'';
};
users.users.sddm = {
createHome = true;
home = "/var/lib/sddm";
group = "sddm";
uid = config.ids.uids.sddm;
};
environment.etc."sddm.conf".source = cfgFile;
environment.pathsToLink = [
"/share/sddm"
];
users.groups.sddm.gid = config.ids.gids.sddm;
environment.systemPackages = [ sddm ];
services.dbus.packages = [ sddm ];
# To enable user switching, allow sddm to allocate TTYs/displays dynamically.
services.xserver.tty = null;
services.xserver.display = null;
};
}