How to setup a virtual desktop on Kubernetes in 15 minutes

yannick misteli
DevOps Dudes
Published in
6 min readJan 12, 2021

Ever since VNC (Virtual Network Computing) was invented in the early 2000s at the Olivetti & Oracle Research Lab it sparked some fascination and acted as precursor of the merits of cloud computing we all enjoying nowadays. Furthermore, the advent of containerization brought much flexibility in deploying solutions in a consistent manner, giving the ability to run your code basically anywhere. So, all the components that we need in order to setup our own graphical remote desktop container are out there which gives us the flexibility to scale (adopting hardware requirements or simply scaling up and down) our remote server according to our needs. Still, having a graphical desktop that is either required by programs or users ultimately is extremely useful.
Hence, in this short article I wanted to demonstrate how to setup your personal virtual desktop on a Kubernetes cluster with a minimal setup. Kubernetes provides us with an easy way to deploy our virtual desktop solution and could also be used to host multiple servers for a team. It is also extremely flexible in adopting our hardware needs — in our case the Kubernetes cluster is very close to the other cloud infrastructure components and therefore also gives additional benefits.
However, beyond that I won‘t argue on why this is particularly useful since it is purely a technical proof of concept at that stage but having a fully fledged xfce desktop on my iPad on the go seems pretty cool - so let me share it with you.

iPad with xfce access on the go

The structure of the article is divided into two parts, the first part figuring out the docker image structure (Dockerfile) and the second part to deploy it on a Kubernetes cluster. Therefore a basic understanding of containerization and writing Dockerfiles will help to grasp the first section. For the deployment part, I tried to make it as minimalistic as possible. So basic Kubernetes concepts like pods & deployments of course will help but are not a precondition — however, of course an access to a Kubernetes cluster is needed (and kubectl setup appropriately) in order to deploy the container.

Getting the Dockerfile right — the difficult part

As a base Image we are going to use ubuntu since most readers will be familiar with the operating system and handling of installing packages and configurations. The first few commands are only installing dependencies and the xfce desktop environment. Since xfce aims to be fast and lightweight while still being visually appealing and easy to use it is a good choice for our virtual desktop solution.

For the remote desktop connectivity the decision was to go with google‘s chrome-remote-desktop application since, also there, the goal was to have a lightweight solution with minimal configuration and setup overhead. Additionally, it should be native to all devices and not require any additional software to be installed on either laptop, iPad or phone to access the virtual desktop. As an alternative, if you would like to keep everything open source, then Guacamole would be a nice solution to have a deeper look into.

google remote desktop setup

If you have never worked with chrome-remote-desktop, the process is fairly straightforward: 1) go to remotdesktop.google.com/headless 2) Press Begin 3) Click Next 4) Click Authorize 5) copy the access code to register your virtual desktop

As you can see in line 45 of the Dockerfile, the verification-code is used to register the container as one of your remote desktops (the code is valid once and only valid for a couple of minutes). Please also specify a PIN that protects the access to the remote desktop (also used in the RUN command at line 45)

Now, one of the tricky aspects is the hostname which is also set as an environment variable. Chrome-remote-desktop uses the current hostname in the setup process — but if you are building the container with docker build your hostname takes on a random hash (and you can not set it at that stage) and hence we need to make sure that the „final“ hostname can read from the correct configuration file. In order to do so we copy the json file (.config/chrome-remote-desktop/host#${HOSTNAME_HASH}.json) that was generated to the new filename (which is then used as configuration by the „new“ hostname) location.

code reverse engineering

Unfortunately there is no documentation on that for chrome-remote-desktop, but one could see that there is some kind of md5 hashing for the file name and hence we „reconstruct“ that filename convention for our new hostname through some shell commands (line 48) and indeed this does the trick! (good old reverse engineering)

The remaining steps that I skipped were the creation of an end-user and adding that user to both, the chrome-remote-desktop group and sudoers. There are probably more elegant solutions for that but just adding the NOPASSWD line to the sudoers configuration does work for now.

Ultimately, we also needed a little workaround for the CMD line where „sleep infinity & wait“ was added in order to keep the virtual desktop running on the Kubernetes cluster.

Summarizing, change the user and hostname variable in the Dockerfile and also copy and paste the authorization code from the chrome-remote-desktop process and change the PIN you would like to use accordingly. Either saving the changes in the file or you can specify the arguments directly (preferred option) and run:

docker build --pull -t myvirtualdesktop \
--build-arg USER=myuser \
--build-arg PIN=271828 \
--build-arg CODE=4/1AY2e-g4KM-JyQgALDqxIcTTO8ZGcHt-0FJb_wJACFZ_SVJdFNAzU6_qoQv_vEAcENw-sww \
--build-arg HOSTNAME=myvirtualdesktop .

(or whatever you want to name the container)

Deploying to your Kubernetes cluster — the simple part

As a first step the container needs to be pushed to a registry. A private Dockerhub repo or any other service will do. Since our infrastructure is AWS based we will be using ECR as an example here. Therefor we login to ECR:

aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ACCOUNT.dkr.ecr.$REGION.amazonaws.com

Then tag our container appropriately

docker tag myvirtualdesktop \ $ACCOUNT.dkr.ecr.$REGION.amazonaws.com/myvirtualdesktop

And push the container (a repository needs to exist with that name):

docker push $ACCOUNT.dkr.ecr.$REGION.amazonaws.com/myvirtualdesktop

Now, assuming that kubectl is configured appropriately then deploying to the Kubernetes cluster is fairly simple.

First, the pod.yaml file should be adopted and the names changed to match the hostname specified in the Dockerfile in the previous section and the image should point to the uploaded container (repo).

In case you want a beefier virtual desktop also change the limits and request of the cpu and memory specifications.

After that executing:

kubectl apply -f pod.yaml

Kubernetes will deploy a pod with the specified container in the default namespace. Keep in mind that this is a very minimalistic setup, hence feel free to adopt to a more advanced version.

Lastly, you can go to https://remotedesktop.google.com/access and simply connect to your virtual desktop instance that should be running on your Kubernetes cluster.

virtual desktop running in the Chrome browser window

Alternatively, it’s worth mentioning that google cloud run or AWS fargate might be some great alternatives in case you don’t have a Kubernetes cluster up and running and quickly want to deploy your virtual desktop container in the cloud.

Feel free to reach out on LinkedIn or here if you have questions or suggestions.

Enjoy and happy new year.

--

--