4

I had posted this answer to my question sometime ago. Now, due to evolving needs, I would like to make the VNC server available to multiple users. The service should start at startup, and be available.

I tried to pass various arguments to the User= directive (under the [Service] section). I tried User=$USER, User=%u, and few other alternatives. None worked. Per the documentation, User should be a unitary and static. However, the documentation also mentions a DynamicUser just below the User= directive, which is unfortunately beyond my understanding of systemd. (Perhaps I should try User=$USER or User=%u and DynamicUser=true? Doesn't work.)

Is there a way to create a systemd template unit file for multiple users?


Ps. Seems like it could be done with the older init.d

Kartik
  • 301
  • How did you run the service with User=%u? – muru Mar 09 '18 at 07:32
  • @muru, by systemctl enable vncserver@5.service, then systemctl start vncserver@5.service. Is there something I am missing? – Kartik Mar 09 '18 at 07:35
  • I think that will use the system init, for which the user will always be root. Have you tried systemctl --user start ...? – muru Mar 09 '18 at 07:36
  • @muru, If I use systemctl --user, how would I make it available at startup for multiple users? Also, it gives me an error: "Failed to connect to bus: No such file or directory" – Kartik Mar 09 '18 at 07:41
  • By enabling linger for those user (see this comment): sudo loginctl enable-linger username, user services can be started at boot. At this time, you can pass only one parameter for systemd templates, so this seems to be the only practical way to have both username and X11 display variable. Also see: this mailing list discussion – muru Mar 09 '18 at 07:54
  • @muru, thanks a million! I figured it out. If you would post a full reply, I would gladly accept it as answer. I am going to post the answer below, but I will delete it if you answer. – Kartik Mar 09 '18 at 08:26
  • I'll post what I said in the comments as an answer, you can go ahead and post what you did as an answer. – muru Mar 09 '18 at 08:31

1 Answers1

4

It's not possible to pass multiple parameters to the a systemd template (see related mailing list discussion). However, since we have only two parameters and one is the username, it makes sense to make it a user service instead of a system service.

User services can be run at boot if you enable lingering for those users:

sudo loginctl enable-linger username

From man loginctl:

enable-linger [USER...], disable-linger [USER...]
   Enable/disable user lingering for one or more users. If enabled for
   a specific user, a user manager is spawned for the user at boot and
   kept around after logouts. This allows users who are not logged in
   to run long-running services. Takes one or more user names or
   numeric UIDs as argument. If no argument is specified,
   enables/disables lingering for the user of the session of the
   caller.

You can create a user service at /etc/systemd/user, which would look like (adapting your earlier service):

[Unit]
Description=Start TigerVNC Server at startup
After=syslog.target network.target

[Service]
Type=forking
PAMName=login
PIDFile=%h/.vnc/%H:%i.pid
ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver :%i -depth 24 -geometry 1920x1080 -nolisten tcp -localhost
ExecStop=/usr/bin/vncserver -kill :%i

[Install]
WantedBy=default.target

Use the %h specifier for the user home directory. I have omitted the User= field, which doesn't make sense in user sessions. Also note the change to WantedBy in [Install] from multi-user.target (which does not exist in user sessions) to default.target.

The users can then control this service using systemctl --user commands. (Note that you might need to restart after enabling linger if that user hasn't logged in yet, so that a user session is started for them.)

Kartik
  • 301
muru
  • 197,895
  • 55
  • 485
  • 740