Installer: cleanup of restart-check, --clone and the uninstall changes

- uninstall: nix-installer's copy outside /nix is made and run as root
  (a user-writable copy run by sudo could be swapped); README uninstall
  paragraph shortened to one account of what happens when Nix stays.
- session.nix: the restart-check activation after steamFrameUserServices,
  so the latter's comment is above it again.
- install.sh: a duplicate `local` in port_listening; comments.
- docs/cleanup.md: the installer internals of --clone (how an existing
  clone is recognised, which git) and restart-check (what it compares,
  test overrides); README keeps the usage.
- README install paragraph: shorter list of the dashboard patches.
This commit is contained in:
Pierre Kisters committed 2026-10-01 18:18:54 +02:00
1 parent 59afc2f616
commit b852a1eb07
4 files changed
+44 -29

No files matched your search

+9 -11
View File
@@ -84,11 +84,10 @@ runs `home-manager switch`; what it sets up is listed under
[Set up by install.sh](#set-up-by-installsh). Everything works in the running [Set up by install.sh](#set-up-by-installsh). Everything works in the running
session right away, except two settings read only at a process start: the session right away, except two settings read only at a process start: the
[keyboard layout](docs/session.md#keyboard-layout) (next Steam session start) [keyboard layout](docs/session.md#keyboard-layout) (next Steam session start)
and the [SteamVR dashboard patches](docs/steamvr-debugger.md) (VR pet, the VR and the [SteamVR dashboard patches](docs/steamvr-debugger.md) (VR pet, VR
keyboard's suggestion strip, window curvature and the other patches of keyboard suggestions, window curvature, ...; next SteamVR start). If they
SteamVR's dashboard; next SteamVR start). If you use them, the installer ends are waiting, the installer ends with "Restart once": reboot once. Re-running
with "Restart once": reboot once. Re-running it just switches it just switches again (`--yes` answers every question). Afterwards edit
again (`--yes` answers every question). Afterwards edit
`~/nix-config/home.nix` and switch (see [Usage](#usage)). `~/nix-config/home.nix` and switch (see [Usage](#usage)).
Your own config in a git repository: `--clone <git-url>` clones it into Your own config in a git repository: `--clone <git-url>` clones it into
@@ -501,12 +500,11 @@ stops Home Manager's user services (reverting the UI patches), runs
`cleanup --all`, runs `home-manager uninstall`, then removes Nix and the `cleanup --all`, runs `home-manager uninstall`, then removes Nix and the
per-user Nix state (see [Set up by install.sh](#set-up-by-installsh)). If per-user Nix state (see [Set up by install.sh](#set-up-by-installsh)). If
SteamVR is running, its key is restored when SteamVR stops (the closing SteamVR is running, its key is restored when SteamVR stops (the closing
message says so). Programs started from the Nix store keep `/nix` busy: message says so). Nix can't be removed while programs started from the Nix
before removing Nix, `uninstall` lists them and waits until you close them store run: `uninstall` lists them and waits; close them or run it right
(with `--yes`, it stops instead); close them or run it right after a reboot. after a reboot. If Nix stays (in use, `--yes`, or its uninstaller failed),
If Nix's own uninstaller fails anyway, the rest still runs (the `~/.config/home-manager` link goes) except the rest still runs (the `~/.config/home-manager` link goes) except the
the per-user Nix state, and the closing message says to reboot and run per-user Nix state, and the closing message says to run `uninstall` again. Your configuration, `*.hm-backup-*` files, app data and
`uninstall` again. Your configuration, `*.hm-backup-*` files, app data and
Flatpaks stay. Flatpaks stay.
To drop steam-frame-nix from a Home Manager configuration you keep, first To drop steam-frame-nix from a Home Manager configuration you keep, first
+16 -1
View File
@@ -45,6 +45,21 @@ What `install.sh install` sets up is listed in the README under
desktop can't reach it with its own environment) and uses the installed desktop can't reach it with its own environment) and uses the installed
`home-manager` if there is one, else Home Manager's `master`. `home-manager` if there is one, else Home Manager's `master`.
`install --clone` takes SteamOS' `git`, else `nix run nixpkgs#git`. An
existing directory is reused only if it is the top of a clone whose
`origin` is the same repository: URLs are compared as lower-case
host/path without `.git` (so `git@host:o/r`, `ssh://git@host/o/r` and
`https://host/o/r.git` match), and with `--ref` it must be on that branch.
`restart-check` (run by the session module's activation after
`steamFrameUserServices`, and by `install` at its end) compares the
keyboard layout drop-in on `gamescope-session.service` with
`XKB_DEFAULT_*` in the environment of the first readable process in that
unit's cgroup (gamescope's own isn't readable), and, while SteamVR runs
with the debugger drop-in, looks for a listener on port 8087 in
`/proc/net/tcp*`. Tests use `STEAM_FRAME_NIX_PROC` and
`STEAM_FRAME_NIX_CGROUP` (section F of `modules/cleanup/check.nix`).
`uninstall` removes Nix with nix-installer, which fails when it can't `uninstall` removes Nix with nix-installer, which fails when it can't
unmount `/nix` (`systemctl stop nix.mount`). Before that it scans `/proc` unmount `/nix` (`systemctl stop nix.mount`). Before that it scans `/proc`
for processes using `/nix`: their `exe`, `cwd`, `root` or an `fd` links into for processes using `/nix`: their `exe`, `cwd`, `root` or an `fd` links into
@@ -56,6 +71,6 @@ the script itself, its subshells (descendants) and its process group (the
`uninstall` from another terminal. Nothing is killed: it asks to close them `uninstall` from another terminal. Nothing is killed: it asks to close them
and re-checks on Enter, or (`--yes`, no terminal) stops before Nix. A bash and re-checks on Enter, or (`--yes`, no terminal) stops before Nix. A bash
from the Nix store re-executes the script with `/usr/bin/bash` first, and from the Nix store re-executes the script with `/usr/bin/bash` first, and
nix-installer runs from a copy outside `/nix`. The check uses nix-installer runs from a root-owned copy in `/tmp`. The check uses
`STEAM_FRAME_NIX_PROC` as a fake `/proc` (section H of `STEAM_FRAME_NIX_PROC` as a fake `/proc` (section H of
`modules/cleanup/check.nix`). `modules/cleanup/check.nix`).
+13 -11
View File
@@ -234,17 +234,19 @@ install_nix() {
} }
uninstall_nix() { uninstall_nix() {
local rc=0 bin local rc=0 bin=
need_sudo need_sudo
ro_unlock ro_unlock
step "Uninstalling Nix" step "Uninstalling Nix"
# From a copy: the uninstaller running from /nix would keep /nix busy. # From a root-owned copy: the uninstaller running from /nix would keep
bin="$(mktemp)" # /nix busy.
if ! { cp "$NIX_INSTALLER_BIN" "$bin" && chmod +x "$bin" && "$bin" --version >/dev/null 2>&1; }; then if ! bin="$(sudo mktemp)" || ! sudo cp "$NIX_INSTALLER_BIN" "$bin" \
rm -f "$bin"; bin=$NIX_INSTALLER_BIN || ! sudo chmod 700 "$bin" || ! sudo "$bin" --version >/dev/null 2>&1; then
[[ -n $bin ]] && sudo rm -f "$bin"
bin=$NIX_INSTALLER_BIN
fi fi
sudo "$bin" uninstall --no-confirm || rc=$? sudo "$bin" uninstall --no-confirm || rc=$?
[[ $bin == "$NIX_INSTALLER_BIN" ]] || rm -f "$bin" [[ $bin == "$NIX_INSTALLER_BIN" ]] || sudo rm -f "$bin"
ro_relock ro_relock
return "$rc" return "$rc"
} }
@@ -1056,7 +1058,6 @@ session_xkb() { # LAYOUT|VARIANT
# Whether something listens on 127.0.0.1/::1/any :<port> (/proc/net/tcp*). # Whether something listens on 127.0.0.1/::1/any :<port> (/proc/net/tcp*).
port_listening() { # port port_listening() { # port
local hex
local hex f files=() local hex f files=()
printf -v hex '%04X' "$1" printf -v hex '%04X' "$1"
for f in "$SFN_PROC/net/tcp" "$SFN_PROC/net/tcp6"; do [[ -r $f ]] && files+=("$f"); done for f in "$SFN_PROC/net/tcp" "$SFN_PROC/net/tcp6"; do [[ -r $f ]] && files+=("$f"); done
@@ -1178,7 +1179,8 @@ nix_users() {
grep -ls '[[:space:]]/nix/' "$SFN_PROC"/[0-9]*/maps || true grep -ls '[[:space:]]/nix/' "$SFN_PROC"/[0-9]*/maps || true
} | while IFS= read -r p; do p=${p#"$SFN_PROC"/}; echo "${p%%/*}"; done | sort -un \ } | while IFS= read -r p; do p=${p#"$SFN_PROC"/}; echo "${p%%/*}"; done | sort -un \
| while read -r pid; do | while read -r pid; do
[[ $pid != "$self" ]] && { read -r name <"$SFN_PROC/$pid/comm"; } 2>/dev/null || continue [[ $pid != "$self" ]] || continue
{ read -r name <"$SFN_PROC/$pid/comm"; } 2>/dev/null || continue # exited
# argv[0]'s name says more than comm (often a thread name) # argv[0]'s name says more than comm (often a thread name)
argv0=''; { IFS= read -r -d '' argv0 <"$SFN_PROC/$pid/cmdline"; } 2>/dev/null || true argv0=''; { IFS= read -r -d '' argv0 <"$SFN_PROC/$pid/cmdline"; } 2>/dev/null || true
[[ ${argv0##*/} == '' || ${argv0##*/} == exe ]] || name=${argv0##*/} [[ ${argv0##*/} == '' || ${argv0##*/} == exe ]] || name=${argv0##*/}
@@ -1274,9 +1276,9 @@ cmd_uninstall() {
cmd_cleanup --all cmd_cleanup --all
remove_hm remove_hm
# A failed Nix uninstall (e.g. /nix still busy) must not skip the rest: # Nix still in use or a failed Nix uninstall must not skip the rest: Home
# Home Manager is gone by now, so its config link goes regardless; the # Manager is gone by now, so its config link goes regardless; the per-user
# per-user Nix files stay for a Nix that may still be there. # Nix files stay for the Nix that is still there.
local nix_failed='' local nix_failed=''
if (( ! keep_nix )); then if (( ! keep_nix )); then
if [[ -x $NIX_INSTALLER_BIN ]]; then if [[ -x $NIX_INSTALLER_BIN ]]; then
+6 -6
View File
@@ -98,12 +98,6 @@ in {
# In a subshell: the outer session's environment must not leak into # In a subshell: the outer session's environment must not leak into
# activation steps that run later. # activation steps that run later.
# Read-only; a warning, never a failed switch.
config.home.activation.steamFrameRestartCheck = lib.hm.dag.entryAfter [ "steamFrameUserServices" ] ''
STEAM_FRAME_NIX_RUNTIME_DIR=${lib.escapeShellArg cfg.runtimeDir} XDG_CONFIG_HOME=${lib.escapeShellArg config.xdg.configHome} \
${lib.getExe restartCheck} || true
'';
config.home.activation.steamFrameUserServices = lib.hm.dag.entryAfter [ "reloadSystemd" ] ('' config.home.activation.steamFrameUserServices = lib.hm.dag.entryAfter [ "reloadSystemd" ] (''
( (
export XDG_RUNTIME_DIR=${lib.escapeShellArg cfg.runtimeDir} DBUS_SESSION_BUS_ADDRESS=${lib.escapeShellArg cfg.bus} export XDG_RUNTIME_DIR=${lib.escapeShellArg cfg.runtimeDir} DBUS_SESSION_BUS_ADDRESS=${lib.escapeShellArg cfg.bus}
@@ -121,4 +115,10 @@ in {
'' + '' '' + ''
) )
''); '');
# Read-only; a warning, never a failed switch.
config.home.activation.steamFrameRestartCheck = lib.hm.dag.entryAfter [ "steamFrameUserServices" ] ''
STEAM_FRAME_NIX_RUNTIME_DIR=${lib.escapeShellArg cfg.runtimeDir} XDG_CONFIG_HOME=${lib.escapeShellArg config.xdg.configHome} \
${lib.getExe restartCheck} || true
'';
} }