gui: one shared dbus session bus for the gui session (#1906)
This commit is contained in:
parent
14ae7367cd
commit
baa5ce3e1a
2 changed files with 62 additions and 5 deletions
|
|
@ -270,6 +270,19 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
|
||||||
wayland client sharing the `/run/gui/wayland-0` socket). Wayland
|
wayland client sharing the `/run/gui/wayland-0` socket). Wayland
|
||||||
clients in the agent's config (e.g. bitburner electron) must run as the
|
clients in the agent's config (e.g. bitburner electron) must run as the
|
||||||
same user with `XDG_RUNTIME_DIR=/run/gui`.
|
same user with `XDG_RUNTIME_DIR=/run/gui`.
|
||||||
|
- **One shared D-Bus session bus (`gui-dbus.service`)**: a single
|
||||||
|
persistent `dbus-daemon --session` bound at `/run/gui/bus`, run as the
|
||||||
|
agent user, ordered `before weston.service` (it shares the same
|
||||||
|
`RuntimeDirectory=gui`, creating the dir first). Chromium/electron via
|
||||||
|
ozone refuse to map an `xdg_toplevel` without a reachable session bus
|
||||||
|
("Failed to connect to the bus" → binds `xdg_wm_base` then destroys it
|
||||||
|
= invisible window even though CDP works). The fix is **not** to wrap
|
||||||
|
each client in its own `dbus-run-session` (a private throwaway bus per
|
||||||
|
process — that's a *separate* session, defeating the one-session
|
||||||
|
model); it's this one shared bus, whose address is exported as
|
||||||
|
`DBUS_SESSION_BUS_ADDRESS=unix:path=/run/gui/bus` via
|
||||||
|
`systemd.globalEnvironment` so weston, the harness and every GUI client
|
||||||
|
inherit it.
|
||||||
- **Fixed Wayland socket name (`--socket=wayland-0`)**: weston is
|
- **Fixed Wayland socket name (`--socket=wayland-0`)**: weston is
|
||||||
launched with `--socket=wayland-0` so the socket path is
|
launched with `--socket=wayland-0` so the socket path is
|
||||||
deterministic. `harness-base.nix` exports `WAYLAND_DISPLAY=wayland-0`
|
deterministic. `harness-base.nix` exports `WAYLAND_DISPLAY=wayland-0`
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,11 @@ in
|
||||||
`Type = "simple"` so a misconfigured weston degrades to a restart
|
`Type = "simple"` so a misconfigured weston degrades to a restart
|
||||||
loop instead of blocking `nixos-container update`.
|
loop instead of blocking `nixos-container update`.
|
||||||
|
|
||||||
Weston and the wayland client run as the agent's own non-root
|
Weston, the wayland client and the agent harness run as the
|
||||||
user (`hyperhive.user.name`), sharing one user session with a
|
agent's own non-root user (`hyperhive.user.name`), sharing one
|
||||||
fixed `XDG_RUNTIME_DIR=/run/gui`.
|
session: a fixed `XDG_RUNTIME_DIR=/run/gui`, one wayland display,
|
||||||
|
and one D-Bus session bus at `/run/gui/bus` (gui-dbus.service),
|
||||||
|
so GUI clients need no private `dbus-run-session`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -100,9 +102,48 @@ in
|
||||||
session sufficient pam_permit.so
|
session sufficient pam_permit.so
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# One shared D-Bus *session* bus for the whole GUI session, bound at
|
||||||
|
# /run/gui/bus and owned by the agent user. Wayland GUI clients
|
||||||
|
# (chromium / electron via ozone) refuse to map a toplevel without a
|
||||||
|
# reachable session bus ("Failed to connect to the bus" -> binds
|
||||||
|
# xdg_wm_base then destroys it = invisible window, though CDP still
|
||||||
|
# works). Running ONE persistent bus here -- instead of each client
|
||||||
|
# wrapping itself in `dbus-run-session` (a private throwaway bus per
|
||||||
|
# process) -- keeps weston, the agent harness and the GUI client in a
|
||||||
|
# single session: one user, one XDG_RUNTIME_DIR, one wayland display,
|
||||||
|
# one bus. The address is exported via globalEnvironment below so
|
||||||
|
# every unit in the container inherits it.
|
||||||
|
systemd.services.gui-dbus = {
|
||||||
|
description = "Shared D-Bus session bus for the GUI session";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "weston.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = userName;
|
||||||
|
Group = userName;
|
||||||
|
# Share /run/gui with weston; ordered `before` weston so this
|
||||||
|
# creates + chowns the dir first. Preserve across restarts so
|
||||||
|
# weston + clients don't lose the dir holding their sockets.
|
||||||
|
RuntimeDirectory = "gui";
|
||||||
|
RuntimeDirectoryMode = "0700";
|
||||||
|
RuntimeDirectoryPreserve = "yes";
|
||||||
|
Environment = "XDG_RUNTIME_DIR=/run/gui";
|
||||||
|
# dbus-daemon unlinks a stale path socket before binding, so a
|
||||||
|
# restart re-binds /run/gui/bus cleanly.
|
||||||
|
ExecStart = "${pkgs.dbus}/bin/dbus-daemon --session --nofork --nopidfile --address=unix:path=/run/gui/bus";
|
||||||
|
SyslogIdentifier = "gui-dbus";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = "2s";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.weston = {
|
systemd.services.weston = {
|
||||||
description = "Weston Wayland compositor (VNC backend)";
|
description = "Weston Wayland compositor (VNC backend)";
|
||||||
after = [ "network.target" ];
|
after = [
|
||||||
|
"network.target"
|
||||||
|
"gui-dbus.service"
|
||||||
|
];
|
||||||
|
wants = [ "gui-dbus.service" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
|
|
@ -155,10 +196,13 @@ in
|
||||||
# to systemd service units. Without these vars a service starting
|
# to systemd service units. Without these vars a service starting
|
||||||
# a Wayland client would either fail to connect (libwayland falls
|
# a Wayland client would either fail to connect (libwayland falls
|
||||||
# back to a headless display) or open a second compositor — VNC
|
# back to a headless display) or open a second compositor — VNC
|
||||||
# shows a blank desktop.
|
# shows a blank desktop. DBUS_SESSION_BUS_ADDRESS points every unit
|
||||||
|
# at the one shared session bus (gui-dbus.service above) so GUI
|
||||||
|
# clients use it instead of spawning a private `dbus-run-session`.
|
||||||
systemd.globalEnvironment = {
|
systemd.globalEnvironment = {
|
||||||
WAYLAND_DISPLAY = "wayland-0";
|
WAYLAND_DISPLAY = "wayland-0";
|
||||||
XDG_RUNTIME_DIR = "/run/gui";
|
XDG_RUNTIME_DIR = "/run/gui";
|
||||||
|
DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/gui/bus";
|
||||||
};
|
};
|
||||||
|
|
||||||
# weston on the agent's interactive PATH so claude can run Wayland
|
# weston on the agent's interactive PATH so claude can run Wayland
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue