nix-community / home-manager

Manage a user environment using Nix [maintainer=@rycee]
https://nix-community.github.io/home-manager/
MIT License
6.78k stars 1.77k forks source link

bug: xdg-desktop-portal-*.service files not found (only in non-NixOS) #4922

Open johanneshorner opened 8 months ago

johanneshorner commented 8 months ago

Are you following the right branch?

Is there an existing issue for this?

Issue description

Using the xdg-portal module with the config

xdg.portal = {
  enable = true;
  extraPortals = with pkgs; [
    xdg-desktop-portal-wlr
    <hyprland from flake>.xdg-desktop-portal-hyprland
    xdg-desktop-portal-gtk
  ];
  configPackages = [
    <hyprland from flake>.default
  ];
}

results in only the xdg-desktop-portal service running with warnings that it can't find the other portal services:

● xdg-desktop-portal.service - Portal service
     Loaded: loaded (/home/johannes/.config/systemd/user/xdg-desktop-portal.service; linked; preset: enabled)
     Active: active (running) since Thu 2024-01-18 17:56:31 CET; 9min ago
   Main PID: 314794 (.xdg-desktop-po)
      Tasks: 6 (limit: 38049)
     Memory: 17.3M
        CPU: 49ms
     CGroup: /user.slice/user-1000.slice/user@1000.service/session.slice/xdg-desktop-portal.service
             └─314794 /nix/store/0n9s802xa305dppw1k9rz9w5nf29zy1k-xdg-desktop-portal-1.18.2/libexec/xdg-desktop-portal

Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: No skeleton to export
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: Failed to create email proxy: Error calling StartServiceByName for org.freedesktop.impl.portal.desktop.gtk: Unit xdg-desktop-portal-gtk.service not found.
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: No skeleton to export
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: Failed to create global_shortcuts proxy: Error calling StartServiceByName for org.freedesktop.impl.portal.desktop.hyprland: Unit xdg-desktop-portal-hyprland.service not found.
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: No skeleton to export
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: Failed to create dynamic_launcher proxy: Error calling StartServiceByName for org.freedesktop.impl.portal.desktop.gtk: Unit xdg-desktop-portal-gtk.service not found.
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: No skeleton to export
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: Failed to create screen cast proxy: Error calling StartServiceByName for org.freedesktop.impl.portal.desktop.hyprland: Unit xdg-desktop-portal-hyprland.service not found.
Jan 18 17:56:31 wslinuxhoo .xdg-desktop-po[314794]: No skeleton to export
Jan 18 17:56:31 wslinuxhoo systemd[1590]: Started xdg-desktop-portal.service - Portal service.

As a result i don't have any screenshare capabilites or other portal features.

I'm not sure where these service files are supposed to be located for the xdg-portal-service service to find them, so I'm in need of some help to track this down.

Maintainer CC

@Misterio77

System information

- system: `"x86_64-linux"`
 - host os: `Linux 6.1.0-17-amd64, Debian GNU/Linux, 12 (bookworm), nobuild`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.18.1`
 - channels(root): `"nixpkgs"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixpkgs`
johanneshorner commented 8 months ago

According to this, systemd looks for user units under $XDG_DATA_DIRS/systemd/user.

The needed service symlinks do exist there, and systemctl --user show-environment shows that systemd knows about XDG_DATA_DIRS:

[I] johannes@wslinuxhoo ~/d/h/h/rust (master)> eza --icons --group-directories-first -alhr ~/.nix-profile/share/systemd/user
/
Permissions Size User Date Modified Name
lrwxrwxrwx     - root  1 Jan  1970   xdg-permission-store.service -> /nix/store/0n9s802xa305dppw1k9rz9w5nf29zy1k-xdg-deskto
p-portal-1.18.2/share/systemd/user/xdg-permission-store.service
lrwxrwxrwx     - root  1 Jan  1970   xdg-document-portal.service -> /nix/store/0n9s802xa305dppw1k9rz9w5nf29zy1k-xdg-desktop
-portal-1.18.2/share/systemd/user/xdg-document-portal.service
lrwxrwxrwx     - root  1 Jan  1970   xdg-desktop-portal.service -> /nix/store/0n9s802xa305dppw1k9rz9w5nf29zy1k-xdg-desktop-
portal-1.18.2/share/systemd/user/xdg-desktop-portal.service
lrwxrwxrwx     - root  1 Jan  1970   xdg-desktop-portal-wlr.service -> /nix/store/4yk8nqfp415ba98csj2wizrjqaaz7l39-xdg-desk
top-portal-wlr-0.7.0/share/systemd/user/xdg-desktop-portal-wlr.service
lrwxrwxrwx     - root  1 Jan  1970   xdg-desktop-portal-rewrite-launchers.service -> /nix/store/0n9s802xa305dppw1k9rz9w5nf2
9zy1k-xdg-desktop-portal-1.18.2/share/systemd/user/xdg-desktop-portal-rewrite-launchers.service
lrwxrwxrwx     - root  1 Jan  1970   xdg-desktop-portal-hyprland.service -> /nix/store/j05swmg7jcg0xlg857r87yn9yzzy5bm2-xdg
-desktop-portal-hyprland-1.2.6+date=2023-12-25_0a318a7/share/systemd/user/xdg-desktop-portal-hyprland.service
lrwxrwxrwx     - root  1 Jan  1970   xdg-desktop-portal-gtk.service -> /nix/store/c1xbfz36a817ahivf0f9ysq73bx89bcd-xdg-desktop-portal-gtk-1.15.1/share/systemd/user/xdg-desktop-portal-gtk.service
lrwxrwxrwx     - root  1 Jan  1970   syncthing.service -> /nix/store/gcn2869izpl3v16sxqp6m34jzrgc1fir-syncthing-1.27.1/share/systemd/user/syncthing.service
[I] johannes@wslinuxhoo ~/d/h/h/rust (master)> echo $XDG_DATA_DIRS
/nix/var/nix/profiles/default/share:/home/johannes/.nix-profile/share:/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktop
[I] johannes@wslinuxhoo ~/d/h/h/rust (master)> systemctl --user show-environment
HOME=/home/johannes
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LOGNAME=johannes
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/home/johannes/.nix-profile/bin/fish
SYSTEMD_EXEC_PID=1633
USER=johannes
XDG_RUNTIME_DIR=/run/user/1000
LOCALE_ARCHIVE_2_27=/nix/store/wyl74hap7bh513hp3rz1j608gs7267af-glibc-locales-2.38-27/lib/locale/locale-archive
NIX_PATH=/home/johannes/.nix-defexpr/channels
QML2_IMPORT_PATH=/home/johannes/.nix-profile/lib/qt-5.15.12/qml:/home/johannes/.nix-profile/lib/qt-6/qml
QT_PLUGIN_PATH=/home/johannes/.nix-profile/lib/qt-5.15.12/plugins:/home/johannes/.nix-profile/lib/qt-6/plugins
QT_QPA_PLATFORMTHEME=gtk2
TERMINFO_DIRS=/home/johannes/.nix-profile/share/terminfo:/etc/terminfo:/lib/terminfo:/usr/share/terminfo
XDG_CACHE_HOME=/home/johannes/.cache
XDG_CONFIG_HOME=/home/johannes/.config
XDG_DATA_DIRS=/nix/var/nix/profiles/default/share:/home/johannes/.nix-profile/share:/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktop
XDG_DATA_HOME=/home/johannes/.local/share
XDG_STATE_HOME=/home/johannes/.local/state
GTK_MODULES=gail:atk-bridge
QT_ACCESSIBILITY=1
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
DISPLAY=:0
HYPRLAND_INSTANCE_SIGNATURE=b240704bee1d04eacc27654ea875cf6f15033c7c_1705645988
SSH_AGENT_LAUNCHER=openssh
SSH_AUTH_SOCK=/run/user/1000/openssh_agent
WAYLAND_DISPLAY=wayland-1
XDG_CURRENT_DESKTOP=Hyprland

Seems correct to me, but I can't even start the xdg-desktop-portal-* services manually.

Misterio77 commented 8 months ago

Hey,

Yeah, it should(tm) be able start user services provided by packages. Does something like systemctl --user cat xdg-desktop-portal-wlr.service work?

johanneshorner commented 8 months ago

Hey, thanks for the help.

No files found for xdg-desktop-portal-wlr.service. is the output i get. I do get output for xdg-desktop-portal.service which is in the same directory:

[Service]
BusName=org.freedesktop.portal.Desktop
Environment=XDG_DESKTOP_PORTAL_DIR=/nix/store/r2za36dwyc8943a2y0asby4pzdcycj3k-xdg-portals/share/xdg-desktop-portal/portals
Environment=NIXOS_XDG_DESKTOP_PORTAL_CONFIG_DIR=/nix/store/5ljbdm9arzvhndigv2mkm0v4zfbz84nc-xdg-portal-configs/share/xdg-desktop-portal
ExecStart=/nix/store/0n9s802xa305dppw1k9rz9w5nf29zy1k-xdg-desktop-portal-1.18.2/libexec/xdg-desktop-portal
Slice=session.slice
Type=dbus

[Unit]
Description=Portal service
PartOf=graphical-session.target

The syncthing service (which I also installed through HM) file is also found by systemd.

As far as I can tell the symlinks are all in the correct directory and point to the correct service files in the nix store. But all the services installed through xdg.portal.extraPortals are somehow not recognised by systemd.

P.S. I just tried pretty much the same HM config on a NixOS system and there it works flawlessly.

Misterio77 commented 8 months ago

P.S. I just tried pretty much the same HM config on a NixOS system and there it works flawlessly.

Hmmm! This is interesting. That's probably the reason why it didn't happen to me. Perhaps they only become available under the HM NixOS module? Will rename this issue accordingly and look into it further

Misterio77 commented 8 months ago

Ah oops I don't have permission for that, haha.

Could you include this context (only in non-NixOS) to the title and assign me?

johanneshorner commented 8 months ago

It seems that I can't change assignees.

baloo commented 8 months ago

I've had the same behavior on ubuntu. Here is my understanding:

The reason that works with nixos but not ubuntu:

How to fix that? according to pam_env(7), it will also read $HOME/.pam_environment and use all environment variables defined there, which means if you were to set this file with:

XDG_DATA_DIRS       DEFAULT=${HOME}/.nix-profile/share

that should make home-manager / systemd happy?

@johanneshorner could you try to set this file and restart your user session? (you also need to make sure the systemd --user is killed, sometimes it stays around, I'm not necessarily sure why, I think it has to do with my poor work with systemd service and I have a couple staying around)

johanneshorner commented 8 months ago

@baloo Thanks for the suggestion. Unfortunately that doesn't change anything for me.

systemctl --user show-environment also lists XDG_DATA_DIRS with the expected value (..:/home/johannes/.nix-profile/share:..), with and without the suggested .pam_environment file in place.

johanneshorner commented 8 months ago

Ahh I misunderstood earlier. systemctl --user show-environment only shows variables available to the services started by the user instance, these are not necessarily set for the user instance itself. Even though setting the XDG_DATA_DIRS through pam didn't work for me (maybe debian related?) I did pretty much the same thing using systemd drop in files.

[I] johannes@wslinuxhoo ~> cat /etc/systemd/system/user@.service.d/local.conf
[Service]
Environment="XDG_DATA_DIRS=/home/johannes/.nix-profile/share"

With that I can observe the user instance (/lib/systemd/systemd --use) being started with XDG_DATA_DIRS set. Then my portal services are found.

I'm not sure yet if there is a way to fix that from the home-manager side though.

baloo commented 8 months ago

the /etc/systemd/system/user@.service.d/local.conf you used has the same effects as what I was trying to suggest. Would you be able to export the content of your /etc/pam.d and upload a tarball here?

Maybe it's an ordering problem?

The reason I suggested the $HOME/.pam_environment is because it fixed it for me on ubuntu, and if was to work on debian too, it's probably a good enough argument to push such a fix in home-manager (and it's within reach).

NOTE: I would suggest using /etc/systemd/system/user@1000.service.d/local.conf instead (where 1000 is your uid as not to affect other users (even if your the only user on the machine, you might want to login as root))

Misterio77 commented 8 months ago

Might be worth documenting this behaviour in the extraPortals option.

johanneshorner commented 8 months ago

@baloo Regarding the .pam_enviroment file, it looks like the file is only read if user_readenv is set to 1 (Default is 0). Ubuntu supposedly also does the same, so not sure why the file is read on your system. One mine at least the user_readenv var is not set anywhere.

Using the drop-in file to set env vars for the systemd user instance works i guess, but as it's a manual step for the user maybe there is a better way? Interestingly when home-manager installs a user service (e.g. syncthing) it immediatly enables it (not actually sure what HM is doing in the background, activation at least results in a symlink in $HOME/.config/systemd/user/). Once the symlink is in $HOME/.config/systemd/user systemd --user knows about it. If you then manually disable the service (and implicitly remove the symlink) through sytemd --user disable the service is no longer found by the user instance and you can't enable it anymore.

EDIT: Maybe HM could link the service files to $XDG_RUNTIME_DIR/systemd/user/* at activation, as that var/path is always known to the user instance and HM has write access?!

baloo commented 8 months ago

@baloo Regarding the .pam_enviroment file, it looks like the file is only read if user_readenv is set to 1 (Default is 0). Ubuntu supposedly also does the same, so not sure why the file is read on your system. One mine at least the user_readenv var is not set anywhere.

This ... is a good point. user_readenv is indeed set to 0, I did experiment with the service dropins as well, I guess I goofed something in my experiment.

khlopkov commented 8 months ago

You can try to symlink required services in this way, probably will help:

ln -s ~/.nix-profile/share/systemd/user/xdg-desktop-portal-gtk.service ~/.config/systemd/user/xdg-desktop-portal-gtk.service
johanneshorner commented 8 months ago

Good Idea! I initially dismissed this as I thought that this would also implicitly "enable" the services (which you don't want for the portal services, as they are started on demand by the xdg-desktop-portal service) but that's actually not true. Only when they are symlinked to a *.target.wants directory, then they are started automatically.

@Misterio77 Maybe the xdg-portal module could create a symlink in $XDG_CONFIG_HOME/systemd/user (or ~/.config/systemd/user if the variable is not set) for each configured portal service? Then the services would be known by the user instance and can be started on demand by the xdg-desktop-portal service.

baloo commented 8 months ago

A solution that would fix more than just xdg-desktop-portal-gtk would be great. Something that fixes systemd unit definitions via home.packages. Maybe a rework of the home-manager-generation/activate script to cover that use-case?

baloo commented 8 months ago

Something ala:

  home.activation.linkSystemd = let
    inherit (lib) hm;
  in hm.dag.entryBefore [ "reloadSystemd" ] (''
    find $HOME/.config/systemd/user/ \
      -type l \
      -exec bash -c "readlink {} | grep -q $HOME/.nix-profile/share/systemd/user/" \; \
      -delete

    find $HOME/.nix-profile/share/systemd/user/ \
      -type f -o -type l \
      -exec ln -s {} $HOME/.config/systemd/user/ \;
  '');
Misterio77 commented 8 months ago

Hmm, I think this would require some more complex logic. As services.* should probably override units provided from the profile.

Maybe a explicit xdg.portal.linkPortalUnits?

baloo commented 8 months ago

The ln -s should fail in case of a conflict. I don't think it would override units (it does not for me).

What do you mean with xdg.portal.linkPortalUnits ? Like a list of units to link? I'd like to avoid having to list the specific list if possible (breaks the abstraction).

khlopkov commented 8 months ago

Probably it would be more stable to link only those .service files that are part of derivations from extraPortals. Apply to each function of the extraPortals' packages smth like this:

{pkg, lib} :
  let isService = (path: type: (builtins.match ".service$" path) == null);
    systemdDir = "${pkg}/share/systemd/user/";
    path = builtins.path { path = systemdDir; filter = isService; };
    script = lib.pipe (builtins.readDir path) [
      builtins.attrNames
      (builtins.map (f: ''ln -s "$HOME/.config/systemd/user/${f}" ${path}/${f}'' + "\n"))
      lib.concatStrings
    ];
  in { script = script; }
baloo commented 8 months ago

Portals is not the only unit where I have this issue. This also causes issues with pipewire.

stale[bot] commented 4 months ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.