Sending notifications from system services

I have a systemd system service that runs backups, and I would like for it to send a notification to my user when the backup fails.

After some digging, it turns out that libnotify’s notify-send uses the DBUS_SESSION_BUS_ADDRESS environment variable to know where the dbus socket is.

Usually that variable contains a predictable filesystem path, e.g. /run/user/1000/bus, but on my NixOS 19.09 machine it looks like unix:abstract=/tmp/dbus-cvbmvEi4fR,guid=219870d4ae1b0bead41f06b6bdce40ec , i.e. it points to an abstarct socket.

I presume the above is less predictable than the filesystem path, and I would like to change that value.

I think the right place to do that would be in the display manager config (I use lightdm), but I’m not sure where exactly.

So two questions:

  • where is that variable initialized and set to use the unix:abstract socket?
  • how can I change that?

AFAIK the variable is initialized by the dbus-launch application.

For a nice path like /run/user/1000/bus you want a socket activated dbus user session. This should be made the default (and IMHO the only) option since it also is necessary for a fully functional systemd user session. I started working on improving this for 19.09 but unfortunately didn’t manage to finish in time, see #67942.

The immediate work-around I could think of is to try adding some line like

sudo systemctl set-environment DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS

to your ~/.xprofile file to inform systemd about your dbus session but that seems mega hacky and if there is any sense in the world you’ll end up with some permission error about your backup service trying to hook itself into your user’s private session bus.

An alternative might be to create a named pipe readable by your user and writable by the backup service and then create a systemd user service that essentially does

while true; do
  read line < "$HOME/.backup-service-pipe" ; notify-send "$line"
done

I don’t know hardly anything about dbus, but can’t it be used to emit events that anyone can listen for? Maybe you could have a systemd user service that listens for a special event and notify-send’s its data. Then any system service that wants to notify the user just emits that event. I guess if you’re not logged in at the time of the event, you’d miss it though…