On my arch server, I was setting up users restricted to their home directories. I ran:
useradd -m -s /bin/bash username
and passwd username
I've read this wiki article…
I figured I should use systemd user services to make each user run a node server on startup. So i logged into one user account su username
and created a file ~/.config/systemd/user/serve.service
containing:
[Unit]
Description=One of the servers
[Service]
ExecStart=/usr/bin/node /home/username/server.js
[Install]
WantedBy=default.target
then I ran systemctl --user enable serve.service
which responded with Failed to connect to bus: Permission denied
As far as I understand I should run systemctl --user ...
command logged in as a user and not as root.
So what did I miss in this configuration?
Best Answer
No, you did not.
You are not logging in. You are augmenting the privileges of your existing login session with
su username
.systemctl
with the--user
option locates your per-user Desktop Bus, managed by you per-user Desktop Bus dæmon, and via that bus communicates with your per-user instance ofsystemd
that manages your per-user servics.su
is not a login mechanism. It works within an existing interactive login session. In that session, your processes have environment variables that tell them where your per-user runtime directory is (XDG_RUNTIME_DIR
), where the per-user Desktop Bus is (DBUS_SESSION_BUS_ADDRESS
), and indeed other things like where your X server is (DISPLAY
).In particular,
DBUS_SESSION_BUS_ADDRESS
can implicitly referenceXDG_RUNTIME_DIR
or can explicitly name the same path. That path will generally be something like/run/user/1001/bus
for the Desktop Bus broker's access socket (presuming that your user ID is 1001, for example).These variables are not changed by
su
. There's been a whole back and forth for many years over this, including the behaviours of other similar commands such aspkexec
.The consequence of this is that if you
su
to a second user in your login session, runningsystemctl
as that second user tries to connect to a Desktop Bus broker access socket located in a directory private to the first user. User 1002 (to pick a user ID for your second user for the sake of example) cannot access/run/user/1001
or anything within it, and even if xe had read+execute access to that directory xe cannot access/run/user/1001/bus
because that only grants access to user 1001 also.Of course, this is not the right Desktop Bus broker to be talking to in the first place. You want to talk to the second user's Desktop Bus broker, and through it to the second user's per-user instance of
systemd
.The simple solution is as part of the
su
to set those environment variables to the ones appropriate for the second user account, pointing to the second user's Desktop Bus:I of course in such circumstances use a handy tool for setting this,
userenv
, which enables me not to have to type that bus address longhand:Further reading
userenv
. nosh toolset manual pages. Softwares.