Skip to content

Preflight reports "no service manager on this host" when Collie is spawned without a session env, though systemd --user is running #194

Description

@lloydsilvertwo

Summary

collie update --check reports the service row as amber

no service manager on this host — the bridge is unsupervised, so restart it by hand after the update

on a host where the bridge is running under systemd --user, is enabled, and has been for weeks.

The false negative depends only on the environment of the process running the check, not on the state of the service. Any spawner that does not pass a session environment triggers it — notably a Herdr plugin action, which herdr-plugin.toml documents as injecting "HERDR_SOCKET_PATH / HERDR_PLUGIN_CONFIG_DIR into these invocations and nothing else — no login shell".

Reproduction

On a host with a healthy ~/.config/systemd/user/collie.service:

$ ./bin/collie update --check | tail -3
  ✓       upstream       already current — v1.6.0 is the newest release of major 1
  ✓       service        collie is active — the update can restart it

$ env -i HOME=$HOME PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
      COLLIE_PLUGIN_ROOT=$PWD ./bin/collie update --check | tail -3
  ✓       upstream       already current — v1.6.0 is the newest release of major 1
  amber:  service        no service manager on this host — the bridge is unsupervised, so restart it by hand after the update

Nothing about the service changed between the two runs. systemctl --user is-active collie is active throughout.

Cause

supervisionTier() (cli/lifecycle.ts:107) gates the systemd tier on systemdUserReachable() (cli/lifecycle.ts:91), which is systemctl --user show-environment exiting 0. systemctl --user locates the user manager through XDG_RUNTIME_DIR (or DBUS_SESSION_BUS_ADDRESS); with neither set it cannot connect and exits non-zero. supervisionTier then falls through to "unsupervised" (cli/lifecycle.ts:117), and serviceCheck prints the amber line (cli/update-check.ts:591-595).

Either variable alone is sufficient for the probe to succeed:

$ env -i HOME=$HOME PATH=/usr/bin:/bin XDG_RUNTIME_DIR=/run/user/1000 systemctl --user show-environment >/dev/null; echo $?
0
$ env -i HOME=$HOME PATH=/usr/bin:/bin DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus systemctl --user show-environment >/dev/null; echo $?
0

The docstring on systemdUserReachable says the probe exists to distinguish "a container commonly ships the systemd package … without ever running a user instance or session bus" from a real user manager. That intent is right; the implementation cannot tell that case apart from "a user manager is running but this process was spawned without a session env", and reports both as unsupervised.

The consequence is not cosmetic: it tells an operator whose only interface is the phone to go restart a daemon by hand that systemd is about to restart correctly on its own.

Suggested fix

When XDG_RUNTIME_DIR is unset, derive it rather than concluding "unsupervised" — /run/user/$(id -u), and only report unsupervised if the probe still fails with it set. That preserves the container case (no user manager ⇒ no socket under that path ⇒ probe still fails) while removing the false negative on a normal Linux host.

Workaround

Adding one line to the Collie config .env fixes it for every spawner at once, since cli/context.ts merges that file into ctx.env and realExec(ctx.env, …) (cli/deps.ts:26, cli/sys.ts:270) hands it to every subprocess:

XDG_RUNTIME_DIR=/run/user/1000

Environment

  • Ubuntu 24.04, kernel 6.8.0, x86_64
  • Herdr 0.8.2, Herdr-managed Collie checkout, linger enabled for the user
  • Checkout detached at v1.6.0; reproduced against the built binary reporting 1.5.1+ba39c05. The logic in cli/lifecycle.ts is unchanged between the two, and the line numbers above are from the v1.6.0 tree.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: installbin/collie verbs, Herdr plugin lifecycle, update, tailscale servebugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions