Objectives:

  1. Install x11vnc as the service that would allow connections to screen 0, console session 0.
  2. Install NoVNC as the engine that would enable web socket connections toward the internal VNC server, using the WebProxy application as the bridge between x11vnc and NoVNC (so that VNC client accessibility is via HTTP/HTML5, instead of a VNC viewer application).

Disclaimer: the following config is for testing only. Do not perform this exact setup in PROD as additional security measures must be implemented to avoid being hacked. At the least, to mitigation potential unauthorized access would be to add firewall rules to only allow connections from certain dedicated jump hosts. AAA principles should be applied at that jump host.

# Install x11vnc on Linux Mint 21
sudo apt-get -y remove vino
sudo apt-get -y install x11vnc
sudo mkdir /etc/x11vnc

# Create the encrypted password file
sudo x11vnc --storepasswd /etc/x11vnc/vncpwd

# create systemd service
sudo vim /lib/systemd/system/x11vnc.service

# Paste this content into the empty file
[Unit]
Description=Start x11vnc
Requires=display-manager.service
After=display-manager.service

[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -xkb -noxrecord -noxfixes -noxdamage -display :0 -auth guess -rfbauth /etc/x11vnc/vncpwd
ExecStop=/usr/bin/killall x11vnc
Restart=on-failure
Restart-sec=2

[Install]
WantedBy=multi-user.target

# Enable service to run on bootup
sudo systemctl daemon-reload
sudo systemctl enable x11vnc.service
sudo systemctl start x11vnc.service
# Install NoVNC
sudo apt install novnc python3-websockify python3-numpy

# Create a self-signed cert
openssl req -x509 -nodes -newkey rsa:3072 -keyout novnc.pem -out novnc.pem -days 3650
#
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:Long Beach
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Dragon Coin LLC
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:[email protected]
#

# move cert into a shared location
sudo mv novnc.pem /usr/share/ca-certificates/

# Test joining NoVNC with x11vnc using WebSockify
websockify -D --web=/usr/share/novnc/ --cert=/usr/share/ca-certificates/novnc.pem 6080 localhost:5900

# View websockify running process
kimconnect@testlinux1:~$ ps aux | grep websockify
kimconnect 14092 0.0 0.1 516252 23228 ? S 10:48 0:02 /usr/bin/python3 /usr/bin/websockify -D --web=/usr/share/novnc/ --cert=/usr/share/ca-certificates/novnc.pem 6080 localhost:5900

# Use a browser to navigate to this URL
http://127.0.0.1:6080/vnc.html

# Stop websockify
killall websockify

# Create a new service to persist reboots
sudo vim /lib/systemd/system/novnc.service

# Note: websockify seems to detach from systemd; hence, it would be detected as 'failed' and caused systemd to issue signterm unnecesarily
# The workaround is to add TimeoutStopSec=1 year, SendSIGKILL=no to persist the service
[Unit]
Description=NoVNC
Requires=display-manager.service
After=x11vnc.service

[Service]
#Type=simple
User=kimconnect
Group=kimconnect
ExecStart=/usr/bin/websockify --web=/usr/share/novnc/ --cert=/usr/share/ca-certificates/novnc.pem 6080 localhost:5900
ExecStop=/usr/bin/killall websockify
# TimeoutStopSec=31536000
SendSIGKILL=no
Restart=on-failure
Restart-sec=120

[Install]
WantedBy=x11vnc.service

# Register
sudo systemctl daemon-reload
# sudo systemctl enable novnc.service # enable system wide
# sudo systemctl --global enable unit # enable all user targets
sudo systemctl --user enable novnc.service # enable this user target
sudo systemctl start novnc.service

# Monitor
journalctl -fu novnc.service
# Create a symlink to make it more convenient
sudo ln -s /usr/share/novnc/vnc.html /usr/share/novnc/index.html

######################################################################################
# Failed Attempts. Keeping this note here as archive
######################################################################################

# This was how I resolved the graphical login loop
# Press Ctrl + Alt + F2 to enter runlevel 2 to change ownership of Xauthority back to my user id
sudo chmod kimconnect:kimconnect /home/kimconnect/.Xauthority

# Optional: slso install mdm in case lightmdm had bugs
sudo apt install mdm
sudo kpkg-reconfigure mdm

# TigerVNC was originally chosen; howevever, it couldn't connect to screen 0
# Hence, x11vnc was chosen instead
# Install TigerVNC
sudo apt-get install dbus-x11 tigervnc-standalone-server tigervnc-xorg-extension tigervnc-viewer

# Discover the default session manager
cat /etc/X11/default-display-manager
# Sample output for Linux Mint
/usr/sbin/lightdm

# On Ubuntu, this is expected
/usr/bin/cinnamon-session

touch ~/.vnc/xstartup
chmod +x ~/.vnc/xstartup

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
/usr/sbin/lightdm

# Setup password
vncpasswd
# Sample output
Password: ******************
Verify: ******************
Would you like to enter a view-only password (y/n)? n
A view-only password is not used

# Ran into issues when trying to run VNCServer on screen 0
vncserver -localhost no :0
A X11 server is already running for display :0 on machine

# Hence, must run VNCServer on [virtual] screen 2
vncserver -localhost no :1

# View sessions
vncserver -list

# View logs
tail -f ~/.vnc/*.log

# Create service
vncserver -kill :1
sudo vim /etc/systemd/user/[email protected]

# Other folders include:
# Under Redhat, /usr/lib/systemd/system/ is for packages that want to install unit files. Under Debian and Ubuntu, the folder is /lib/systemd/system/.
# /usr/local/lib/systemd/system/ is for installing units by locally compiled packages

[Unit]
Description=TigerVNC server daemon
After=syslog.target network.target

[Service]
Type=forking
WorkingDirectory=%h

Restart=always
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=3

ExecStartPre=-/bin/sh -c '/usr/bin/vncserver -kill :%i > /dev/null 2>&1 || :'
ExecStart=/bin/bash -lc '/usr/bin/vncserver -localhost no -xstartup %h/.vnc/xstartup :%i'
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill :%i'

[Install]
WantedBy=default.target

# Register
systemctl --user daemon-reload
systemctl --user enable vncserver@1
systemctl --user start vncserver@1

# Monitor
journalctl --user -fu vncserver@1