Skip to content

backend/nitro: add#36

Open
CosmicToast wants to merge 1 commit into
chimera-linux:masterfrom
CosmicToast:nitro
Open

backend/nitro: add#36
CosmicToast wants to merge 1 commit into
chimera-linux:masterfrom
CosmicToast:nitro

Conversation

@CosmicToast
Copy link
Copy Markdown

This is closely modeled after the runit backend, with the following changes:

  1. Error codes are different due to there being additional error conditions. These are based on sysexits.h, besides 32 for usage.
  2. The environment directory (and control socket) are placed in SRVDIR. Unless the configuration sets the parameter to null, this is then symlinked into an XDG_RUNTIME_DIR static location.
  3. The script to update the runtime environment does some additional handling, in case (e.g.) turnstile isn't handling XDG_RUNTIME_DIR while profile.d is. (this is untested)
  4. Readiness notification is done via a file created in SRVDIR by generating a SYS/setup. Nitro automatically runs SYS on startup as a oneshot. Inside of sys, it is possible to launch (and wait on) arbitrary services, meaning users can specify their core services inside of SYS/rc.

Globally, this is an adaptation from what I wrote for my system to try and make it fit into the codebase better. What I had locally involved things like a more generic envdir handler that could be shared, but even if this is desirable, fitting into the existing codebase is a higher priority when upstreaming for me.

This adapted version is currently running on the system I am typing this on with no issues, but I did not perform consistent testing. I also didn't bother building/installing this (i.e. it's running by way of manually adding entries to /usr/libexec, /usr/local/bin, and /etc/turnstile).

It may be useful to give users guidance as to how to import the environment locally. NITRO_SOCK is in the envdir (which allows using nitroctl), but this is not automatically imported. I'm not sure if there's interest in automatically propagating service manager environment variables to a user shell like the DBUS_SESSION_BUS_ADDRESS, but even if there is I similarly consider this out of scope here.


. @CONF_PATH@/backend/nitro.conf
: ${service_env_dir:="${XDG_RUNTIME_DIR}/turnstile.env"}
envd=${TURNSTILE_ENV_DIR:-${service_env_dir:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/turnstile.env}}
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.

i don't think it makes sense for the envdir to be in XDG_RUNTIME_DIR. I put it in ~/.config so users could set persistent vars

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I don't really like doing that because you then end up with stale references. Consider for example:

  1. Service foo also updates the activation environment to include its _SOCK variable, but is not launched on session startup (but rather manually by the user).
  2. User imports the activation environment in their rc.
  3. User starts a session, starts foo, then reboots.
  4. FOO_SOCK is now in the activation environment, even though it shouldn't be (i.e. it is a stale reference).

There are various ways to update the activation environment that is in control of the user (xdg autostart, profile, window manager config, etc). For persistent vars I would prefer those be used, ensuring that the current activation environment narrowly matches the current session.

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.

would it make sense for this to be generic across backends that need it?

turnstile-update-envdir <nitro|runit> <var>[=value]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I think it would, but figured I'd do something closer to what's already in the repo. I had considered a fully-generic envdir + envfile handler, but I can't quite find my draft for that. I have found a turnstile-envdir draft from a bit earlier than that point, see examples for (some of) the motivation. Let me know what you think!

I'm perfectly willing to adapt the PR to also update both envdir-based backends to use this mechanism or something similar if that's what's desirable.

A draft of `turnstile-envdir` I have lying around.
#!/bin/bash
# bash is pulled in for printf %q (which may become POSIX) and namerefs
# clobbers $envdir, $e, $f, $action, $name
# note that printf %q under bash produces $'' strings
# these are POSIX-2024 compliant, but your shell may not be

: ${envdir:=${ENVDIR:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/env}}

usage() {
	cat <<-EOF
	$1 [-LSX] [-d envdir] [VAR...]
	Manages a chpst(8)-compatible env dir.

	-L: Export environment in a quoted format appropriate for evaluating,
	    if any VARs are specified, only export those. Default mode.
	-S: Update env dir with arguments. If VAR follows the VAR=VAL pattern,
	    set VAR to VAL, otherwise take the value from the environment.
	-X: Take VAR... to be a sublist to execute with the environment.
	    Exactly equivalent to exec chpst -e "\$envdir".
	-d: Set envdir explicitly. The actual envdir is a priority rule:
	    the OPTARG of -d > \$envdir > \$ENVDIR > /env under \$XDG_RUNTIME_DIR.
	    With your current invocation, it would be '$envdir'.

	Examples:
	- eval "\$($1 -L)" # set all variables without exporting them
	- set -a; eval "\$($1 -L)"; set +a # ditto, while exporting them
	- $1 -S foo bar=baz # set foo to whatever \$foo is right now, and bar to baz
	- $1 -X my cmd # run 'my cmd' with the envdir variables set and exported
	- $1 -d /some/dir # like '$1 -L' but /some/dir is used as the envdir
	EOF
} >&2

action=list
while getopts LSXd: name
do
	case $name in
		L) action=list ;;
		S) action=set  ;;
		X) action=exec ;;
		d) envdir=$OPTARG ;;
		?) usage "$(basename "$0")"; exit 2 ;;
	esac
done
shift $(( $OPTIND - 1))

case $action in
	list)
		[ -d "$envdir" ] || break
		for f in "$envdir"/*; do
			# WARN: printf %q is not POSIX… yet; see notes under POSIX 2024
			# it's *not* yet available in the dash builtin or busybox
			# use either bash (#!/bin/bash) or coreutils to get this
			printf '%s=%q\n' "$(basename "$f")" "$(cat "$f")"
		done
		;;
	set)
		[ -d "$envdir" ] || mkdir -pm 0700 "$envdir"
		for e; do
			case "$e" in
				*=*) printf '%s' "${e#*=}" > "$envdir/${e%%=*}" ;;
				*)
					declare -n name="$e"
					printf "$name" >"$envdir/$e"
					;;
			esac
		done
		;;
	exec)
		exec chpst -e "$envdir" "$@"
		;;
esac

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.

2 participants