2

I am currently trying to set up automated backups using borg. For that, I have written a oneshot systemd user service (called borgbackup.service) that I am planning to start via a timer.

Borg can also mount a backup repository as a virtual file system and I would like to keep my backups mounted at all times. I have written another user service for that which I called borgmount.service. However, it is impossible to create backups while the repository is mounted.

My current solution to this problem consists of these lines in my borgbackup.service to stop and restart the mounting service before and after the backup.

ExecStartPre=/usr/bin/systemctl --user stop borgmount.service
ExitStart=/bin/sh -c "borg create ::$(date) --exclude-caches --keep-tag-files"
ExecStopPost=/usr/bin/systemctl --user start borgmount.service

This seems very ugly and does not take into account the state that the borgmount.service unit was in when the backup was started (maybe it was stopped and disabled).

Is there a better way to do this?

1

Not a perfect solution, but rather than ExecStartPre you could use Conflicts.

Conflicts=

A space-separated list of unit names. Configures negative requirement dependencies. If a unit has a Conflicts= setting on another unit, starting the former will stop the latter and vice versa. Note that this setting is independent of and orthogonal to the After= and Before= ordering dependencies.

You can combine that with an ExecStopPost that checks if the conflict is enabled:

ExecStopPost=/usr/bin/systemctl is-enabled borgmount.service && /usr/bin/systemctl --user start borgmount.service

If you're not familiar with the && operator, if the first command succeeds the second will be performed. systemctl is-enabled returns 0 when the unit is enabled.

Still doesn't cover the use case that the service was enabled and stopped, but you could probably still handle that will a more complex ExecStopPost or even determine state in ExecStartPre. It's too bad systemd doesn't have an Interupts directive or similar, to stop another unit only while the unit runs.


Instead of an ExecStartPost you could also specify Conflicts= in borgmount.service and rather than running just systemctl start borgbackup.service you could run systemctl start borgbackup.service borgmount.service, but that requires remembering to run both.


Another alternative (probably the cleanest) would be to use the Conflicts in both services, and create a new target for backing up that includes both services.

borgbackup.service would need:

Before=borgmount.service to make sure it runs first

WantedBy=${NEW_TARGET} to make sure running the new target causes it to be run.

borgmount.service would need:

WantedBy=${NEW_TARGET}, you can specify multiple WantedBy directives in a unit.

Then you can trigger your backup using systemctl start ${NEW_TARGET}.

The nice thing about this method is that if borgmount.service isn't enabled it wont run in the ${NEW_TARGET}, and if you want to trigger the backup without running borgmount.service you can call the borgbackup.service on its own.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.