login: remove systemd pam integration (so it doesnt try, and fail, to start the user manager)

This commit is contained in:
Colin 2024-05-29 13:26:03 +00:00
parent d865be952a
commit d4dfcd6510
12 changed files with 124 additions and 57 deletions

View File

@ -23,11 +23,5 @@
# see <https://manpages.ubuntu.com/manpages/bionic/man5/user-dirs.conf.5.html>
sane.user.fs.".config/user-dirs.conf".symlink.text = "enabled=False";
sane.user.fs.".profile".symlink.text = ''
# configure XDG_<type>_DIR preferences (e.g. for downloads, screenshots, etc)
# surround with `set -o allexport` since user-dirs.dirs doesn't `export` its vars
set -a
source $HOME/.config/user-dirs.dirs
set +a
'';
sane.user.fs.".config/environment.d/30-user-dirs.conf".symlink.target = "../user-dirs.dirs";
}

View File

@ -81,6 +81,7 @@
# found on graphical hosts
sane.ids.nm-iodine.uid = 2101; # desko/moby/lappy
sane.ids.seat.gid = 2102;
# found on desko host
# from services.usbmuxd

View File

@ -87,7 +87,7 @@ let
in
{
sane.programs.bemenu = {
sandbox.method = "bwrap"; # landlock works, but requires *all* of /run/user/$ID to be granted.
sandbox.method = "bwrap"; # landlock works, but requires *all* of $XDG_RUNTIME_DIR to be granted.
sandbox.whitelistWayland = true;
sandbox.extraHomePaths = [
".cache/fontconfig" #< else it complains, and is *way* slower

View File

@ -141,7 +141,7 @@ in
# '';
# see: <https://docs.pipewire.org/page_module_protocol_native.html>
# defaults to placing the socket in /run/user/$id/{pipewire-0,pipewire-0-manager,...}
# defaults to placing the socket in $XDG_RUNTIME_DIR/{pipewire-0,pipewire-0-manager,...}
# but that's trickier to sandbox
env.PIPEWIRE_RUNTIME_DIR = "$XDG_RUNTIME_DIR/pipewire";

View File

@ -5,7 +5,7 @@
# - use as a launcher/file browser
# - `rofi -sidebar-mode`
# - separate tabs for filebrowser, drun, etc.
# - `rofi -pid /run/user/$UID/rofi.pid -replace`
# - `rofi -pid $XDG_RUNTIME_DIR/rofi.pid -replace`
# - single-instance mode
# - pid is probably optional, just need `-replace`.
#

View File

@ -1,11 +1,17 @@
{ config, ... }:
{ config, lib, ... }:
let
cfg = config.sane.programs.shadow;
in
{
sane.programs.shadow = {
sandbox.enable = false; #< `login` can't be sandboxed because it launches a user shell
};
services.getty.loginProgram = "${cfg.package}/bin/login";
config = lib.mkMerge [
{
sane.programs.shadow = {
sandbox.enable = false; #< `login` can't be sandboxed because it launches a user shell
};
}
(lib.mkIf cfg.enabled {
services.getty.loginProgram = "${cfg.package}/bin/login";
security.pam.services.login.startSession = lib.mkForce false; #< disable systemd integration
})
];
}

View File

@ -179,7 +179,8 @@ in
sandbox.extraRuntimePaths = [ "/" ]; # TODO: should need just "sway". but even if i sandbox EVERY entry under run individually, it fails!
sandbox.extraPaths = [
"/dev/input"
"/run/systemd/sessions"
"/run/seatd.sock" #< required if not using `logind` systemd login manager
"/run/systemd/sessions" #< TODO: remove
"/run/udev"
"/sys/class/backlight"
"/sys/class/drm"
@ -238,6 +239,11 @@ in
services.graphical-session.partOf = [ "default" ];
};
# TODO: sandbox seatd
# also consider any alternatives (ConsoleKit?).
# /run/seatd.sock location can be configured, but only via compile-time flag
services.seatd.enable = lib.mkIf cfg.enabled true;
# TODO: this can go elsewhere
hardware.bluetooth.enable = lib.mkIf cfg.enabled true;
services.blueman.enable = lib.mkIf cfg.enabled true;

View File

@ -89,29 +89,17 @@ in
"shadow" #< for login
];
fs.".profile".symlink.text = lib.mkMerge [
(lib.mkBefore ''
# setup primarySessionCommands here and let any other nix config populate it later
primarySessionCommands=()
initPrimarySession() {
for c in "''${primarySessionCommands[@]}"; do
eval "$c"
done
}
'')
# lib.mkAfter so that launching the DE happens *after* any other .profile setup.
(lib.mkAfter ''
fs.".profile".symlink.text = ''
unl0krCheck() {
# if already running a desktop environment, or if running from ssh, then `tty` will show /dev/pts/NN.
if [ "$(tty)" = "/dev/${tty}" ]; then
if (( ''${#primarySessionCommands[@]} )); then
echo "launching primary session commands in ${builtins.toString cfg.config.delay}s: ''${primarySessionCommands[*]}"
# if the `sleep` call here is `Ctrl+C'd`, then it'll exit false and the desktop isn't launched.
sleep ${builtins.toString cfg.config.delay} && \
initPrimarySession
fi
fi
'')
];
# if the `sleep` call is `Ctrl+C'd`, then it'll exit false and the session commands won't be launched
[ "$(tty)" = "/dev/${tty}" ] && (( ''${#primarySessionCommands[@]} )) \
&& echo "launching primary session commands in ${builtins.toString cfg.config.delay}s: ''${primarySessionCommands[*]}" \
&& sleep ${builtins.toString cfg.config.delay}
}
primarySessionChecks+=('unl0krCheck')
'';
# N.B.: this sandboxing applies to `unl0kr` itself -- the on-screen-keyboard;
# NOT to the wrapper which invokes `login`.

View File

@ -89,7 +89,7 @@ in
};
# also available: ${cfg.package}/libexec/xdg-document-portal
# - <https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Documents.html>
# - shares files from its namespace with programs inside a namespace, via a fuse mount at /run/user/$uid/doc
# - shares files from its namespace with programs inside a namespace, via a fuse mount at $XDG_RUNTIME_DIR/doc
};
# after #603 is resolved, i can probably stop linking `{gtk,wlr}.portal` into ~

View File

@ -21,6 +21,7 @@
"media" # servo
"networkmanager"
"nixbuild"
"seat" # for sway, if using seatd
"systemd-journal" # allows to view other user's journals (esp system users)
"transmission" # servo
"video" # mobile; for LEDs & maybe for camera?

View File

@ -190,12 +190,26 @@ let
# homeMode defaults to 700; notice: no leading 0
mode = "0" + nixConfig.users.users."${name}".homeMode;
};
# ~/.config/environment.d/*.conf is added to systemd user units.
# - format: lines of: `key=value`
# ~/.profile is added by *some* login shells.
# - format: lines of: `export key="value"`
# see: `man environment.d`
fs.".config/environment.d/10-sane-nixos-users.conf".symlink.text =
### normally a session manager (like systemd) would set these vars (at least) for me:
# - XDG_RUNTIME_DIR
# - XDG_SESSION_ID
# - XDG_SESSION_CLASS
# - XDG_SESSION_TYPE
# - XDG_VTNR
# - SYSTEMD_EXEC_PID
# some of my program-specific environment variables depend on some of these being set,
# hence do that early:
# TODO: consider moving XDG_RUNTIME_DIR to $HOME/.run
fs.".config/environment.d/10-sane-baseline.conf".symlink.text = ''
XDG_RUNTIME_DIR=/run/user/${name}
'';
fs.".config/environment.d/20-sane-nixos-users.conf".symlink.text =
let
env = lib.mapAttrsToList
(key: value: ''${key}=${value}'')
@ -203,15 +217,63 @@ let
;
in
lib.concatStringsSep "\n" env + "\n";
fs.".profile".symlink.text = ''
# source env vars and the like, as systemd would. `man environment.d`
for env in ~/.config/environment.d/*.conf; do
# surround with `set -o allexport` since environment.d doesn't explicitly `export` their vars
set -a
source "$env"
set +a
done
'';
fs.".profile".symlink.text = lib.mkMerge [
(lib.mkBefore ''
# sessionCommands: ordered sequence of functions which will be called whenever this file is sourced.
# primarySessionCommands: additional functions which will be called only for the main session (i.e. login through GUI).
# GUIs are expected to install a function to `primarySessionChecks` which returns true
# if primary session initialization is desired (e.g. if this was sourced from a greeter).
sessionCommands=()
primarySessionCommands=()
primarySessionChecks=()
runCommands() {
for c in "$@"; do
eval "$c"
done
}
initSession() {
runCommands "''${sessionCommands[@]}"
}
maybeInitPrimarySession() {
for c in "''${primarySessionChecks[@]}"; do
if eval "$c"; then
runCommands "''${primarySessionCommands[@]}"
return
fi
done
}
setVTNR() {
# some desktops (e.g. sway) need to know which virtual TTY to render to
if [ -v "$XDG_VTNR" ]; then
return
fi
local ttyPath=$(tty)
case $ttyPath in
(/dev/tty*)
export XDG_VTNR=''${ttyPath#/dev/tty}
;;
esac
}
sessionCommands+=('setVTNR')
sourceEnv() {
# source env vars and the like, as systemd would. `man environment.d`
for env in ~/.config/environment.d/*.conf; do
# surround with `set -o allexport` since environment.d doesn't explicitly `export` their vars
set -a
source "$env"
set +a
done
}
sessionCommands+=('sourceEnv')
'')
(lib.mkAfter ''
sessionCommands+=('maybeInitPrimarySession')
initSession
'')
];
services."default" = {
description = "service (bundle) which is started by default upon login";
@ -227,7 +289,7 @@ let
}
];
});
processUser = user: defn:
processUser = name: defn:
let
prefixWithHome = lib.mapAttrs' (path: value: {
name = path-lib.concat [ defn.home path ];
@ -239,8 +301,17 @@ let
}]));
in
{
sane.fs = makeWanted (prefixWithHome defn.fs);
sane.defaultUser = lib.mkIf defn.default user;
sane.fs = makeWanted ({
"/run/user/${name}" = [{
dir.acl = {
user = lib.mkDefault name;
group = lib.mkDefault config.users.users."${name}".group;
# homeMode defaults to 700; notice: no leading 0
mode = "0" + config.users.users."${name}".homeMode;
};
}];
} // prefixWithHome defn.fs);
sane.defaultUser = lib.mkIf defn.default name;
# `byPath` is the actual output here, computed from the other keys.
sane.persist.sys.byPath = prefixWithHome defn.persist.byPath;

View File

@ -204,7 +204,7 @@ let
# to decrease sandbox escaping, i want to run s6-svscan on a read-only directory
# so other programs can't edit the service scripts.
# in practice, that means putting the servicedirs in /nix/store, and linking selective pieces of state
# towards /run/user/{uid}/s6/live/..., the latter is shared with s6-rc.
# towards $XDG_RUNTIME_DIR/s6/live/..., the latter is shared with s6-rc.
mkScanDir = livedir: compiled: pkgs.runCommandLocal "s6-scandir" { } ''
cp -R "${compiled}/servicedirs" "$out"
cd "$out"
@ -287,7 +287,7 @@ let
services
;
# create a template s6 "live" dir, which can be copied at runtime in /run/user/{uid}/s6/live.
# create a template s6 "live" dir, which can be copied at runtime in $XDG_RUNTIME_DIR/s6/live.
# this is like a minimal versio of `s6-rc-init`, but tightly coupled to my setup
# wherein the scandir is external and selectively links back to the livedir
mkLiveDir = compiled: pkgs.runCommandLocal "s6-livedir" {} ''
@ -322,8 +322,8 @@ in
)
);
compiled = compileServices sources;
uid = config'.users.users."${name}".uid;
scanDir = mkScanDir "/run/user/${builtins.toString uid}/s6/live" compiled;
xdg_runtime_dir = "/run/user/${name}";
scanDir = mkScanDir "${xdg_runtime_dir}/s6/live" compiled;
liveDir = mkLiveDir compiled;
in {
fs.".config/s6/live".symlink.target = liveDir;