Ubuntu – Systemd user service not starting on login

systemd

I'd like to have a backup script execute when certain external USB drives get mounted. I'm trying to achieve this systemd.

In /etc/systemd/user/autobackup.service, I've added:

[Unit]
Description=Autobackup to USB drive
Requires=media-david-backup.mount
After=media-david-backup.mount

[Service]
ExecStart=/home/david/Documents/computer/backup/scripts/backup_to_usb.sh

[Install]
WantedBy=default.target media-david-backup.mount

(Note: I'm note sure whether both WantedBy values are necessary or not.)

The mount name was determined by mounting the desired USB drive and executing systemctl list-units -t mount.

After adding the above service file, I can run systemctl --user start autobackup.service and the backup executes as expected.

I then execute systemctl --user enable autobackup.service for the service to be running every time my user logs in, which creates the necessary symlinks in ~/.config/systemd.

However, when I next log on the backup doesn't trigger when the USB drive is mounted: it will only work once I manually execute systemctl --user start autobackup.service again.

journalctl -r --user-unit autobackup shows:

Mai 19 21:15:42 david-ThinkPad-T490 systemd[4766]: autobackup.service: Succeeded.
Mai 19 21:15:42 david-ThinkPad-T490 backup_to_usb.sh[7107]: snapshot fefecca4 saved

# I've cut a bunch of backup-related log lines

Mai 19 21:15:39 david-ThinkPad-T490 backup_to_usb.sh[7107]: open repository
Mai 19 21:15:39 david-ThinkPad-T490 systemd[4766]: Started Autobackup to USB drive.

Curiously, systemctl --user -t service does NOT show the service even after it just executed successfully after manually starting the service.

As far as I can gather, I'm not expected to put systemctl --user start autobackup.service in some sort of startup script, since systemctl --user enable autobackup.service should be taking care of that.

What am I doing wrong?

Best Answer

Edit: it turns out my specific case/problems were related to my encrypted home dir and using only systemd was all that was needed for it to work, although the unit has to be started on each login. For more info see here.


Looking into this more, it appears that using only systemd isn't the best approach anyway, since I'd like to have the backup to USB triggered any time USB drives with "backup" partitions are mounted (potentially multiple times per session). Instead, it's better to have udev "want" a systemd user unit that will then trigger the actual backup script. Here's what I did:

Label the drives in GParted (e.g. to be called "backup") so they will always be mounted at the same mountpoint.

Add a user systemd unit in ~/.config/systemd/user/auto-usb-backup.service with:

[Unit]
Description=Autobackup to USB drive

[Service]
ExecStart=/home/david/Documents/computer/backup/scripts/backup_to_usb.sh

Reload the daemon: systemctl --user daemon-reload so it's aware of the new unit.

Then, add a udev rule to trigger the unit when a USB drive with a "backup" partition is mounted. Create a udev rule at /etc/udev/rules.d/90-auto-usb-backup.rules containing

SUBSYSTEM=="block", ACTION=="add", ENV{ID_FS_LABEL}=="backup", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="auto-usb-backup.service"

The ID_FS_LABEL parameter name and value were obtained using udevadm monitor --environment --udev and plugging in the drive, but the lsusb (and its -v option) and udevadm info -a -p $(udevadm info -q path -n /dev/sda) may also be useful to fine-tune rules (e.g. have the udev rule trigger only for a specific drive based on its serial number).

Reload udev for the new rule to apply: sudo udevadm control --reload

Check the rule will trigger for the drive with udevadm test /block/sda (where sda is the current drive mountpoint): you should see TAGS=:systemd: among the output.

Finally, turn remove and add the drive: the script in the systemd user unit defined above should get executed. You can double-check this (and debug) using journalctl --user-unit auto-usb-backup -r -b (note that on some systems the --user-unit option may be -u instead).

Note: it appears the script gets triggered before the drive is done mounting, so the backup script called by the systemd unit has a wait loop to sleep until the folders its looking for are available.

Resources that were helpful:

https://vic.demuzere.be/articles/using-systemd-user-units/

https://borgbackup.readthedocs.io/en/stable/deployment/automated-local.html

Related Question