fix(console): make a failed Steam session diagnosable, add shortcut tooling
Autologin into the gamescope Steam session does not take on the real hardware; the television lands on ReGreet instead. The config side is correct -- initial_session is present in the generated greetd.toml and services.greetd.restart evaluates to false -- so the likely cause is the session starting and then dying, which greetd answers by falling through to default_session. greetd hands a session the VT for its standard streams, so whatever the session prints on its way down is erased as soon as the greeter repaints. Run the launcher under systemd-cat so the reason survives in the journal under the steam-session identifier. Steam's non-Steam-game Browse dialog and its library-folder picker both go through the XDG portal FileChooser interface and do not open here (ValveSoftware/steam-for-linux#9447, #10415). Add steamtinkerlaunch, which writes shortcuts.vdf without the dialog, and document library_folder_add as the equivalent route for the library folder. Docs also catch up with the host's actual state: hardware-configuration .nix is a real scan now, standalone pcsx2 is installed, and the untested claims become the list of open problems. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
59d5d70221
commit
4e3347cb8c
+100
-32
@@ -9,17 +9,12 @@ A 4th-generation Core i7 (Haswell) on a UEFI board with an NVIDIA GeForce GTX
|
|||||||
is driven from the sofa with a Bluetooth controller; keyboard and mouse are
|
is driven from the sofa with a Bluetooth controller; keyboard and mouse are
|
||||||
supported but secondary.
|
supported but secondary.
|
||||||
|
|
||||||
## Not installed yet
|
## Disk
|
||||||
|
|
||||||
`hardware-configuration.nix` in this host directory is a **placeholder**, not a
|
`hardware-configuration.nix` is a real `nixos-generate-config` scan from the
|
||||||
hardware scan. It exists so the flake evaluates in CI and assumes the install
|
installed machine: GPT with a vfat ESP at `/boot` and an ext4 root, both
|
||||||
labels its partitions `nixos` (root, ext4) and `BOOT` (ESP, vfat). Replace the
|
addressed by UUID, and no swap device. Nothing else in the host config depends
|
||||||
whole file with the output of `nixos-generate-config` run on the machine and
|
on the disk layout.
|
||||||
commit that. If the labels do not match, the boot fails on a missing device
|
|
||||||
rather than touching the wrong disk.
|
|
||||||
|
|
||||||
Partition the disk GPT with an ESP (vfat, 512 MB is comfortable). Nothing else
|
|
||||||
in the host config depends on the disk layout.
|
|
||||||
|
|
||||||
## Bootloader
|
## Bootloader
|
||||||
|
|
||||||
@@ -88,7 +83,7 @@ to ReGreet, where the ordinary Sway session is available for everything else.
|
|||||||
`services.greetd.restart` defaults to `false` once `initial_session` is set,
|
`services.greetd.restart` defaults to `false` once `initial_session` is set,
|
||||||
which is what stops a logout looping straight back into autologin.
|
which is what stops a logout looping straight back into autologin.
|
||||||
|
|
||||||
Two details worth knowing:
|
Three details worth knowing:
|
||||||
|
|
||||||
- The launcher is referenced as `/run/current-system/sw/bin/steam-gamescope`.
|
- The launcher is referenced as `/run/current-system/sw/bin/steam-gamescope`.
|
||||||
The steam module builds that script privately and only adds it to
|
The steam module builds that script privately and only adds it to
|
||||||
@@ -96,17 +91,73 @@ Two details worth knowing:
|
|||||||
- `programs.gamescope.capSysNice = true` installs gamescope as a setcap wrapper
|
- `programs.gamescope.capSysNice = true` installs gamescope as a setcap wrapper
|
||||||
in `/run/wrappers/bin` instead of the system profile. That path precedes the
|
in `/run/wrappers/bin` instead of the system profile. That path precedes the
|
||||||
system profile on `PATH`, so `steam-gamescope` still resolves it.
|
system profile on `PATH`, so `steam-gamescope` still resolves it.
|
||||||
|
- greetd gives the session the VT for its standard streams, so anything the
|
||||||
|
Steam session prints as it dies is erased the moment the greeter repaints.
|
||||||
|
`initial_session` therefore runs the launcher under `systemd-cat`, and the
|
||||||
|
output is readable after the fact with `journalctl -b -t steam-session`.
|
||||||
|
|
||||||
|
### When the television lands on ReGreet instead of Steam
|
||||||
|
|
||||||
|
greetd starts `initial_session` **once per boot** — the check is the presence of
|
||||||
|
`/run/greetd.run` — and if the session process starts and then exits, greetd
|
||||||
|
falls through to `default_session`, i.e. ReGreet. A gamescope that dies on
|
||||||
|
startup is therefore indistinguishable from autologin never having run, unless
|
||||||
|
the logs are read:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
journalctl -b -t steam-session # what the session itself said
|
||||||
|
journalctl -b -u greetd # whether greetd started it at all
|
||||||
|
ls -l /run/greetd.run # exists => greetd has already had its one go
|
||||||
|
```
|
||||||
|
|
||||||
|
If greetd never even reaches the session, it prints `unable to start greeter`
|
||||||
|
and **exits** — there is no greeter to fall back to and the screen stays blank.
|
||||||
|
Recover over SSH (`modules/ssh.nix`), or hold space at power-on and boot the
|
||||||
|
previous generation.
|
||||||
|
|
||||||
|
To reproduce a session failure by hand, switch to a free VT and run
|
||||||
|
`steam-gamescope` there. Running it from inside Sway is not the same test:
|
||||||
|
gamescope picks its nested Wayland backend when `WAYLAND_DISPLAY` is set, and it
|
||||||
|
is the DRM backend — the one the boot session uses — that is in question.
|
||||||
|
|
||||||
The greeter is **Dvorak**, like every other host here (`modules/sway.nix` forces
|
The greeter is **Dvorak**, like every other host here (`modules/sway.nix` forces
|
||||||
`XKB_DEFAULT_VARIANT=dvorak` on cage). Only relevant if someone else has to type
|
`XKB_DEFAULT_VARIANT=dvorak` on cage). Only relevant if someone else has to type
|
||||||
a password.
|
a password.
|
||||||
|
|
||||||
### Adding RetroArch and Clone Hero to Big Picture
|
### Adding RetroArch, PCSX2 and Clone Hero to Big Picture
|
||||||
|
|
||||||
Both are installed system-wide but are not Steam titles. Add each once, from a
|
All three are installed system-wide but are not Steam titles. Added as Steam
|
||||||
Sway session, via Steam's **Games → Add a Non-Steam Game**; they then appear in
|
shortcuts they appear in Big Picture and inherit Steam Input, so the controller
|
||||||
Big Picture and inherit Steam Input, so the controller works in them without
|
works in them without further configuration.
|
||||||
further configuration.
|
|
||||||
|
Steam's own **Games → Add a Non-Steam Game** is the documented route and is also
|
||||||
|
the one that tends not to work. Both that dialog's **Browse** button and the
|
||||||
|
library-folder picker below go through the XDG desktop portal `FileChooser`
|
||||||
|
interface; when the portal is unreachable the client silently falls back to a
|
||||||
|
legacy chooser that is blank or inert — Valve
|
||||||
|
[#9447](https://github.com/ValveSoftware/steam-for-linux/issues/9447) and
|
||||||
|
[#10415](https://github.com/ValveSoftware/steam-for-linux/issues/10415), neither
|
||||||
|
fixed. Check the portal side before blaming the client:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
busctl --user introspect org.freedesktop.portal.Desktop \
|
||||||
|
/org/freedesktop/portal/desktop | grep FileChooser
|
||||||
|
```
|
||||||
|
|
||||||
|
`modules/sway.nix` enables `xdg-desktop-portal-gtk`, which is the backend that
|
||||||
|
implements `FileChooser` (`xdg-desktop-portal-wlr` implements only screenshot
|
||||||
|
and screencast), and the generated `sway-portals.conf` routes everything but
|
||||||
|
those two to `gtk`. If the interface is missing from the introspection above,
|
||||||
|
the backend is not running and that is the fault to chase.
|
||||||
|
|
||||||
|
Independent of the dialog, `steamtinkerlaunch` writes `shortcuts.vdf` directly:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Steam must be closed -- it rewrites shortcuts.vdf on exit.
|
||||||
|
steamtinkerlaunch addnonsteamgame -an="RetroArch" -ep="$(command -v retroarch)"
|
||||||
|
steamtinkerlaunch addnonsteamgame -an="PCSX2" -ep="$(command -v pcsx2-qt)"
|
||||||
|
steamtinkerlaunch addnonsteamgame -an="Clone Hero" -ep="$(command -v clonehero)"
|
||||||
|
```
|
||||||
|
|
||||||
## Emulation — RetroArch
|
## Emulation — RetroArch
|
||||||
|
|
||||||
@@ -167,13 +218,12 @@ system directory on this host:
|
|||||||
Be honest about the two heaviest cores. `dolphin` and `pcsx2` are libretro ports
|
Be honest about the two heaviest cores. `dolphin` and `pcsx2` are libretro ports
|
||||||
of emulators whose upstream effort goes into their **standalone** builds; the
|
of emulators whose upstream effort goes into their **standalone** builds; the
|
||||||
cores lag on compatibility and are the first place to look when a GameCube, Wii
|
cores lag on compatibility and are the first place to look when a GameCube, Wii
|
||||||
or PS2 title misbehaves. If a game does not cooperate, add the standalone
|
or PS2 title misbehaves.
|
||||||
emulators to `environment.systemPackages` in `gaming.nix`:
|
|
||||||
|
|
||||||
```nix
|
That has already happened for PS2: the LRPS2 core was not good enough in
|
||||||
pkgs.dolphin-emu # GameCube / Wii
|
practice, so **standalone `pkgs.pcsx2` is installed** in `gaming.nix` alongside
|
||||||
pkgs.pcsx2 # PlayStation 2
|
the core and is what PS2 titles should be run through. `pkgs.dolphin-emu` is not
|
||||||
```
|
installed; add it the same way if GameCube or Wii turns out to need it.
|
||||||
|
|
||||||
Both are controller-driven and can be added to Big Picture the same way as
|
Both are controller-driven and can be added to Big Picture the same way as
|
||||||
RetroArch. The hardware is not the limit here — a GTX 1070 and a Haswell i7 run
|
RetroArch. The hardware is not the limit here — a GTX 1070 and a Haswell i7 run
|
||||||
@@ -226,7 +276,19 @@ RetroArch is pointed at these paths declaratively. The other two have to be told
|
|||||||
once, in their own UIs:
|
once, in their own UIs:
|
||||||
|
|
||||||
- **Steam** — Settings → Storage → the `+` control → add `/srv/games/steam` as a
|
- **Steam** — Settings → Storage → the `+` control → add `/srv/games/steam` as a
|
||||||
library folder. Games installed there survive a reinstall of the OS.
|
library folder. Games installed there survive a reinstall of the OS. That
|
||||||
|
picker is the broken one described under
|
||||||
|
[Adding RetroArch, PCSX2 and Clone Hero to Big Picture](#adding-retroarch-pcsx2-and-clone-hero-to-big-picture);
|
||||||
|
when it comes up blank, use Steam's own console instead — open Steam with
|
||||||
|
`steam -console`, pick the **CONSOLE** tab and run:
|
||||||
|
|
||||||
|
```
|
||||||
|
library_folder_add /srv/games/steam
|
||||||
|
```
|
||||||
|
|
||||||
|
The directory must already exist and be writable by the user Steam runs as,
|
||||||
|
which `systemd.tmpfiles` guarantees. The command does not create it.
|
||||||
|
|
||||||
- **Clone Hero** — set the song library path to `/srv/games/clonehero/songs` from
|
- **Clone Hero** — set the song library path to `/srv/games/clonehero/songs` from
|
||||||
its settings screen. Clone Hero keeps its own config in `~/.clonehero`.
|
its settings screen. Clone Hero keeps its own config in `~/.clonehero`.
|
||||||
|
|
||||||
@@ -311,17 +373,23 @@ wired 360 pads — as well as `mt76x2u`, and pulls in proprietary dongle firmwar
|
|||||||
Not worth the side effects unless that dongle is actually in use, and if it ever
|
Not worth the side effects unless that dongle is actually in use, and if it ever
|
||||||
is, the 360 pads have to be re-tested.
|
is, the 360 pads have to be re-tested.
|
||||||
|
|
||||||
## Untested claims
|
## Open problems
|
||||||
|
|
||||||
This host has not been built or booted yet. Two things are worth watching on
|
The machine is installed and Sway works. Still outstanding:
|
||||||
first boot:
|
|
||||||
|
|
||||||
- **gamescope on the proprietary NVIDIA driver.** `gaming.nix` sets
|
- **Autologin into Steam does not happen** — the television comes up on ReGreet.
|
||||||
`GBM_BACKEND=nvidia-drm` and `__GLX_VENDOR_LIBRARY_NAME=nvidia` for the
|
Not yet root-caused; the config side is correct (`initial_session` is present
|
||||||
session, which is the standard fix, but the combination has a history of
|
in the generated `greetd.toml` and `services.greetd.restart` evaluates to
|
||||||
needing tweaks. If the session dies at startup, switch the greeter back to
|
`false`), so the suspicion is that gamescope starts and dies on the
|
||||||
interactive by commenting out `services.greetd.settings.initial_session`, log
|
proprietary NVIDIA driver, which greetd treats as a finished session and
|
||||||
into Sway, and read `journalctl --user -b`.
|
answers by starting the greeter. `gaming.nix` sets `GBM_BACKEND=nvidia-drm`
|
||||||
|
and `__GLX_VENDOR_LIBRARY_NAME=nvidia`, the standard fix, but the combination
|
||||||
|
has a history of needing more. Read `journalctl -b -t steam-session` first —
|
||||||
|
see [When the television lands on ReGreet instead of Steam](#when-the-television-lands-on-regreet-instead-of-steam).
|
||||||
|
- **Steam's file pickers do not open** — both the non-Steam-game **Browse**
|
||||||
|
dialog and the library-folder picker. Upstream client bugs with usable
|
||||||
|
workarounds; see the two sections above.
|
||||||
|
- **Boot into Big Picture has not been exercised**, since autologin has not run.
|
||||||
- **Television resolution and refresh.** gamescope takes the output's native
|
- **Television resolution and refresh.** gamescope takes the output's native
|
||||||
mode by default. Add `gamescopeSession.args = [ "-W" "3840" "-H" "2160" "-r"
|
mode by default. Add `gamescopeSession.args = [ "-W" "3840" "-H" "2160" "-r"
|
||||||
"60" ]` if a specific mode is wanted.
|
"60" ]` if a specific mode is wanted.
|
||||||
|
|||||||
@@ -61,6 +61,14 @@ let
|
|||||||
"clonehero/backgrounds"
|
"clonehero/backgrounds"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# greetd gives a session the VT for stdio, so a failed Steam session leaves no
|
||||||
|
# evidence once the greeter takes the VT back. Log to the journal instead:
|
||||||
|
# `journalctl -b -t steam-session`.
|
||||||
|
steamSession = pkgs.writeShellScript "steam-session" ''
|
||||||
|
exec ${pkgs.systemd}/bin/systemd-cat --identifier=steam-session \
|
||||||
|
/run/current-system/sw/bin/steam-gamescope
|
||||||
|
'';
|
||||||
|
|
||||||
# RetroArch and the cores this machine is expected to run. The wrapper already
|
# RetroArch and the cores this machine is expected to run. The wrapper already
|
||||||
# points RetroArch at the packaged assets, core info and joypad autoconfig
|
# points RetroArch at the packaged assets, core info and joypad autoconfig
|
||||||
# profiles; `settings` here is merged on top of those.
|
# profiles; `settings` here is merged on top of those.
|
||||||
@@ -178,13 +186,11 @@ in
|
|||||||
# ask for it; Steam's Proton builds and most native titles do.
|
# ask for it; Steam's Proton builds and most native titles do.
|
||||||
programs.gamemode.enable = true;
|
programs.gamemode.enable = true;
|
||||||
|
|
||||||
# Autologin into the Steam session. The launcher is not exposed as a package
|
# Autologin into the Steam session. greetd's `restart` option defaults to
|
||||||
# by the steam module -- it is built inside it and added to
|
# false once initial_session is set, which is what stops a logout from looping
|
||||||
# environment.systemPackages -- so reference it through the system profile.
|
# straight back into autologin.
|
||||||
# greetd's `restart` option defaults to false once initial_session is set,
|
|
||||||
# which is what stops a logout from looping straight back into autologin.
|
|
||||||
services.greetd.settings.initial_session = {
|
services.greetd.settings.initial_session = {
|
||||||
command = "/run/current-system/sw/bin/steam-gamescope";
|
command = "${steamSession}";
|
||||||
user = tvUser;
|
user = tvUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -242,6 +248,10 @@ in
|
|||||||
pkgs.clonehero
|
pkgs.clonehero
|
||||||
pkgs.pcsx2
|
pkgs.pcsx2
|
||||||
pkgs.dualsensectl # DualSense LED/battery/mic control from the shell
|
pkgs.dualsensectl # DualSense LED/battery/mic control from the shell
|
||||||
|
# Writes shortcuts.vdf from the shell. Steam's own "Add a Non-Steam Game"
|
||||||
|
# dialog depends on a working portal file picker and frequently does not
|
||||||
|
# open; see docs/hosts/console.md.
|
||||||
|
pkgs.steamtinkerlaunch
|
||||||
pkgs.mangohud # FPS/frametime overlay; use `mangohud %command%` in Steam
|
pkgs.mangohud # FPS/frametime overlay; use `mangohud %command%` in Steam
|
||||||
pkgs.vulkan-tools # vulkaninfo, for checking the 32/64-bit ICDs Proton needs
|
pkgs.vulkan-tools # vulkaninfo, for checking the 32/64-bit ICDs Proton needs
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user