Skip to content

Conversation

@BohdanTkachenko
Copy link

Description

On systems where graphical sessions like GNOME are started by the systemd user manager, the session environment is not sourced from a traditional shell profile. This results in an incomplete PATH environment variable. Consequently, .desktop files for applications installed by Home Manager are considered invalid because their Exec= target cannot be found in the PATH, and the applications do not appear in menus.

While systemd.user.sessionVariables can set simple variables, it is not well-suited for dynamically constructing PATH. Systemd provides a more suitable mechanism for this task: an environment generator.

This commit implements this solution by adding a script to ~/.config/systemd/user-environment-generators/. This script is executed by the systemd user manager on startup and sources:

  • The main Nix profile script (nix.sh)
  • The Home Manager session variables script (hm-session-vars.sh)

This correctly populates the environment for all services and applications managed by the user instance. While the primary motivation is fixing the PATH, this approach also ensures all other environment variables from the profile scripts are set. This makes the systemd session environment consistent with that of an interactive shell profile, providing a more predictable experience regardless of how the user session is initiated.

A test is included to validate the generator's creation and content.

Fixes: #1439

Checklist

  • Change is backwards compatible.

  • Code formatted with nix fmt or
    nix-shell -p treefmt nixfmt deadnix keep-sorted --run treefmt.

  • Code tested through nix run .#tests -- test-all or
    nix-shell --pure tests -A run.all.

  • Test cases updated/added. See example.

  • Commit messages are formatted like

    {component}: {description}
    
    {long description}
    

    See CONTRIBUTING for more information and recent commit messages for examples.

  • If this PR adds a new module

    • Added myself as module maintainer. See example.
    • Generate a news entry. See News
    • Basic tests added. See Tests
  • If this PR adds an exciting new feature or contains a breaking change.

    • Generate a news entry. See News

On systems where graphical sessions like GNOME are started by the systemd
user manager, the session environment is not sourced from a traditional
shell profile. This results in an incomplete `PATH` environment variable.
Consequently, `.desktop` files for applications installed by Home Manager
are considered invalid because their `Exec=` target cannot be found in the
`PATH`, and the applications do not appear in menus.

While `systemd.user.sessionVariables` can set simple variables, it is not
well-suited for dynamically constructing `PATH`. Systemd provides a more
suitable mechanism for this task: an environment generator.

This commit implements this solution by adding a script to
`~/.config/systemd/user-environment-generators/`. This script is executed
by the systemd user manager on startup and sources:
  - The main Nix profile script (`nix.sh`)
  - The Home Manager session variables script (`hm-session-vars.sh`)

This correctly populates the environment for all services and applications
managed by the user instance. While the primary motivation is fixing the
`PATH`, this approach also ensures all other environment variables from the
profile scripts are set. This makes the systemd session environment
consistent with that of an interactive shell profile, providing a more
predictable experience regardless of how the user session is initiated.

A test is included to validate the generator's creation and content.

Fixes: nix-community#1439
Refactor the user environment generator to comply with the
systemd.environment-generator(7) specification. Generators must write
environment variables as KEY=VALUE pairs to standard output, not source
scripts directly.

The new implementation sources the Home Manager profile scripts in a
subshell, calculates the resulting environment changes, and prints them
in the required format. This ensures variables are correctly propagated
to the systemd user session.
The script for sourcing profiles in the user environment generator is
refactored to be more direct and readable.

The previous implementation, which manually constructed a command string
to be executed in a subshell, is replaced with a more idiomatic `for`
loop inside a process substitution. This simplifies the script and
removes unnecessary complexity.

Co-authored-by: Bruno BELANYI <bruno@belanyi.fr>
@BohdanTkachenko
Copy link
Author

It looks like $XDG_CONFIG_HOME/systemd/user-environment-generators is actually not a standard path for these generator scripts and it is not listed in systemd.environment-generator(7).

There is an open feature request systemd/systemd#32423 to add this path by default and there is also a workaround, which I am going to try to use.

I discovered this, because this pull request works on my laptop, but does not work on my PC. I have no idea why it works on my laptop. On my laptop I use bluefin-dx and on my PC I use bazzite, which is based on Bluefin as well. I checked Bazzite and Bluefin repos but couldn't find anything that would affect this behavior. What is even more confusing is that systemd-path systemd-search-user-environment-generator does not list $XDG_CONFIG_HOME/systemd/user-environment-generators on both my PC and my laptop, so it shouldn't work! I tried grepping configs on my laptop to find where user-environment-generators is referenced and was only able to find it in the same basic libs as on my PC. Kind of a mystery here...

This PR probably cannot be merged until we can figure out how to make it reliably work on most environments, or until systemd/systemd#32423 is addressed.

According to `man systemd.environment-generator(7)`, the search paths for environment generators
are hardcoded and do not include a user-specific directory like `%h/.config/systemd/user-
environment-generators`. This prevents Home Manager's generator from being discovered by default.

This change implements a workaround by creating a `systemd/user.conf` file to override the
`SYSTEMD_ENVIRONMENT_GENERATOR_PATH` environment variable for the user's manager instance, adding
the necessary user path.

This resolves the issue until a permanent solution is implemented upstream.

Related to systemd issue: systemd/systemd#32423
@BohdanTkachenko
Copy link
Author

So the workaround suggested in systemd/systemd#32423 (comment) worked, so I added a systemd config file to override default generators path.

Regarding to why previously I though it is working was trivial - during previous debug session I hardcoded something to make it work and then forgot about that.

The previous commit inadvertently introduced a second source for the `systemd/user.conf` file,
causing a file collision between the new logic and the existing `systemd.user.settings` option that
broke the test suite.

This follow-up commit resolves the issue by merging the two mechanisms. The logic to add the
environment generator path is now handled within the `apply` function of the
`systemd.user.settings` option.

This change prepends the required path to the user's configuration, making it a hardcoded,
non-overridable setting that ensures the Home Manager generator path is always correctly set.
@teto
Copy link
Collaborator

teto commented Oct 26, 2025

sounds promising. not sure when I can test but will do

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.

installed apps don’t show up in Ubuntu's "Show Applications"

3 participants