5

I would like to setup system socket activation for x11vnc on a server but I'm not getting the proper configuration to achieve my requirements.

I would like to:

  • Open a new VNC connection to the server on standard port (5900). Socket activation should launch x11vnc on the currently running X server.
  • Be able to connect a second client to the same vnc server so they can both see the same screen.
  • When the last client disconnects, x11vnc should be stoped.
  • A new client connection re-launches x11vnc if it is not running.

Systemd is at 225 and x11vnc at 0.9.13.

It seems I can't use a simple x11vnc.socket+x11vnc.service files combination because x11vnc will map to the next TCP port (5901) if it detects the standard port (5900) is already used (by the systemd socket).

So I use a systemd "proxy" (see https://www.freedesktop.org/software/systemd/man/systemd-socket-proxyd.html) so that systemd listen to 5900 and x11vnc on 5901. So I have:

proxy-to-x11vnc.socket:

[Socket]
ListenStream=5900
[Install]
WantedBy=sockets.target

proxy-to-x11vnc.service:

[Unit]
Description=x11vnc
Requires=x11vnc.service
After=x11vnc.service
[Service]
User=myuser
ExecStart=/lib/systemd/systemd-socket-proxyd 127.0.0.1:5901

x11vnc.service:

[Unit]
Description=x11vnc
[Service]
User=myuser
StandardError=syslog
ExecStart=/usr/bin/x11vnc -auth /home/myuser/.Xauthority -shared -display :0 -rfbport 5901 -noipv6

Only proxy-to-x11vnc.socket is started/enabled.

The problem with this setup is:

  • On first client connection, I see x11vnc being started and listening on the proper port, but the client connection just "hangs". Looking at the server logs x11vnc does not receive the connection attempt.
  • Killing the client and reconnecting successfully show the remote display.
  • Disconnecting the client will let x11vnc terminate, but I then cannot re-connect to it. x11vnc.service is in the inactive (dead) state.

Thanks!

1

Unfortunately there is no a complete solution for your problem. Your third point is not possible with the current systemd-socket-proxyd, there is a feature request on GitHub to address this issue.

For your first point, the problem is that x11vnc take quite a long time to start and does not accept connection until it is completely started. The solution, as proposed by atlassian here is to add a sleep after starting the vnc server. The systemd-socket-proxyd will then wait before forwarding the communications.

For the second point, there is the -share option for x11vnc to allow it to accept more than one connection.

The third point is unfortunatly not doable. But you can stop the vnc server by hand with systemctl stop x11vnc.

Even if you can not stop x11vnc automatically, the forth point will work when the server is stopped manually.

To summarize, here is the files you need:

/etc/systemd/system/x11vnc-proxy.socket

[Socket]
ListenStream=5900

[Install]
WantedBy=sockets.target

/etc/systemd/system/x11vnc-proxy.service

[Unit]
Requires=x11vnc.service
After=x11vnc.service

[Service]
ExecStart=/lib/systemd/systemd-socket-proxyd 127.0.0.1:15900

/etc/systemd/system/x11vnc.service

[Unit]
Description=VNC Server

[Service]
ExecStart=/usr/bin/x11vnc -forever -shared -rfbport 15900
ExecStartPost=/usr/local/bin/waitport 127.0.0.1 15900

[Install]
WantedBy=graphical.target

Please note the -forever option to keep the vnc server running when all clients are disconnected. It's the only way I found to be able to reconnect until the feature request is done. The ExecStartPost is the part that wait until the vnc server is up and running before letting the proxy to forward the connection.

/usr/local/bin/waitport

#!/bin/bash

host=$1
port=$2
tries=15

for i in `seq $tries`; do
    if /usr/bin/nc $host $port > /dev/null ; then
        # Ready
        exit 0
    fi

    /bin/sleep 1
done

# FAIL
exit -1

With all this scripts setup, you can then enable the x11vnc-proxy.socket with systemctl enable x11vnc-proxy.socket and start it systemctl start x11vnc-proxy.socket.

  • 1
    Just to note, you can simplify your answer a bit, as x11vnc also supports the -inetd option flag. Combined with a StandardInput=socket directive in x11vnc.service, it makes x11vnc-proxy.service redundant. Read about the StandardInput=socket option in the man page for systemd.exec, and note that it our case we are specifying a single socket only and do not have Accept=yes set. Doing this will also make the waitport process unnecessary. – Amir Jan 23 at 12:05

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.