Skip to content

Support exporting variables into an starting environment#782

Merged
navi-desu merged 8 commits intomasterfrom
rc-update-env
Apr 2, 2026
Merged

Support exporting variables into an starting environment#782
navi-desu merged 8 commits intomasterfrom
rc-update-env

Conversation

@navi-desu
Copy link
Copy Markdown
Member

@navi-desu navi-desu commented Mar 4, 2025

included is a refactor of rc-update also

@navi-desu navi-desu force-pushed the rc-update-env branch 2 times, most recently from 5fa5e74 to 49be101 Compare March 6, 2025 23:16
@navi-desu navi-desu marked this pull request as ready for review March 6, 2025 23:42
Comment thread src/librc/librc-misc.c Outdated
Comment thread src/librc/librc-misc.c Outdated
Comment thread src/rc-update/rc-update.c Outdated
Comment thread src/rc-update/rc-update.c
Comment thread src/rc-update/rc-update.c Outdated
Comment thread src/librc/librc-misc.c Outdated
@navi-desu navi-desu force-pushed the rc-update-env branch 3 times, most recently from f83bb7f to 5682c69 Compare March 7, 2025 09:20
Comment thread src/rc-update/rc-update.c
@navi-desu
Copy link
Copy Markdown
Member Author

i rebased this on top of #819, so that's now a dependency of this mr

also reimplemented it with envdirs instead, makes it easier to unset variables, and we don't have to worry about escaping things at all

@navi-desu
Copy link
Copy Markdown
Member Author

added more details in commit messages

Comment thread src/librc/librc-misc.c Outdated
Comment thread src/librc/librc-misc.c Outdated
Comment thread man/rc-update.8 Outdated
Comment thread src/value/value.c Outdated
Comment thread src/librc/librc-misc.c Outdated
Comment on lines +472 to +473
fputs(value, envfile);
return fclose(envfile) == 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also need to check the fputs return value. Also, shouldn't we check of envfile being NULL as well?

Comment thread src/librc/librc-misc.c Outdated
Comment thread src/librc/librc-misc.c Outdated
Comment thread src/librc/librc-misc.c Outdated
Comment thread src/openrc-run/openrc-run.c Outdated
Comment on lines +948 to +949
rc_import_variables(svc->value);
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So service specific env are supposed to overwrite the global one?

Also should we be importing the env of a stopped service?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also should we be importing the env of a stopped service?

no i'm just stupid and forgot the dep stop is about dependees, not dependers

So service specific env are supposed to overwrite the global one?

i dunno actually, i could see it being argued either way

Copy link
Copy Markdown
Contributor

@N-R-K N-R-K Apr 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dunno actually, i could see it being argued either way

Yes, that's why I am asking. Either way we need to document it.

Or we could also provide some sort of special "const" functionality for the global env which disallows services overriding it. E.g something like: rc.override which will be sourced at the very end.

Or we can default to global env overriding service ones, and then have something like rc.preference which sets a preference but allows services to take priority.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, i say service-specific ones should take priority, because:

1: allows you to set something generically for all services, then override it in specific conf.d's
2: services could "choose" to allow users to override vars by doing : ${FOO:=default}
3: matches the conf.d semantics (i.e. rc.conf goes first, conf.d/$svc overrides)

@N-R-K
Copy link
Copy Markdown
Contributor

N-R-K commented Apr 16, 2025

Also, wouldn't we be able to get rid of this and simply export them into the global starting env during init?

openrc/src/shared/misc.c

Lines 67 to 71 in 6411b4b

static const char *const usrenv_allowlist[] = {
"USER", "LOGNAME", "HOME", "SHELL", "XDG_RUNTIME_DIR",
"XDG_CONFIG_HOME", "XDG_STATE_HOME", "XDG_CACHE_HOME",
NULL
};

Seems to be a cleaner and more deterministic approach.

@navi-desu
Copy link
Copy Markdown
Member Author

Also, wouldn't we be able to get rid of this and simply export them into the global starting env during init?

for XDG_RUNTIME_DIR, no, since the envdir would be located in $XDG_RUNTIME_DIR/openrc/environment -- for the others we could tho it'd be a lot of "setting the same values at every invocation" and the tmpfs IO related to that, just to re-export the same vars again later?

@N-R-K
Copy link
Copy Markdown
Contributor

N-R-K commented Apr 29, 2025

for the others we could tho it'd be a lot of [...], just to re-export the same vars again later?

The point is to have a deterministic environment for starting the services instead of getting the env from the whatever calling process' env is. But that's not a blocker, can be done in later PR.

@N-R-K
Copy link
Copy Markdown
Contributor

N-R-K commented May 29, 2025

It'd be nice to have some user facing documentation on how this works. Maybe in service-script-guide.md.

@amano-kenji
Copy link
Copy Markdown

If you are trying to change openrc-run, the man page for openrc-run should change as well, or people will not know about this.

@navi-desu
Copy link
Copy Markdown
Member Author

it's not ready yet, i'm still changing things

docs will be updated before it's merged

@amano-kenji
Copy link
Copy Markdown

Does this pull request export variables into a starting environment and also new login sessions? There can be multiple login sessions.

If I log in sway and then a linux virtual console, I have two login sessions. pam module should export DBUS_SESSIONS_BUS_ADDRESS to the second login session and the later ones as well as the first session that started dbus user service.

@WhyNotHugo
Copy link
Copy Markdown
Contributor

Isn't it much simpler to export variables into an envdir from one init script and have dependant service import that envdir from their own script?

Such an approach doesn't require adding complexity to OpenRC itself.

@WhyNotHugo
Copy link
Copy Markdown
Contributor

Perhaps I'm missing something, but if service A sets a variable for service B, reading the definition for service B provides no indication that it's receiving this environment variable from some external source.

@navi-desu
Copy link
Copy Markdown
Member Author

navi-desu commented Dec 11, 2025

Isn't it much simpler to export variables into an envdir from one init script and have dependant service import that envdir from their own script?
Such an approach doesn't require adding complexity to OpenRC itself.

not really for a few reasons:

  1. the goal is to have it be transparent, if a variable is required to be set, like how DBUS_SESSION_BUS_ADDRESS and SSH_AUTH_SOCK are, then doing depend() { need dbus ssh-agent; } should be enough, the depend function encodes information about external factors which the service requires to work and i'd like to not split that

as well as, the service that export the variable should ideally be tied to the exported variables, and having the logic in openrc makes state cleanup easier (keeping exported variables in ram after the service is stopped would be bad, since $svc restart is expected to have a clean state

s6/runit services might encode the variables in an envdir, but openrc has the script as the source of truth, we'd use envdir as an implementation detail

  1. pam_openrc must have access to said environment variables, variables exported by boot services will be expected to be exported in the pam session -- otherwise manual setup would be required for anyone using dbus via openrc, and that's not too great

this requirement means each service needs a standardized way of exporting said variables

  1. currently the implementation is done via an envdir yes, but i'm changing that to an env file, reasons being: we don't need the flexibility for modification that an envdir has, each service starts with exported envs being an empty set, and adds to them as they go, and have the set cleared at the end -- so having a single file would reduce the number of syscalls and allocations necessary, while making processing easier

Perhaps I'm missing something, but if service A sets a variable for service B, reading the definition for service B provides no indication that it's receiving this environment variable from some external source.

A doesn't set variables "for B", it exports variables "required" for any service to access A, so it's more like "service B, by doing need A, it asks for all needed variables from A

@WhyNotHugo
Copy link
Copy Markdown
Contributor

I missed the fact that the "depends" declaration triggers importing the variable, thanks for the clarification.

@xz-dev
Copy link
Copy Markdown

xz-dev commented Dec 18, 2025

What happens when a user has multiple concurrent PAM sessions running different desktop environments (e.g., KDE on tty7 and GNOME on tty6)?

Will the exported environment variables from one session overwrite those from the other?

@navi-desu
Copy link
Copy Markdown
Member Author

What happens when a user has multiple concurrent PAM sessions running different desktop environments (e.g., KDE on tty7 and GNOME on tty6)?

currently all pam sessions share the service directory, so they all share the same state

note that this is also the case on systemd, dinit, and pretty much all init systems

openrc does (in master) support setting different RC_SVCDIR, but running multiple parallel instances is not something tested nor that we guarantee works

it is something i want to think of properly doing eventually, but that is far off

so for now, if you're running multiple DEs at once, for now it is expected that they can share the services, e.g., pipewire, dbus, etc, (since even ignoring the environment sharing, you wouldn't be able to start two different "dbus" or "pipewire" services anyway)

@swagtoy
Copy link
Copy Markdown

swagtoy commented Dec 18, 2025 via email

@swagtoy
Copy link
Copy Markdown

swagtoy commented Dec 18, 2025 via email

@swagtoy
Copy link
Copy Markdown

swagtoy commented Feb 8, 2026

heads up: In the coming week I will test this PR out and experiment with its usage as a way to propagate env variables with gnome-session-openrc. I feel like I noticed a possible design quirk (wrt local service environments) but I won't comment on it much until I really prove it's there; it has to do with how things work when services exit (and when the user logs out/logs in). i could've missed a line of code here which shows how that's handled, though.

Code overall seems fine to me.

@navi-desu navi-desu force-pushed the rc-update-env branch 3 times, most recently from deccf1a to 1c4ca1b Compare March 28, 2026 23:58
librc api to interact with service environemnts. it allows us to set
variables that would live across invocations, like, exporting *DISPLAY
for gui daemons (notification, xdg-desktop), a bus address dependees
should use

the implementation stores the environment as a NUL-delimited list of
string to a file in $RC_SVCDIR/environ, similar to /proc/$pid/environ on
linux.
used to export environments set with the `export` variable in openrc-run
@navi-desu
Copy link
Copy Markdown
Member Author

okay i'm tired of pushing this off and i'm happy with this version

any changes, we can do before 0.64

@navi-desu navi-desu merged commit 93a1f58 into master Apr 2, 2026
10 checks passed
@navi-desu navi-desu deleted the rc-update-env branch April 2, 2026 01:53
@swagtoy
Copy link
Copy Markdown

swagtoy commented Apr 2, 2026

that's fine. thanks! I'll play with it some

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants