Options
All options live under steamix.*. Anything not listed here is configured
through upstream nixpkgs options (programs.steam.*, programs.gamescope.*).
This page is the curated tour; the option reference is the complete listing, generated from the module so it cannot drift.
Every package Steamix installs has a package option (steamix.heroic.package,
steamix.losslessScaling.package, steamix.library.boilr.package, …), so
any of them can come from another nixpkgs, an overlay or an override. Steam
and gamescope themselves are set through the upstream
programs.steam.package and programs.gamescope.package. For example, lsfg-vk
2.x on a NixOS 26.05 machine:
steamix.losslessScaling = {
package = unstable.lsfg-vk; # `unstable` being a nixos-unstable package set
ui.package = unstable.lsfg-vk-ui; # same major version as the layer
};
Core
steamix.enable
Type bool, default false. Master switch. Enables programs.steam and
programs.gamescope, and registers this module’s own Gaming Mode session.
It also sets programs.steam.gamescopeSession.enable = false — nixpkgs’
session and this one both register steam.desktop, and this one is a superset
(see How it works).
steamix.user
Type null or str, default null. The user the Gaming Mode session runs as.
Required when autoStart is on — that user is logged in without a password
prompt.
steamix.autoStart
Type bool, default true. Boot straight into Gaming Mode by owning the
login path with a greetd session loop. Cannot be combined with a regular
display manager (greetd aliases display-manager.service), so turn off the
one your desktop configuration enables, for example
services.displayManager.gdm.enable = false.
With autoStart = false the module only registers the “Steam” session: pick
it from your own display manager’s session chooser; session switching (which
relies on the loop) is not available.
steamix.desktopSession
Type null or str, default null, example "gnome". The Wayland session
started by “Switch to Desktop” — a name from
services.displayManager.sessionData.sessionNames (the basename of a
wayland-sessions/*.desktop file). An unknown name is an eval-time error
listing the valid ones; null keeps you in Gaming Mode (with a warning).
The session itself must be enabled through your normal configuration
(services.desktopManager.gnome.enable, plasma6.enable, …) — this option
only selects it.
steamix.steamArgs
Type list of str, default
[ "-gamepadui" "-steamos3" "-steampal" "-steamdeck" "-pipewire-dmabuf" ].
Arguments Steam is launched with inside Gaming Mode — the set Valve’s own
steam-launcher uses, plus -pipewire-dmabuf for Remote Play.
Leave -steamos3 in place: it is what ties Steam into gamescope’s focus
handling and puts “Switch to Desktop” in the power menu.
Display features
Each of these does two things: passes the gamescope flag, and sets the
STEAM_GAMESCOPE_* variable that makes the matching toggle appear in Gaming
Mode’s settings. Steam reads those once at startup and simply believes them,
so they are tied to the flag rather than exposed separately.
| Option | Default | gamescope flag | Steam capability |
|---|---|---|---|
steamix.hdr.enable | true | --hdr-enabled | STEAM_GAMESCOPE_HDR_SUPPORTED |
steamix.vrr.enable | true | --adaptive-sync | STEAM_GAMESCOPE_VRR_SUPPORTED |
steamix.tearing.enable | false | --immediate-flips | STEAM_GAMESCOPE_TEARING_SUPPORTED |
steamix.mangoapp.enable | true | --mangoapp | STEAM_USE_MANGOAPP |
- HDR is safe to leave on for SDR displays — gamescope only drives HDR when the connected output advertises it. It needs the WSI layer below for games to hand HDR swapchains through; without it, HDR content is tonemapped to SDR. Turn it on per game in Gaming Mode’s display settings.
- VRR is likewise ignored when the output does not support FreeSync.
- Tearing is off by default: it trades visible tearing for latency, and VRR is the better answer on displays that have it.
- mangoapp is what backs Steam’s built-in “Performance Overlay” levels; it is not the same thing as running MangoHud on a game yourself.
steamix.mangoapp.fontScale
Type null or float/int, default null. Multiplier for the performance
overlay’s size — MangoHud’s font_scale, which scales the panel as well as the
text.
MangoHud draws the overlay at a fixed size chosen for the Steam Deck’s
1280x800 panel, so it shrinks to an unreadable speck on a big television. The
default scales it automatically against the tallest connected output (about
1.8x at 1440p, 2.7x at 2160p), which keeps it roughly Deck-sized. Set a number
to pin it, or 1 for MangoHud’s own sizing.
The sizing is applied through MANGOHUD_PRESETSFILE — the module defines all
five overlay levels itself and bakes the scale into them — because the two
obvious routes both fail: Steam rewrites the config file on every level
change, and MANGOHUD_CONFIG makes MangoHud apply the preset twice, drawing
every element double. Levels 2–4 additionally get a narrower scale than
level 1 where needed, computed so the widest table row still fits the display;
at full scale on a 4K screen the dense levels would run off both edges.
steamix.mangoapp.pciDev
Type null or str, default null, example "0000:03:00.0". PCI address of
the GPU the overlay reports on (MangoHud’s pci_dev, written as lspci -D
prints it).
Only meaningful on a machine with more than one GPU: MangoHud enumerates every
GPU and picks one itself, which need not be the one gamescope renders with — a
desktop with an idle iGPU can get an overlay reporting that chip’s load while
the games run on the discrete card. null leaves the choice to MangoHud.
steamix.mangoapp.package
The mangohud package that supplies mangoapp. It talks to gamescope over X
atoms and a message queue, so when programs.gamescope.package is overridden
to a much newer gamescope, override this to match.
steamix.mangoapp.backgroundAlpha
Type null or float/int, default 0.8. Opacity of the performance overlay’s
backdrop, from 0 (invisible) to 1 (solid). MangoHud defaults to 0.5,
which is legible on a monitor an arm’s length away and washes out into the game
from across a living room. null leaves MangoHud’s own default alone.
steamix.realtime.enable
Type bool, default false. Adds --rt and gives gamescope cap_sys_nice
through programs.gamescope.capSysNice, letting it renice itself for smoother
frame pacing.
Off by default because the capability puts gamescope in secure-execution mode,
where the loader ignores LD_LIBRARY_PATH/LD_PRELOAD — which has
historically broken launching it out of Steam’s FHS environment. Turn it on,
reboot, and confirm Gaming Mode still starts before keeping it.
gamescope
steamix.gamescope.args
Type list of str, default [ ]. Extra arguments appended to the gamescope
command line, after the ones derived from the options above. One list element
per argv entry:
steamix.gamescope.args = [
"--output-width"
"3840"
"--output-height"
"2160"
"--nested-refresh"
"120"
];
steamix.gamescope.env
Type attrs of str, default { }. Extra environment for the session,
exported last so it overrides the module’s own defaults.
steamix.gamescope.wsi.enable
Type bool, default true. Installs the gamescope WSI Vulkan layer
(VK_LAYER_FROG_gamescope_wsi) into hardware.graphics.extraPackages and
extraPackages32, and sets ENABLE_GAMESCOPE_WSI=1 for the session.
The layer is how games present through gamescope instead of through plain
Xwayland WSI; it carries frame pacing, the framerate limiter, and HDR
swapchains. Requires hardware.graphics.enable32Bit (asserted).
steamix.gamescope.wsi.package / .package32
Defaulting to pkgs.gamescope-wsi and pkgs.pkgsi686Linux.gamescope-wsi. The
layer speaks a versioned protocol to gamescope, so override these to keep it in
step with a non-default programs.gamescope.package:
# `newer` being a newer nixpkgs, for example an unstable input
programs.gamescope.package = newer.gamescope;
steamix.gamescope.wsi = {
package = newer.gamescope-wsi;
package32 = newer.pkgsi686Linux.gamescope-wsi;
};
steamix.binaryCache.enable
Type bool, default true. Downloads SteamOS Manager, Decky Loader and the
32-bit gamescope WSI layer from steamix.cachix.org instead of compiling
them, by adding the cache and its key to nix.settings next to
cache.nixos.org. No trust beyond what importing the module already asks
for: the module runs as root and the key is pinned. It helps only when the
machine’s nixpkgs matches a revision CI built against; see
Binary cache.
steamix.tweaks.enable
Type bool, default true. SteamOS’ opinionated system tuning, minus
everything specific to Valve’s hardware. Every setting below is a mkDefault,
so an individual one can be overridden without turning the group off.
| Setting | Why |
|---|---|
zramSwap — zstd, 50% of RAM, priority 100 | A console has no swap partition to fall back on, and shader compilation, Proton and a browser-based UI will happily use everything. |
services.earlyoom — 5% free memory and swap | Under pressure the kernel’s own OOM killer arrives long after the machine stopped responding, which on a controller-driven box means reaching for the power button. |
net.ipv4.tcp_mtu_probing = 1 | Some storefronts and matchmaking services sit behind PMTU black holes. |
net.ipv4.tcp_fin_timeout = 5 | A game killed and relaunched cannot rebind its port while the old socket lingers, and the default timeout is far longer than a relaunch takes. |
What else the module sets
Beyond the session itself:
| Setting | Why |
|---|---|
security.pam.loginLimits — hard nice of -8 for steamix.user | Proton runs some threads at negative niceness. Scoped to the account the session logs in as, not system-wide. |
A polkit rule for NetworkManager, when steamix.user is set and networking.networkmanager.enable is on | Gaming Mode’s Wi-Fi settings write system connections, which normally needs the networkmanager group — impossible to grant mid-setup with only a controller in hand. Scoped to that one user’s local, active session; Jovian grants it to everyone in users. |
Controller access is deliberately not handled here. programs.steam turns
on hardware.steam-hardware, which installs Valve’s steam-devices rules —
those already tag /dev/uinput for the active session and carry uaccess
rules for every controller Steam supports. A blanket
KERNEL=="hidraw*", TAG+="uaccess" would hand the session every HID device on
the machine, which is more than Valve grants on a Deck. If you have a pad that
Valve’s list misses, add a rule for that device.
steamix.heroic
Heroic Games Launcher for Epic, GOG and Amazon Prime Gaming libraries.
| Option | Type | Default | Purpose |
|---|---|---|---|
.enable | bool | false | Install Heroic. |
.package | package | pkgs.heroic | What to install. |
This installs Heroic as a normal application, so it is there in Desktop Mode. Gaming Mode only shows what is in Steam’s library: use Heroic’s own per-game “Add to Steam” action, or add Heroic itself as a non-Steam game. Adding library entries declaratively is on the roadmap.
nixpkgs’ heroic runs the launcher in an FHS environment with the libraries
its games and Wine builds expect; pkgs.heroic.override { extraPkgs = pkgs: [ ... ]; } adds more.
steamix.emulation
RetroArch with a set of libretro cores. It
does not need the rest of Steamix (steamix.enable): it also serves
machines Steam does not run on, such as a Raspberry Pi 4.
| Option | Type | Default | Purpose |
|---|---|---|---|
.enable | bool | false | Install RetroArch with the cores. |
.retroarch.package | package | pkgs.retroarch-bare | The frontend the cores and settings are wrapped around. |
.retroarch.cores | list of package | Nestopia, bsnes, mGBA, PCSX ReARMed | The cores, from pkgs.libretro. |
.retroarch.settings | attrs of string | { } | retroarch.cfg settings applied over the user’s own on every start. |
.retroarch.finalPackage | package | read-only | The RetroArch that is installed. |
.kiosk.enable | bool | false | Boot straight into RetroArch, full screen in cage, started again when it quits. Not together with Gaming Mode’s autoStart. |
.kiosk.user | null or string | steamix.user | Who RetroArch runs as in the kiosk. |
The default cores are free software and cover NES, SNES, Game Boy / Color / Advance and PlayStation. The fastest SNES and Mega Drive cores, Snes9x, Genesis Plus GX and PicoDrive, are unfree (non-commercial use only), so adding them needs unfree packages allowed; on small ARM boards they are the ones to use:
steamix.emulation.retroarch.cores = with pkgs.libretro; [
nestopia snes9x genesis-plus-gx mgba pcsx-rearmed
];
Games go in ~/ROMs, where RetroArch’s file browser starts. With Gaming
Mode, RetroArch is an application in Desktop Mode; add it as a non-Steam
game to reach it from Gaming Mode.
steamix.library.boilr
BoilR puts games from other launchers in Steam’s library, so Gaming Mode can start them: Heroic (Epic and GOG), Legendary, Lutris, itch.io, Bottles, Flatpaks, MiniGalaxy and more. It runs on every login, inside the Gaming Mode session right before Steam starts, because it needs Steam closed. A game installed in Desktop Mode appears the next time Gaming Mode starts.
| Option | Type | Default | Purpose |
|---|---|---|---|
.enable | bool | false | Sync on every login. |
.package | package | pkgs.boilr | What to run. |
.settings | TOML attrs | { } | BoilR’s configuration, written to ~/.config/boilr/config.toml on every login. |
.steamGridDbKeyFile | null or str | null | A file with a SteamGridDB API key, read at login, for artwork. |
.timeout | positive int | 120 | Seconds a sync may take before Steam starts anyway. |
steamix.library.boilr = {
enable = true;
steamGridDbKeyFile = "/run/secrets/steamgriddb"; # e.g. from sops-nix
settings.steam.create_collections = true;
};
Repeating the sync is safe: BoilR removes only the shortcuts it added itself, and shortcuts you added by hand stay. Heroic’s games launch through Heroic by default, which keeps Epic sign-in and cloud saves working.
settings is the source of truth. Anything left out keeps BoilR’s default,
which detects most launchers by itself; Steamix only sets
steam.optimize_for_big_picture = true and enables SteamGridDB when a key
file is given. Changes made in BoilR’s own window do not survive the next
login. The key never enters the Nix store: the config is written with a
placeholder and the key is filled in at login, into a file only the user can
read.
steamix.losslessScaling
Lossless Scaling’s frame generation for Steam’s games, through lsfg-vk, a Vulkan layer that runs it with the DLL from your own copy of Lossless Scaling.
You need Lossless Scaling installed from Steam. lsfg-vk 2.x additionally
needs its “lsfg-vk” beta branch: in Steam, Lossless Scaling > Properties >
Game Versions & Betas. lsfg-vk finds the DLL in the usual Steam libraries;
dll points elsewhere.
| Option | Type | Default | Purpose |
|---|---|---|---|
.enable | bool | false | Install the layer for Steam’s games. |
.package | package | pkgs.lsfg-vk | What to install. |
.support32Bit.enable | bool | false | Also install the 32-bit layer, for 32-bit games. |
.dll | null or str | null | Where Lossless Scaling’s DLL is, if lsfg-vk does not find it. |
.allowHalfPrecision | bool | true | FP16 frame generation, 2 to 3 times faster where supported (2.x). |
.profiles | attrs of profiles | { } | Declarative profiles; see below. |
.ui.enable | bool | false | lsfg-vk’s configuration UI, for editing profiles in Desktop Mode. |
.ui.package | package | pkgs.lsfg-vk-ui | Which UI; keep it on the layer’s major version (Steamix warns otherwise). |
.deckyPlugin.enable | bool | see below | Manage lsfg-vk from Gaming Mode with the Decky LSFG-VK plugin. |
.deckyPlugin.package | null or package | pkgs.deckyPlugins.decky-lsfg-vk or null | Which plugin. |
Three ways to run it.
-
From Gaming Mode, with Decky. When Decky Loader is on and
profilesis empty, Steamix adds the Decky LSFG-VK plugin instead of installing the layer itself: per-game frame generation settings in the Quick Access menu, the way it works on SteamOS. Press its “Install lsfg-vk” button once; it installs its own lsfg-vk into your home. The plugin needs Decky to run plugins as the Steam user, as SteamOS does, because that is whose home it installs into:steamix.decky-loader.user = config.steamix.user;Without that, Steamix installs its own layer instead and warns why the plugin was left out. The plugin’s own lsfg-vk build is made for ordinary distributions and does not run on NixOS, so Steamix’s package repairs it: the plugin validates settings with a NixOS build of its
lsfg-vk-cli, and its UI launcher starts a NixOS build of its UI. The layers games load stay as upstream built them. It carries lsfg-vk’s build, so it is unfree. After a NixOS update that changed the plugin, press “Reinstall” in it, so the copies in your home match. -
Declaratively, with
profilesset:
steamix.losslessScaling = {
enable = true;
profiles.elden-ring = {
activeIn = [ "1245620" ]; # Steam App ID, executable or process name
multiplier = 2;
flowScale = 0.75;
};
};
Steamix installs the layer, writes the whole config to
/etc/lsfg-vk/conf.toml and points every session at it, read-only; the
Decky plugin is left out, since it could not change it.
- Interactively without Decky: with
profilesempty and no Decky, the config is~/.config/lsfg-vk/conf.toml, created with defaults the first time a game loads the layer and edited with lsfg-vk’s UI (ui.enable).
A profile has activeIn (Steam App IDs, executables, Windows .exe names or
process names; lsfg-vk 1.x matches only executables and process names, and
Steamix warns about App IDs there), multiplier (2 doubles the frame rate),
flowScale (0.25 to 1, the resolution of the motion estimation),
performanceMode, pacingMode (2.x) and hdrMode (1.x).
Versions and licence. nixpkgs has shipped two major versions with
different config formats. NixOS 26.05 has the MIT-licensed 1.0;
nixos-unstable has 2.0, licensed CC BY-NC-ND 4.0, which nixpkgs treats as
unfree. Steamix writes whichever format the installed version reads, and the
variable it reads the path from (LSFG_CONFIG or LSFGVK_CONFIG). For 2.0,
nixpkgs.config.allowUnfree (or a predicate allowing lsfg-vk) has to
permit it. Its licence also forbids redistribution, so no binary cache
carries it, Steamix’s included, and it builds on your machine.
steamix.proton
GE-Proton, and AMD FSR 4 through it.
| Option | Type | Default | Purpose |
|---|---|---|---|
.ge.enable | bool | false | Install GE-Proton as a compatibility tool. |
.ge.package | package | pkgs.proton-ge-bin | Which GE-Proton; also what the FSR 4 variant is built from. |
.fsr4.enable | bool | false | Add a “GE-Proton (FSR 4)” compatibility tool. |
.fsr4.version | null or str | null | The FSR 4 DLL version to ask for, e.g. "4.1.1"; null takes GE-Proton’s default. |
.fsr4.indicator | bool | false | Draw AMD’s FSR watermark, to see whether FSR 4 is active. |
FSR 4 is AMD’s machine-learning upscaler. GE-Proton can swap it in for
the FSR 3.1 a game ships: with PROTON_FSR4_UPGRADE set, it downloads AMD’s
FSR 4 DLL when the game starts and uses it instead. It needs an AMD RDNA 3 or
RDNA 4 GPU and a game with FSR 3.1, and a network connection the first time.
The DLL is GE-Proton’s download, not something Nix manages.
fsr4.enable adds GE-Proton with that flag in front of it, as its own
compatibility tool: “GE-Proton (FSR 4)”, internal name GE-Proton-FSR4. It
sits next to a plain GE-Proton instead of replacing it, so the two never
clash. Pick it per game in Steam (Properties > Compatibility), or make it
Steam’s default compatibility tool to use it everywhere. A game’s launch
options still win: PROTON_FSR4_UPGRADE=0 %command% turns it off for that
game, and PROTON_FSR4_UPGRADE=4.1.1 %command% pins a version.
steamix.proton.fsr4 = {
enable = true;
indicator = true; # until you have seen it work
};
FSR 1 is a different thing and needs nothing: gamescope’s FSR 1 upscaler is the “Scaling Filter” in Gaming Mode’s Quick Access menu, under Performance, for games that render below the display’s resolution.
steamix.decky-loader
Decky Loader injects a plugin menu into Steam’s Gaming Mode UI.
| Option | Type | Default | Purpose |
|---|---|---|---|
.enable | bool | false | Run the loader. |
.package | null or package | pkgs.decky-loader or null | What to run. |
.user | str | "decky" | Unprivileged user plugins run as; created automatically when left at the default. |
.stateDir | path | /var/lib/decky-loader | Installed plugins and their data. |
.extraPackages | list of package | [ ] | Extra tools on the loader’s PATH, for plugins that shell out. |
.extraPythonPackages | function | _: [ ] | Extra Python modules importable by plugins, as a function of the interpreter’s package set. |
nixpkgs does not package Decky Loader. package therefore defaults to
pkgs.decky-loader only when something has provided it, and to null
otherwise — in which case the module configures nothing and emits a warning
rather than failing to evaluate. That keeps the module usable against a bare
nixpkgs, which is the same constraint the rest of it follows. Steamix builds
one in packages/decky-loader, and its overlays.default provides it as
pkgs.decky-loader; without the overlay, supply your own:
steamix.decky-loader = {
enable = true;
package = inputs.somewhere.packages.${pkgs.system}.decky-loader;
extraPythonPackages = ps: [ ps.hid ];
};
The service runs as root and drops to user for plugins. That is upstream’s
design, not an oversight — running the loader unprivileged is unsupported and
breaks.
What the module does for Decky beyond running it
Decky does not draw its own window — it injects into Steam’s UI over the CEF
debugger that steamwebhelper opens on 127.0.0.1:8080, and Steam only opens
that when .cef-enable-remote-debugging exists in its data directory at
startup. Without it the loader starts, serves happily on port 1337, and is
simply never visible in Gaming Mode.
So the module creates that file in steamix.user’s Steam directory, through
that user’s own tmpfiles instance at login, so every directory it creates on
the way belongs to the user. Steam
has to be restarted afterwards — switching the configuration is not enough,
since Steam only reads the flag when it launches.
Be aware of what that implies: an unauthenticated debugger into the Steam client, bound to loopback, for as long as Decky is enabled. That is inherent to how Decky works, not something this module adds on top.
The service also gets lsof and systemctl on its PATH — the loader uses
the first to find that CEF socket and the second to manage its own unit.
steamix.decky-loader.plugins
Type list of package, default [ ]. Plugins installed declaratively:
steamix.decky-loader.plugins = with pkgs.deckyPlugins; [
hltb-for-deck
protondb-decky
];
Each is symlinked into the plugin directory. Decky scans that directory for
subdirectories containing a plugin.json and resolves symlinks on the way, so
store paths load exactly like installed ones.
This composes with the in-game store rather than replacing it. Plugins installed through Decky’s UI are ordinary directories sitting alongside these symlinks, and keep working and updating as normal — so you can declare the ones you rely on and still try something from the store without touching your configuration.
What a declared plugin gives up is Decky’s own updater: its version is whatever the package pins, so updating means bumping the package. Uninstalling one from the UI removes only the symlink, which the next boot restores — declarative wins, which is the point, but it is a behaviour change worth knowing.
Per-plugin settings and data are unaffected either way. Decky keeps those in
settings/<plugin> and data/<plugin> beside the plugin directory, never
inside it, which is exactly what makes read-only store paths workable here.
Plugins are packaged in packages/deckyPlugins/, built by buildDeckyPlugin
from the prebuilt tarball each plugin publishes per release. Adding one is a
handful of lines — pname, version, owner, hash.
steamix.manager
SteamOS Manager is the system daemon Steam queries for things it cannot reach itself. Steam probes the interface at startup and shows only the settings the daemon can actually back, so on hardware that is not a Steam Deck most of it simply does not appear.
| Option | Type | Default | Purpose |
|---|---|---|---|
.enable | bool | false | Run the daemon. |
.package | null or package | pkgs.steamos-manager or null | What to run. |
Like Decky’s, the package is not in nixpkgs; Steamix builds one in
packages/steamos-manager and provides it through overlays.default.
Without the overlay the option resolves to null and the module stays inert
with a warning.
Why it is off by default
Enabling it on a greetd login path breaks “Switch to Desktop.” The daemon
advertises SessionManagement1, which Steam prefers over the
steamos-session-select script this module ships — and upstream implements
session switching by writing an SDDM autologin drop-in:
#![allow(unused)]
fn main() {
const CONFIG_PREFIX: &str = "/etc/sddm.conf.d";
write(paths.temp_config(), format!("[Autologin]\nSession={session}\n"))
}
Nothing reads that under greetd, and it asks for gamescope-wayland.desktop by
name where this module registers steam. The result is a stop of
graphical-session.target followed by greetd putting you straight back into
Gaming Mode. The module warns when it sees both options on.
That assumption is not unreasonable of Valve — SteamOS ships KDE and SDDM — but it is baked into the daemon rather than abstracted behind the display manager.
What you actually get on a desktop
Plausibly working: TdpLimit1, GpuPerformanceLevel1, GpuPowerProfile1,
CpuScaling1, CpuBoost1, PerformanceProfile1 (generic amdgpu and cpufreq
sysfs) and Storage1 (external drive formatting).
Not available: FanControl1, BatteryChargeLimit1, AmbientLightSensor1,
UpdateBios1 and UpdateDock1 are Steam Deck hardware; HdmiCec1/HdmiCec2
need Valve’s cecd, which this tree does not ship.
It does not fix Gaming Mode’s resolution list. That was the original reason
to reach for it, and the interface specification has no display or resolution
interface at all — Steam sets the game resolution directly through gamescope’s
GAMESCOPE_XWAYLAND_MODE_CONTROL atom, from a list it builds itself.
steamix.loginManager
Type enum [ "greetd" "sddm" ], default "greetd". Which display manager owns
the login path when steamix.autoStart is on. The difference is not cosmetic.
greetd | sddm | |
|---|---|---|
| Needs anything outside nixpkgs | no | yes — steamos-manager |
| logind session | class greeter, type tty, corrected by a pam_env rule | class user, type wayland natively |
| Respawn loop | greetd’s greeter slot, used kiosk-style | sddm.autoLogin.relogin |
| Session switching | steamos-session-select writes a state file the launcher consumes | SteamOS Manager’s SessionManagement1, which Steam drives directly |
| Closure | small | Qt, mitigated by sddm.wayland.enable |
greetd is the default because it is self-contained: nothing here needs a
package nixpkgs does not have. The price is that greetd registers its sessions
as class greeter, type tty, which desktop compositors refuse to start on,
so the module corrects it with a pam_env rule — a fix that works but that
upstream never intended.
sddm is what SteamOS itself runs, so Valve’s software finds the shape it
expects and nothing needs correcting. It also unlocks steamix.manager, which
this path enables for you: switching goes through the interface Steam prefers,
rather than through a script emulating it.
Two things the module arranges on the SDDM path so it actually works:
- Gaming Mode is registered under
gamescope-waylandas well assteam. SteamOS Manager asks forgamescope-wayland.desktopby name when Steam requests game mode and that string is not configurable, so without the alias you could leave Gaming Mode but never return to it. steamos-session-selectkeeps its name but delegates tosteamosctl switch-to-game-mode/switch-to-desktop-mode, so the desktop’s “Return to Gaming Mode” entry works the same on both paths.
Picking sddm without a steamos-manager package is an assertion, not a
silent no-op — nothing else can write SDDM’s autologin drop-in, so the module
refuses rather than leaving you with a switch that does nothing.