Connecting to static VNC server

I have a dedicated node for VNC work and would like to connect to it through VNC but all the instructions suggest we should make VNC available on the compute nodes which we dont really want to do. Any tips how to approach this? Also we have set VNC to be available via xinetd on this dedicated node so we have a static port users can connect to so users do not need to run vncserver themselves. Is this possible to use? Looking at the VNC template Ruby code it seems some fundamental changes may be needed.

Otherwise great piece of work - have Jupyter and Rstudio working with some changes to how it submits on our system. Good job everyone!

Maybe try to use the Linux Host Adapter for this?

Thanks. That was my thinking. I will have to experiment to see how it can be integrated. The dependency between noVNC, Websockify and VNC servers I am still trying to get my head round.

@tomgreen66 There’s a lot of moving parts around VNC in OnDemand, but you can skip most of it to get this done because at the end of the day noVNC is configurable on the client side through query parameters. If you have VNC available via xinetd that handles authentication for you, then you could add a button somewhere on the Interactive Apps page that links to noVNC.

Take a look at how we redirect users to noVNC: https://sourcegraph.com/github.com/OSC/ondemand/-/blob/apps/dashboard/app/helpers/batch_connect/sessions_helper.rb#L184

A URL is built and the user is redirected to the noVNC client which is a static asset:

"/vnc.html?autoconnect=true&password=#{password}&path=rnode/#{connect.host}/#{connect.websocket}/websockify&resize=#{resize}"

A short technical dive into the relationship between noVNC, WebSockify and VNC:

  1. User launches a VNC session and this shell script is executed on the remote node: https://sourcegraph.com/github.com/OSC/ood_core/-/blob/lib/ood_core/batch_connect/templates/vnc.rb#L83

A few things happen here, a password is generated and used to build the URL #{password}, and the port the VNC server started on is found:

# Parse output for ports used
display=$(echo "${VNC_OUT}" | awk -F':' '/^Desktop/{print $NF}')
port=$((5900+display))
  1. After the VNC server has started, WebSockify is booted up: https://sourcegraph.com/github.com/OSC/ood_core/-/blob/lib/ood_core/batch_connect/templates/vnc.rb#L127

A random port is allocated for the WebSocket connection and WebSockify is started. Then a watchdog process is started that watches VNC log files for successful authentication requests and once detected, resets the VNC password for use on the next successful connection (this is a hacky OOD specific process, we’re working on improving internal authentication)

So what purpose does WebSockify serve? It’s a simple TCP proxy that talks over WebSockets, it allows for this data flow to be possible:
Browser <-> noVNC (Remote Frame Buffer) <-> WebSocket <-> WebSockify <-> underlying VNC server

noVNC is responsible for most of the magic, it’s implements the VNC protocol for you through JavaScript.

But since you have a VNC server running already then you only need to spawn WebSockify processes. I think in combination with the Linux Host Adapter, this can be done easily.

Here’s a snippet from the startup script that you could use (the bash script finds a random port, and WebSockify is started in daemon mode):

websocket=$(find_port)
#{websockify_cmd} -D ${websocket} localhost:${port}

If you’re interested in learning more about the internals of WebSockify, I recommend looking at the source https://github.com/novnc/websockify. We use novnc/websockify at OSC.

I ported WebSockify to Golang which might be easier to understand (you can spin up the batteries included Docker image): https://github.com/msquee/go-websockify

Thanks for the detailed response. I think the most confusing thing is there are multiple locations where content is written so not sure where startup script is defined (reading documentation on Interactive desktop isnt clear for Linux host adapter. Seems some stuff can go into /etc/ood/clusters.d/vnc.yml where I can specify the linux_host adapter and then in batch_connect vnc settings e.g.
batch_connect:
basic:
script_wrapper: |
module purge
module load tmux
%s
vnc:
script_wrapper: |
module purge
module load tmux

Or I can write code in /etc/ood/config/apps/bc_desktop where I currently just have a file vnc.yml:

title: Hawk Login VNC desktop
description: This launches a VNC desktop on a Hawk VNC server.
cluster: vnc
form:
- desktop
- bc_num_hours
attributes:
bc_num_hours:
value: 1
desktop: “dummy”

So trying to fit this altogether where the actual startup script goes. I tried putting it first into the cluster file /etc/ood/clusters.d/vnc.yml under the batch connect vnc location but not add %s since I already setup the vncserver but I get an error about find_port not found. Tried hardcoding it to a port number and then couldnt get it to change at all and kept using an old version of the script where find_port is used. Maybe a clear head is needed in the morning but hitting my head against the keyboard at the moment. Thanks again - made some progress tonight.