feat(nb): run the WoW card's AzerothCore server as user units #248

Merged
dominik.polakovics merged 1 commit from feat/nb-wow-server-user-units into main 2026-08-01 14:47:19 +02:00

Completes the WoW card work. #247 was necessary but not sufficient — this is the
fallback it ruled in.

Why A is dead

With /etc/subuid bound into Steam's FHS (#247), podman stops silently
degrading and instead attempts the real mapping:

newuidmap 263502 0 1000 1 1 100000 65536: write to uid_map failed: Operation not permitted
Error: unable to create a new pause process

newuidmap is setuid, and setuid does not elevate inside an already
unprivileged user namespace — which is precisely what bubblewrap has created.
No amount of configuration fixes that; rootless podman cannot nest in Steam's
sandbox.

#247 is still right and still needed: before it, podman did not fail at all, it
fell back to single-uid mapping, which silently cannot reach the card's
userns-mapped files. It converted a silent wrong answer into an honest error.

What works instead

The sandbox can still reach the host's user systemd over /run/user/1000/bus
verified: systemctl --user is-system-running returns running from inside
steam-run, and bare systemctl resolves there, so the card scripts stay
portable. So the podman half moves out of the sandbox:

  • server-up.sh / server-down.sh delegate to wow-server.service when
    WOW_SERVER_VIA_SYSTEMD is set. The unit clears the variable, so the same
    script run by ExecStart/ExecStop does the real work instead of recursing.
  • bot-band.sh needs podman exec into the database container for the same
    reason, so it becomes wow-bot-band.service, PartOf the server so it stops
    with the stack. session.sh already treats this one as never-fatal.

This preserves the card's design — server starts with the game, stops when you
quit, including via Steam's Stop button, since session.sh's exit trap still
calls server-down.sh.

The card-side change is three guards in the same idiom as the WOW_GRAPHROOT
one, all no-ops where the variable is unset — so the handheld is unaffected.

Notes

No PATH handling needed: the user manager's default already carries
/run/wrappers/bin (newuidmap) and /run/current-system/sw/bin (podman,
rsync), and /usr/bin/env exists for the shebangs. It does not inherit
environment.sessionVariables, though, so WOW_GRAPHROOT is repeated in the
unit environment — that asymmetry is deliberate, not duplication by accident.

Testing

scripts/test-configuration nb passes. Runtime verification after deploy:
systemctl --user start wow-server.service, then the containers coming up and
the client reaching the login screen.

Completes the WoW card work. #247 was necessary but not sufficient — this is the fallback it ruled in. ### Why A is dead With `/etc/subuid` bound into Steam's FHS (#247), podman stops silently degrading and instead attempts the real mapping: ``` newuidmap 263502 0 1000 1 1 100000 65536: write to uid_map failed: Operation not permitted Error: unable to create a new pause process ``` `newuidmap` is setuid, and setuid does not elevate inside an already unprivileged user namespace — which is precisely what bubblewrap has created. No amount of configuration fixes that; rootless podman cannot nest in Steam's sandbox. #247 is still right and still needed: before it, podman did not fail at all, it fell back to single-uid mapping, which silently cannot reach the card's userns-mapped files. It converted a silent wrong answer into an honest error. ### What works instead The sandbox can still reach the host's user systemd over `/run/user/1000/bus` — verified: `systemctl --user is-system-running` returns `running` from inside `steam-run`, and bare `systemctl` resolves there, so the card scripts stay portable. So the podman half moves out of the sandbox: - `server-up.sh` / `server-down.sh` delegate to `wow-server.service` when `WOW_SERVER_VIA_SYSTEMD` is set. The unit clears the variable, so the same script run by `ExecStart`/`ExecStop` does the real work instead of recursing. - `bot-band.sh` needs `podman exec` into the database container for the same reason, so it becomes `wow-bot-band.service`, `PartOf` the server so it stops with the stack. `session.sh` already treats this one as never-fatal. This preserves the card's design — server starts with the game, stops when you quit, including via Steam's Stop button, since `session.sh`'s exit trap still calls `server-down.sh`. The card-side change is three guards in the same idiom as the `WOW_GRAPHROOT` one, all no-ops where the variable is unset — so the handheld is unaffected. ### Notes No PATH handling needed: the user manager's default already carries `/run/wrappers/bin` (newuidmap) and `/run/current-system/sw/bin` (podman, rsync), and `/usr/bin/env` exists for the shebangs. It does **not** inherit `environment.sessionVariables`, though, so `WOW_GRAPHROOT` is repeated in the unit environment — that asymmetry is deliberate, not duplication by accident. ### Testing `scripts/test-configuration nb` passes. Runtime verification after deploy: `systemctl --user start wow-server.service`, then the containers coming up and the client reaching the login screen.
Rootless podman cannot run inside Steam's FHS sandbox, so the card's session.sh
cannot bring its own server up on this host.

Binding /etc/subuid into the sandbox (previous commit) was necessary but not
sufficient: it got podman as far as attempting the real mapping, where it fails
with "newuidmap: write to uid_map failed: Operation not permitted". newuidmap is
setuid and setuid does not elevate inside an already unprivileged user
namespace, which is exactly what bubblewrap has created. Before that fix podman
did not fail at all — it silently fell back to single-uid mapping, which cannot
reach the card's userns-mapped files.

The sandbox can still reach the host's user systemd over /run/user/1000/bus, so
the podman half moves out of it. server-up.sh and server-down.sh delegate to
wow-server.service when WOW_SERVER_VIA_SYSTEMD is set, and the unit clears the
variable so it does not delegate back to itself. bot-band.sh needs podman exec
into the database container for the same reason and becomes its own unit, PartOf
the server so it stops with the stack.

The unit needs no PATH handling — the user manager's default already carries
/run/wrappers/bin for newuidmap and /run/current-system/sw/bin for podman and
rsync — but it does not inherit sessionVariables, so WOW_GRAPHROOT is repeated
in the unit environment.
dominik.polakovics deleted branch feat/nb-wow-server-user-units 2026-08-01 14:47:19 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/nixos!248
No description provided.