Tips - X11 in an Embedded System - noVNC

Tips - X11 in an Embedded System - noVNC

noVNC is a VNC Client tool to connect to VNC server via Web Browser. And it can uses to connect on an graphic Embedded System.

  1. Features
  2. Browser Requirements
  3. Server Requirements
  4. Install some required packages
    1. Update and upgrade your OS
    2. Install X11 required packages
    3. Install VNC required packages
  5. Create a dedicated unix user
  6. Create noVNC password
  7. Create novnc.pem certificate
  8. X11 auto login
  9. Start Websockify to proxy [localhost:9000] on port [6080]
  10. Creating x11vnc system service
    1. First, it might be a good idea to copy the password file under /etc/
    2. Second, we have to create the service file ourselves:
  11. Proxying with nginx
    1. Configure nginx
  12. Proxying with lighttpd
    1. Configure lighttpd


  • Supports all modern browsers including mobile (iOS, Android)
  • Supported VNC encodings
  • Supports scaling, clipping and resizing the desktop
  • Local cursor rendering
  • Clipboard copy/paste

Browser Requirements

noVNC requires a browser with HTML5 support, this means it works on all major browsers. noVNC uses many modern web technologies so a formal requirement list is not available. However these are the minimum versions we are currently aware of: Chrome 49, Firefox 44, Safari 11, Opera 36, IE 11, Edge 12.

Server Requirements

noVNC follows the standard VNC protocol, but unlike other VNC clients it does require WebSockets support. Many servers include support (e.g. x11vnc / libvncserver, QEMU, and MobileVNC), but for the others you need to use a WebSockets to TCP socket proxy.

Install some required packages

Update and upgrade your OS

sudo apt update ; sudo apt upgrade

Install X11 required packages

sudo apt install xserver-xorg-video-qxl xinit slim jwm

Install VNC required packages

sudo apt install x11vnc novnc
  • xserver-xorg-video-qxl : This package provides the driver for QXL video device, i.e. if Linux is running inside a RedHat Enterprise Virtualization (RHEV) environment, or other SPICE-compatible KVM/Qemu emulator.
  • xinit : xinit and startx are programs which facilitate starting an X server, and loading a base X session.
  • slim : slim aims to be light, simple and independent from the various desktop environments.
  • jwm : very small lightweight pure X11 window manager with tray and menus. Low resource Window manager ideal for older PCs. It uses a minimum of external libraries, thus very little memory, includes virtual screens, menubar and root-menu popup.
  • x11vnc : x11vnc allows one to view remotely and interact with real X displays with any VNC viewer. It has built-in SSL encryption and authentication, UNIX account and password support, server-side scaling, single port HTTPS and VNC.
  • noVNC : noVNC is a HTML5 VNC (WebSockets, Canvas) with encryption (wss://) support client that runs well in any modern browser including mobile browsers (iOS and Android).

Create a dedicated unix user

sudo useradd <noVNC_user>

With <noVNC_user> user dedicated for login to noVNC

Create noVNC password

Login as a user <noVNC_user> who runs vnc. Create a password to connect using vnc viewer from the client system.

x11vnc -storepasswd
Enter VNC password: *********
Verify password: *********
Write password to /home/<noVNC_user>/.vnc/passwd?  [y]/n y
Password written to: /home/<noVNC_user>/.vnc/passwd

Create novnc.pem certificate

openssl req -x509 -nodes -newkey rsa:2048 -keyout novnc.pem -out novnc.pem -days 365

X11 auto login

Edit /etc/slim.conf

sudo vi /etc/slim.conf

In the file, uncomment the line starting with #default_user (remove the hash) and add the NAME (<noVNC_user>) of the default user

And put yes in auto_login directive

Start Websockify to proxy [localhost:9000] on port [6080]

websockify -D --web=/usr/share/novnc/ --cert=/home/<noVNC_user>/novnc.pem 6080 localhost:9000
WebSocket server settings:
  - Listen on :6080
  - Flash security policy server
  - Web server. Web root: /usr/share/novnc
  - SSL/TLS support
  - Backgrounding (daemon)

The script check status and start the web socker if is down.

You can chech it every 15th minute in the crontable sush as :

##  novnc    ##
*/15 * * * *		/<path>/ >/dev/null 2>&1

Creating x11vnc system service

First, it might be a good idea to copy the password file under /etc/

sudo mv ~/.vnc/passwd /etc/x11vnc.passwd

This also ensures the ownership to root and his rw access, as confirmed by:

sudo ls -la /etc/x11vnc.passwd
-rw------- 1 root root 8 Feb 15 17:02 /etc/x11vnc.passwd

Second, we have to create the service file ourselves:

sudo vi /etc/systemd/system/x11vnc.service
Description=Start x11vnc at startup.

ExecStart=/usr/bin/x11vnc -auth /var/run/slim.auth -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.passwd -rfbport 9000 -shared


Disclaimer: The man page is quite lengthy, and maybe I’ve made some serious, e.g. security mistake. Use on your own risk.

sudo systemctl enable x11vnc.service
sudo systemctl daemon-reload

Note : For Raspberry pi :

  • In /etc/systemd/system/x11vnc.service file change -auth /var/run/slim.auth by -auth /var/run/lightdm/root/:0
  • Without a monitor attached you must setting hdmi_force_hotplug=1 in /boot/config.txt. So it always thinks that an HDMI monitor is attached.

and you may simply reboot the server.

Proxying with nginx

Configure nginx

  • Step 1 : Upstream IP + port to the websocketproxy server

Edit your nginx subdomain (or domain) config file in /etc/nginx/sites-enable/ folder. Thereafter, represents the (sub)domain where noVNC will live at.

Edit /etc/nginx/sites-enable/ and add the line below at the beginning.

upstream vnc_proxy {
  • Step 2 : A path to /websockify to proxy the websocket connection
server {
    listen 80; # consider using 443, see below
    location /websockify {
          proxy_http_version 1.1;
          proxy_pass http://vnc_proxy/;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";

          # VNC connection timeout
          proxy_read_timeout 61s;

          # Disable cache
          proxy_buffering off;

As seen above, it is recommended to set a proxy_read_timeout greater than 60 seconds which is the default value. If not set you can end up in a race-condition which could cause a disconnection after inactivity longer than a minute. To avoid unnecessary caching of the VNC stream proxy_buffering should be set to off.

  • Step 3 : A path to your base URL, where you want it to show up

location /vncws {
    index vnc.html;
    alias </path/to/noVNC/>;
    try_files $uri $uri/ /vnc.html;


With this config, you can point your browser to to use noVNC.

  • Step 4 : Test new nginx configuration et restart
# Test configuration file for syntax errors by typing
sudo nginx -t

# reload Nginx to make the necessary changes
sudo systemctl reload nginx

noVNC, X11, screenshot

noVNC sceenshot

Proxying with lighttpd

Configure lighttpd

  • Step 1 : websocket tunnel to VNC server via noVNC client

If noVNC files are installed in /usr/share/novnc, and x11vnc is running as VNC server with x11vnc then lighttpd mod_wstunnel can be configured with this novnc.conf file in /etc/lighttpd/conf-enabled/ directory:

# file: "/etc/lighttpd/conf-enabled/novnc.conf"
alias.url = ( "/x11/" => "/usr/share/novnc/" )

server.indexfiles = ("index.html")
server.modules += ( "mod_wstunnel" )
$HTTP["url"] =~ "^/websockify" {
    wstunnel.server = ( "" => ( ( "host" => "", "port" => "9000" ) ) )
    # (optional, but recommended settings with noVNC)
    wstunnel.frame-type = "binary"  = 2 = 2

Please take proper precautions to limit access to the VNC server, possibly including requiring proper authentication and limiting access to certain source IPs.

  • Step 2 : Test new lighttpd configuration et restart
# Test configuration file for syntax errors by typing
lighttpd -p -f /etc/lighttpd/lighttpd.conf

# reload Nginx to make the necessary changes
sudo systemctl reload lighttpd

With this config, you can point your browser to to use noVNC.

Share it :