Open adrelanos opened 5 days ago
~Interestingly, there is no graphical-session.target
at all in Fedora (but it is documented in the systemd.special
man page).~ my bad, typo
This is going to be a bit tricky, as qubes-gui-agent is a system unit, and graphical-session.target is a user unit. I don't think one can bind them across system/user instances boundary. I guess we need a dummy user unit for this...
On my Kubuntu system, I see that /usr/lib/systemd/user/plasma-workspace.target
Requires
graphical-session.target, BindsTo
it, and is Before
it. I can test if making and enabling such a service on R4.3 fixes the issue, and make a pull request if so.
@ArrayBolt3 the thing is, VM has no equivalent of plasma-workspace.target user unit. There is only qubes-gui-agent.service system unit.
@marmarek Right, but all that needs to be done is making some arbitrary dummy unit like you said, and enabling it (at least I think that will work). I wasn't really coming up with any new ideas, just looking for which settings the dummy unit would need in order to do the right thing.
The following works for me in a whonix-workstation-17 template:
[template workstation user ~]% cat /usr/lib/systemd/user/force-graphical-session.service
[Unit]
Description=get graphical-session.target to work
BindsTo=graphical-session.target
Before=graphical-session.target
Requires=graphical-session.target
[Service]
ExecStart=/usr/bin/true
Type=oneshot
RemainAfterExit=true
[Install]
WantedBy=default.target
Then systemctl --user enable force-graphical-session.service
and reboot. graphical-session.target
will be active on boot.
[template workstation user ~]% systemctl --user status graphical-session.target
● graphical-session.target - Current graphical user session
Loaded: loaded (/usr/lib/systemd/user/graphical-session.target; static)
Active: active since Tue 2024-11-12 21:58:55 UTC; 1min 50s ago
Docs: man:systemd.special(7)
Nov 12 21:58:55 host systemd[793]: Reached target graphical-session.target - Current graphical user session.
However, this does NOT seem to make graphical-session.target work in a whonix-workstation-17-dvm machine. Not sure why yet.
edit 1: clarified that this was a whonix-workstation-17 template
edit 2: Switched from WantedBy=basic.target
to WantedBy=default.target
since that seemed more sensible
Well, even it that "works", it would be wrong thing to do, as graphical-session.target
is supposed to be active when actual graphical session is active, not just always.
Yeah, that's a good point. Further complicating matters is that enabling a user service in a template doesn't seem to enable it in a DispVM, and disabling the user service in the template doesn't disable it in the DispVM either. Not sure what's happening there, I'm on Qubes OS R4.3.
Hmm. The way it works in KDE Plasma appears to be something like this:
/usr/bin/startplasma-x11
startplasma-x11
does some setup work, then connects to systemd over D-Bus and instructs it to launch the plasma-workspace-x11.target
user targetplasma-workspace.target
plasma-workspace.target
appears to be what reaches graphical-session.target
.So it might be possible for the GUI daemon to do sort of the same thing:
That wouldn't require a dummy systemd unit at all, though it would require some substantial complexity. The potentially tricky parts are going to be figuring out which user to "drop" to, and then doing the D-Bus connection.
er, replace gui-daemon with gui-agent, I had them mixed up.
The proper place is to plug it into qubes-session
somehow - this is what is started under Xorg as the user. But still, not sure how to do it to behave as the documentation says:
graphical-session.target
This target is active whenever any graphical session is running. It is used to stop user services which only apply to a graphical (X, Wayland, etc.) session when the session is terminated. Such services should have "PartOf=graphical-session.target" in their [Unit] section. A target for a particular session (e. g. gnome-session.target) starts and stops "graphical-session.target" with "BindsTo=graphical-session.target".
So, we need to ensure not only it gets started at proper time, but also it gets stopped when graphical session (qubes-session / qubes-gui-agent) are stopped.
Or maybe even one step earlier - plug it into qubes-run-xorg to call the whole xinit etc (see final lines of the script) under user unit. But then, monitoring if the X server is still running will get tricky, qubes-run-xorg
shouldn't exit before X server exits, and systemctl --user start
doesn't normally wait for the unit to stop... (maybe systemctl --user --wait start
could be used?)
To me it seems like qubes-session is the equivalent of startplasma-x11 as far as sessions are concerned. My initial instinct would be to put it here: https://github.com/QubesOS/qubes-gui-agent-linux/blob/main/appvm-scripts/usrbin/qubes-session#L40-L49 Have a user systemd unit with the needed BindsTo
that calls qsvc qubes-gui-agent
, and start that unit using systemctl
in qubes-session
. When qubes-gui-agent
dies, so will the unit (if configured properly), which should take down graphical-session.target
with it.
If going the latter direction, this would need to be done carefully - all the user processes (including most qrexec services, xdg autostart apps etc) are started as children of qubes-session, which means it's sensitive for changes in environment vars, applied limits, cgroups etc...
My initial instinct would be to put it here: https://github.com/QubesOS/qubes-gui-agent-linux/blob/main/appvm-scripts/usrbin/qubes-session#L40-L49
Nope, this part applies only to sys-gui (it starts Xfce or whatever user has configured in sys-gui, which itself runs gui-agent connected to dom0).
Nope, this part applies only to sys-gui (it starts Xfce or whatever user has configured in sys-gui, which itself runs gui-agent connected to dom0).
hmm, I may be severely confused as to the purpose of the qubes-session script then, because I don't see anything else in that script that would launch the GUI agent, and I thought this was the GUI agent launcher each qube ran. edit: or I can't read and just missed the blatant exit
that was right there :facepalm:
the flow is: qubes-gui-agent -> qubes-run-xorg -> xinit -> ... -> Xorg + qubes-session
I think your --wait
idea will work. man systemctl
's documentation on --wait
makes it sound like it will work to block until the unit terminates, and I tested the theory with the following simple systemd user unit:
[Unit]
Description=testabcd
[Service]
Type=exec
ExecStart=/usr/bin/sleep 10
[Install]
WantedBy=multi-user.target
With systemctl --user start testabcd
, the command returns instantly. With systemctl --user --wait start testabcd
, it hangs for 10 seconds.
Qubes OS release
R4.2.
Brief summary
The
graphical-session.target
is missing in Qubes.This breaks Kicksecure's and Whonix's msgcollector /usr/lib/systemd/user/msgcollector-gui.service.
Steps to reproduce
Expected behavior
Compared to KUbuntu:
Actual behavior
Qubes Debian Template: