## Run VNC server before logging to Linux GUI

I installed X11vnc and to my dismay, there isn’t a easy option that automatically configures VNC as a service like most Windows VNC software does (so you can VNC into a computer before you login as a user graphically and launch the X11vnc executable).

I had to manually create a service and I ran into a few problems as the instructions on StackExchange and other forums are missing critical pieces.

In here, I will use X11vnc server on Ubuntu Cinnamon (systemd) as an example. Instead of blindly pasting code here without context, I’ll sketch out the ideas here:

1. Establish a password in a password file stored in common areas such as /etc/x11vnc.pwd instead of using the user-specific home folder default ~/.vnc/passwd
2. Create a service (such as systemd) pointing to x11vnc program with the right parameters, which includes the path to the password file stored in common areas
3. Start the service

It’s worth nothing that the X11server connection is unencrypted. I tried the -ssl options but my RealVNC clients complained about their version

First of all, x11vnc -storepasswd creates the encrypted password file at the current home folder where you run the code. You are going to call the said password file with x11vnc -rbfauth {path to password file} parameter when launching the X11vnc server program.

One way to do it is to copy the created password to a system-specific configuration folder instead of user’s home folder:

sudo cp ~/.vnc/passwd /etc/x11vnc.pwd

Alternatively (which I do not recommend), is to specify the password AND the password-file path directly with optional specifiers of the -storepasswd parameter.

# Directly create the password file without a prompt that hides the password entry
# Clean up your terminal command history since you've exposed the password visually
history -c

Unfortunately, if you want to specify the path to the password-file, you have to specify type the plain text password in the command line, which you should do it when nobody’s watching and clear the history immediately afterwards. If you are in a public place, just do it the old way and copy the password file over

The core part of setting (doing the data-entry) for registering a service is the figuring out the command line parameters executing x11vnc program. At minimal, you’ll need

• -rfbauth specifies where the password file is (or you can directly specify the password with -passwd, which I do not recommended)
• auth: authentication means (prefers –auth guess, but you can specify where your .Xauthority file is)
• -display: 0 connects to the X11 server display, which is usually 0
• -create is the missing link! you must absolutely use this tell the VNC server to make a Xvfb (X virtual framebuffer) session if no display session is found (which is the case when you are running X11vnc as a service before logging in the a Desktop Environment like Cinnamon)

You’ll typically want this for a constant-on VNC server

• -forever: x11server instances are by default (-once) killed after the client disconnects. -forever option keeps it there

My personal preferences

• -shared: I might have a few computer VNC’ing into the linux computer and I don’t want to make sure I remember to close the ones I’m not using.
• -noxdamage: XDamage is a system that only updates the changed parts of the screen. Don’t need it when bandwidth isn’t super tight.
• -repeat: allow hold and repeat keystrokes just like what we are used to. By default it’s set to -norepeat to avoid stuck key scenarios.

For debugging (useful! that’s how I figured out the missing part that I have to use -create to make a dummy screen when using x11vnc as a service):

• -o {output log file}: typically -o /var/log/x11vnc.log
• -loop: if the program crashes for any reason, it’ll try to auto-restart for robustness. Might not need it if you use -forever

So the core command needed is:

x11vnc -repeat -noxdamage -create -display :0 -auth guess -rfbauth /etc/x11vnc.pwd -shared -forever

Now after we’ve decided the exact launch command, we will have to create the service entry. In systemd Linux, it’s done by writing a service configuration file in text format very much like Windows INI files under /etc/systemd/system and the filename MUST end with suffix “.service

In short, create /etc/systemd/system/x11vnc.service. Basic file without logging is like this:

[Unit]
Description=VNC Server for X11
Requires=display-manager.service
# The two below are for performance (make sure everything is ready before launching)
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/bin/x11vnc -repeat -noxdamage -create -display :0 -auth guess -rfbauth /etc/x11vnc.pwd -shared -forever
# The 3 lines below are option, but for robustness
ExecStop=/usr/bin/x11vnc -R stop
Restart=on-failure
RestartSec=2

# For automatically creating symlinks with "sudo systemctl enable" only
[Install]
# Start at runlevel 5 (multi-user)
WantedBy=multi-user.target

This is the minimum skeleton that does the same less robustness against the unexpected:

[Unit]
Description=VNC Server for X11
Requires=display-manager.service

[Service]
ExecStart=/usr/bin/x11vnc -repeat -noxdamage -create -display :0 -auth guess -rfbauth /etc/x11vnc.pwd -shared -forever

[Install]
WantedBy=multi-user.target

The default permissions 644 (everybody reads but only root can write is standard for services. 640, denying unknown people the read access is also acceptable if you are paranoid) should be correct if you use sudo creating the file in the /etc/systemd/system folder.

There are some older tutorials using the (/usr)/lib/systemd/system folder, which are now reserved for automatic entry by programs instead of manual service entry like what we are doing now. Technically either way works, but follow the convention so people know where to find the entries.

After that enable the service file you’ve created (the “.service” suffix is optional when calling), preferably do a daemon-reload to make sure edits in the service file is reflected. If you don’t want to wait until the next book, you can start it with systemctl

sudo systemctl enable x11vnc
sudo systemctl start x11vnc