Desktop notifications from Systemd Service

I am trying to setup a proper monitoring for my backups (done via Restic+rclone, setup via Nix, working as expected).

I would like to receive a desktop notification (I’m using plasma desktop) every time backup succeeds or fails (setup at hourly interval). To test things out, I created config as below:

  systemd.services.backup-success-notify-org = {
      description = "Desktop notification about successful backup";
      serviceConfig = {
        ExecStart = "${pkgs.libnotify}/bin/notify-send \'Successfully backed up: Org\'"; # for some strange reason, I don't see quotes in systemd logs, but it doesn't complain regardless of quote escaping
      };
      path = [ pkgs.bash ];  # from NixOS manual, its presence or absence doesn't matter
    };
    restic-backups-org = {      # this is name of actual restic backup service configured elsewhere
      onFailure = [ "backup-failure-alert-org.service" ];
      unitConfig.OnSuccess = [ "backup-success-notify-org.service" ]; # this shouldn't be necessary per systemd docs, but it doesn't work regardless of presence/absence
    };
  };

  systemd.timers.backup-success-notify-org = {
    timerConfig = {
      OnCalendar = "minutely"; # for testing and debugging. Ultimately this should only be invoked by OnSuccess/OnFailure events of backup service
    };
  };

I see the service and timer files are properly generated and enabled, and I see from logs that service is successfully invoked by timer every minute:

❱ systemctl status backup-success-notify-org.service
○ backup-success-notify-org.service - Desktop notification about successful backup
     Loaded: loaded (/etc/systemd/system/backup-success-notify-org.service; linked; vendor preset: enabled)
     Active: inactive (dead) since Sun 2022-02-13 17:36:02 IST; 11s ago
TriggeredBy: ● backup-success-notify-org.timer
    Process: 70743 ExecStart=/nix/store/avi8rkdrxw41b9f0gzd6i4dsaz176m9y-libnotify-0.7.9/bin/notify-send Successfully backed up: Org (code=exited, status=0/SUCCESS)
   Main PID: 70743 (code=exited, status=0/SUCCESS)
         IP: 0B in, 0B out
        CPU: 4ms

Feb 13 17:36:02 enterprise systemd[1]: Started Desktop notification about successful backup.
Feb 13 17:36:02 enterprise systemd[1]: backup-success-notify-org.service: Deactivated successfully.

But, there are no desktop notification. I can run notify-send "Some text" from terminal to desired effect, but it doesn’t seem to work when systemd service does the same. What am I missing and how can I get it to work?

I don’t know anything about libnotify specifically, but this seems relevant: [SOLVED] Desktop notifications from a systemd service / Applications & Desktop Environments / Arch Linux Forums

Thanks.

I tried with and without User=payas and it runs both ways, but result is same.

As for other solution mentioned in the link, I am not running X11, but Plasma Wayland session, and have no idea how that one can fit here.

I would try looking at any XDG_* variables set in your user session.

Pardon me if its too simple, but I have these env variables set for XDG, but not sure what I can use them for. I don’t know of Xauthority parallel in Wayland world:

❱ env | rg DISPLAY
DISPLAY=:1
WAYLAND_DISPLAY=wayland-0

❱ env | rg "XDG_[^=]+" -o
XDG_DATA_DIRS
XDG_SESSION_PATH
XDG_SEAT
XDG_ACTIVATION_TOKEN
XDG_SESSION_DESKTOP
XDG_SEAT_PATH
XDG_RUNTIME_DIR
XDG_CONFIG_DIRS
XDG_SESSION_ID
XDG_SESSION_CLASS
XDG_CURRENT_DESKTOP
XDG_SESSION_TYPE
XDG_VTNR
XDG_DESKTOP_PORTAL_DIR

Edit: Judging by this, it doesn’t appear to be possible with Wayland. What I’m wondering about is why would specifying User not work, as then none of this will be necessary…

I’d say the main issue is the system service/notify-send not having access to the user session’s D-Bus instance.

You might try giving it access by using:

[Service]
User=payas
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%U/bus
4 Likes

That worked! Thanks a lot!

1 Like

Hi, i’d like to do the same with awesome under X11 but it fails and i don’t understand why. This is what i’ve got (with a timer triggering on boot for testing):

  systemd = {
    timers."notify" = {
      wantedBy = ["timers.target"];
      timerConfig = {
        OnStartupSec = "1s";
        AccuracySec = "1us";
        Unit = "notify.service";
      };
    };

    services."notify" = {
      script = ''
        ${pkgs.libnotify}/bin/notify-send --urgency=critical "Systemd Service has failed"
      '';
      environment = {
        USER = "sperber"; # makes no difference
        # Display = ":0"; # makes no difference
        DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/%U/bus";        
        # DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/1000/bus"; # makes no difference
        # XAUTHORITY = "/home/sperber/.Xauthority"; # makes no difference
      };
      serviceConfig = {
        Type = "oneshot";
        User = "sperber";
      };
    };
  };

However, no notification is displayed and it fails like this:

~ ❯ systemctl status notify                                                                                                          ✘ 3
× notify.service
     Loaded: loaded (/etc/systemd/system/notify.service; linked; preset: enabled)
     Active: failed (Result: exit-code) since Tue 2023-09-05 12:38:14 CEST; 4min 0s ago
TriggeredBy: ● notify.timer
    Process: 1280 ExecStart=/nix/store/4ibrrh7p6ggvdsd6ih9wk16r71g71bfj-unit-script-notify-start/bin/notify-start (code=exited, status=>
   Main PID: 1280 (code=exited, status=1/FAILURE)
         IP: 0B in, 0B out
        CPU: 6ms

Sep 05 12:38:14 nixos systemd[1]: Starting notify.service...
Sep 05 12:38:14 nixos notify-start[1286]: Could not connect: No such file or directory
Sep 05 12:38:14 nixos systemd[1]: notify.service: Main process exited, code=exited, status=1/FAILURE
Sep 05 12:38:14 nixos systemd[1]: notify.service: Failed with result 'exit-code'.
Sep 05 12:38:14 nixos systemd[1]: Failed to start notify.service.

If i run notify.service in the terminal, there is no error and the notification is displayed:

~ ❯ systemctl start notify                                                                                                           ✘ 3
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ====
Authentication is required to start 'notify.service'.
Authenticating as: sperber
Password:
==== AUTHENTICATION COMPLETE ====

This works as well:

~ ❯ sudo systemctl start notify                                                                                                       7s
doas (sperber@nixos) password:

So there is something missing when run as root by systemd. What do i have to add?

I set it up as a user service and after removing the specified user, it works like this:

      services."notify" = {
        script = ''
          ${pkgs.libnotify}/bin/notify-send --urgency=critical "Systemd Service has failed"
        '';
        environment = {
          # USER = "sperber";
          # HOME = "/home/sperber/";
          # Display = ":0";
          # DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/%U/bus";
          # DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/1000/bus";
          # XAUTHORITY = "/home/sperber/.Xauthority";
        };
        serviceConfig = {
          Type = "oneshot";
          # User = "sperber";
        };
      };