-
Notifications
You must be signed in to change notification settings - Fork 247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
User Services 2.0 #723
base: master
Are you sure you want to change the base?
User Services 2.0 #723
Conversation
a98a008
to
c26bc8a
Compare
Previous discussion: #573 |
Hello, I didn't review this PR (yet?) so I have no idea what's going on inside at all, however, I'd like to describe my setup so maybe you'll find my thoughts useful and implement it here. So, I came to conclusion that there are in fact 2 kinds of user services:
For DE-dependent services, there's a problem that if DE process is not their ancestor then you'll need to pass al the required environment variables by hand. Systemd do exactly that by using command So DE-dependent services must have DE as their ancestor. This way we will exterminate the problem of environment variables for good. The 2nd problem of DE-dependent services is that they can depend on DE-independent ones. For example, my So I'm launching 2 $ cat ~/.config/s6/sway/yambar/run
#!/bin/bash -e
s6-svwait ~/.config/s6/user/pipewire
yambar and in general, everything is very nice, simple and works very well. So IMO for openrc user session to be useful, it should (ideally) be able to be started multiple times and provide a public API to wait for services or (systemd-like) have a mechanism of injecting environment variables like |
Regarding compositor-dependant services, there are a few other approaches worth mentioning (and many other which I don't think would add any value here): Start the service manager as a child of the compositorThis is by far the simplest approach, and I doubt there's anything simpler than this. Run the service manager as a child of the compositor. E.g.: via The main difference is that if I pick zsh as a shell instead of sway when logging in, user services won't start. For me, this is perfectly fine. If I'm logging into zsh, it's usually on a second tty to debug something that I've broken for my main session. If you expect pipewire or some other service when logging into a console, you can configure Run the compositor as a serviceRunning the compositor itself as a service is a pretty straightforward of ordering dependencies. You need some mechanism to save relevant environment variables into a file, and signal readiness. Usually a tiny helper executed by the compositor is enough. You dependant service scripts (e.g.: yambar) would depend on the compositor service and load those previously saved files with the environment variables. There are no obvious downsides to this approach, and it results in much tighter integration between relevant parts (without any unnecessary coupling). Restarting the compositor is possible, and dependant services are properly restarted. This works especially well with s6, where s6-svscan will be the main process invokes during login and that lives for the entire session. You'll end up with a service tree that's a pretty good reflection of your mental model of services. This approach is likely to have issues if the service manager is started by root and not part of the user's session. In such a scenario, because the compositor is not part of the session, I believe that seatd won't grant the compositor access input/output devices. Exporting compositor variables into a fileWhen the compositor starts, the relevant environment variables are stored in a file. The run scripts for dependant services load these environment variables. This part is the same as above. In this case, the compositor doesn't run as a service, and is started via some other mechanism. When the compositor is ready, it starts a second runlevel. Services which depend on the compositor are tied to this runlevel. |
the "recommended" way here would be to switch to a runlevel while inside your compositor's session. openrc does not have a deamon of any kind to import environments to, but when starting a service it does pick up the current environment (and filters it) so, my current workflow with that is openrc just using the current environment is both more convenient but also a bit more error prone than systemd's approach, but i think it works quite well for us i do not recommend you run your compositor as a service at all. if you use pam_openrc, it would start during the pam auth sequence, not in a proper session, and as soon as you quit it, the login process would continue and then drop you into a shell or similar and even if you don't use pam, and instead launch openrc manually, you're also starting the compositor inside openrc's environment, meaning filtered envs, so things from .profile/.bash_profile/.zshenv won't be picked up, among other things |
Passing (filtered) environment variables when starting the runlevel seems like a pretty sensible solution. I don't think a service manager needs an "import environment" anyway. If services need environment variables, they should be provisioned via their run script.
This is a limitation of having root enforce execution of the service manager instead of users executing it themselves. The core of the issue here is involving pam in the execution of the user's services themselves. |
that is true for pam, but even non pam, readiness status for compositors doesn't work well, and there's many moments it can get messes up by being inside openrc's service running enviroment it could work, but idk if it's worth it considering possible weirdnesses (having to background the compositor's process and all that) |
i've split most of this PR into 3: #752, #753, and this one once the other two are reviewed and merged, i'll update this one to use their code instead. you can keep track of all three changes in this branch: https://github.com/OpenRC/openrc/tree/user-services |
Adds two functions to librc, rc_set_user() and rc_is_user(). The latter just queries if the former was called. The former instantiates paths for locations that make sense for user services: Script dirs get set to $XDG_CONFIG_HOME/openrc/{init.d,conf.d}, and variations of the system sysconf dirs with "user.d/" as a suffix. Runlevel dir is set to $XDG_CONFIG_HOME/openrc/runlevels, and the svcdir is set to $XDG_RUNTIME_DIR/openrc. XDG_CONFIG_HOME falls back to $HOME/.config should it be unset. XDG_RUNTIME_DIR has no fallback, and thus required for user services.
c09cdd4
to
622f016
Compare
fd62d58
to
e4dbc44
Compare
Add a new function to librc, `rc_usrconfdir()`, whick returns the location where user-made rc.conf exists. The user-made configuration is loaded first over the global config, so it takes priority when resolving variables, thus "overriding" global configs.
Those variables are required for user scripts to work properly.
Some services might expect to be in home, and may behave unexpectedly for the user, e.g. any program started via dbus, and this matches systemd-user behaviour.
e4dbc44
to
9b500ed
Compare
Some binaries required to have their `atexit(cleanup)` calls moved to after argument parsing, since setting user mode also adds an atexit call, and cleaning up user paths should only happen after the cleanup of the application is done, thus needs to be set first.
9b500ed
to
fe3b01c
Compare
We need to handle --user before calling any functions that interact with librc.
fe3b01c
to
aa90ecd
Compare
with a proper branch now