5

I'm trying to set up some tasks and services on my machine across different users.

One task is to run regular backups using restic with a regular user restic. While I can skip file permission checks for the restic binary via setcap cap_dac_read_search=+ep ~restic/bin/restic, I have trouble with another aspect of this:

Some services can only be reliably backed up while they are stopped. These services are managed by another user's systemd, however.

As root I can systemctl --user --machine [email protected] stop myservice.service just fine, but as user restic I get:

Failed to connect to system scope bus via machine transport: Permission denied
Failed to list units: Transport endpoint is not connected

(I even get the same error when I attempt to use the --machine option with my current username.)

I have tried to grant extended capabilities to a copy of the systemctl binary, but I suppose either I haven't found the correct ones, or other binaries might be involved, or what I am trying to do is not possible.

Any advice would be appreciated.

1
  • I am not very familiar with this feature and never tried to use it as non-root. My guess is that systemd just does not allow this to non-root users. This is not filesystem access but a connection to the systemd socket or some d-bus stuff. In both cases systemd sees the connection comes from a non-root user, no matter the capabilities you add to the process. You probably should use a sudo call to systemctl. Commented Aug 31 at 18:43

2 Answers 2

5

You could have a service that deactivates these units, installed as the other user, activated via socket or via file existence watch. That way, you could have a mechanism for the backup user to trigger the shutdown of these services.

But truth be told: Maybe a backup client isn't the worst to run as root? You can put it in a readonly filesystem namespace via systemd's isolation capabilities.

4
  • I ended up moving the service back to root. For anyone who might end up here, systemd service sandboxing is described here: freedesktop.org/software/systemd/man/latest/… Commented Sep 2 at 10:04
  • @LysannTranvouez awesome! I think you deserve more credit here than I do, honestly, you did all the hard work. If you post an answer to your own question, telling people what you did, maybe even showing the specific sandboxing options in your unit file, and tell me (so that I see it later), I'd definitely upvote that! It's very welcome here if you answer your own question :-) Commented Sep 2 at 10:32
  • thank you. I posted my own setup below. I would obviously appreciate input on how to improve the service file further, if you have the time for looking at that :D Edit: but I cannot seem to tag you. Is that a privilege I get only with more reputation? Oh well. Commented Sep 2 at 17:51
  • @LysannTranvouez you cannot tag me under an answer I wrote myself, because I'm getting notified of it anyways, I think Commented Sep 2 at 20:07
2

I ended up moving the backup service back to the root user and I've applied some of the systemd sandboxing options for it. I will share the details of my setup below. Note that I am very new to systemd or linux server management, so I'd appreciate input on how to improve the setup and harden it further.

# /etc/systemd/system/restic.service

[Unit]
Description=Restic backup service
Requires=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=python3 /etc/restic/backup.py --log debug
WorkingDirectory=/etc/restic
EnvironmentFile=/etc/restic/.env

ProtectSystem=strict
PrivateTmp=true
PrivateDevices=true
ProtectHostname=true
ProtectClock=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=strict
LockPersonality=true
MemoryDenyWriteExecute=true
RestrictRealtime=true
RestrictSUIDSGID=true
ReadWritePaths=/root/.cache/restic

# no Install section because it is triggered by a timer
# /etc/restic/.env

AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
# could have more environment variables for restic but my script generally passes things in via command line arguments instead

# without this (or $HOME), restic would run without cache, which is super slow
XDG_CACHE_HOME=/root/.cache

That backup.py script is not central to the question itself, but I can share a link in case anyone else wants to use it as a starting point for their setup. It stops a bunch of services, runs a bunch of restic commands, and then restarts the services it had stopped.
https://gist.github.com/lysanntranvouez/834f09d8fd5a51da0abeed0b4c5faeed

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.