Running remote GUI apps with the infinite power of the cloud.
Tags: aws, gis, gui, vnc
Published: 2022-09-20 09:42:48

---
title: Running remote GUI apps with the infinite power of the cloud.
published: true
description: Remote development is a revolution, but how can we run our demanding GUI apps in AWS?
tags: AWS, GIS, GUI, VNC
cover_image: https://live.staticflickr.com/4137/4821228934_5841eaf12b_b.jpg
---

Remote development environments allow us to shift our computing needs to the infinite processing and high bandwidth offered by the cloud. It creates a shared, collaborative space that's close to our production environment. The growing toolchain around them is an exciting part of a new developer experience. But I'd never used it with a GUI app until now.

The below takes about 10-15minutes, and you get a remote, powerful desktop environment ready to run whatever Linux GUI tool you need; scientific research, 3D modelling, or just renting a faster computer for a while.

[QGIS](http://qgis.org) is a tool to help load, analyse and visualise geospatial data. But they don't have a build for my M1-based Mac; plus, I want to load a lot of data into it.

![GeoSpatial layers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zl7fbn5roxe4fhx6snb8.png)

I'd turn to [VSCode remote development](https://code.visualstudio.com/docs/remote/remote-overview) or a [SageMaker Studio](https://aws.amazon.com/sagemaker/studio/) Notebook for command line or scripting work. For a GUI app, I need to add a desktop environment to Ubuntu and access that through VNC.

### Start with an Ubuntu 22.04 EC2 instance.
I've used [CDK](https://aws.amazon.com/cdk/) to spin this up, but go with the console, the AWS CLI, or whatever is comfortable for you.

```
instance = ec2.Instance(self, "DevInstance",
    instance_type=ec2.InstanceType('t3.micro'),
    machine_image=ec2.MachineImage.generic_linux(
        {'eu-west-1': 'ami-0d75513e7706cf2d9'}
        # The above is Ubuntu22.04 in the Ireland region
        # If you use another region, you'll want to find
        # the AMI for your region
    ),
    block_devices=[
        ec2.BlockDevice(
	    device_name="/dev/sda1",
	    volume=ec2.BlockDeviceVolume.ebs(
        )
    ],
    vpc=ec2.Vpc.from_lookup(self, "VPC", is_default=True)
)
instance.role.add_managed_policy(
    policy=iam.ManagedPolicy.from_aws_managed_policy_name(
        "AmazonSSMManagedInstanceCore"
    )
)
CfnOutput(self, "InstancePublicIp",
    value=instance.instance_id,
)
```

### Gain CLI access to the EC2 instance.
I'm using AWS's SSM Session Manager, so I don't need to worry about ssh keys or opening ports.

```
aws ssm start-session --target $AWS_INSTANCE_ID
```

### Install a desktop environment and a VNC server.
I'm using Tiger VNC and securing it with a password. Do this as the ubuntu user

```
sudo su
su ubuntu
	
sudo apt update
	
sudo apt install -y \
    xfce4 xfce4-goodies \
    tigervnc-standalone-server tigervnc-common tigervnc-tools

```

You'll now need to do a "first run" of the vnc server to do some initial configuration - like setting a password:

```
vncserver
```

This will prompt you to create a password and optionally create a "view only" password so that user can only view. I didn't set a view only, you probably don't need that either.

We can now continue with the setup of the VNC server:

```
cat > /home/ubuntu/.vnc/xstartup<< EOF
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
/usr/bin/startxfce4
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
x-window-manager &
EOF
	
chmod u+x /home/ubuntu/.vnc/xstartup

echo ':1=ubuntu' | sudo tee -a /etc/tigervnc/vncserver.users

sudo systemctl start tigervncserver@:1.service
sudo systemctl enable tigervncserver@:1.service
```

### Allow access to port 5901 on the server.
I've used SSM Session Manager to create a tunnel. This way, localhost:5901 tunnels across to remote:5901; saving me from opening that port in AWS and making everything more secure.

```
aws ssm start-session --target  $AWS_INSTANCE_ID \
    --document-name AWS-StartPortForwardingSession \
    --parameters \
    '{"portNumber":["5901"], "localPortNumber":["5901"]}'
```

### Open a VNC client connection.
macOS comes with one! [Or, download a VNC client for your machine](https://www.realvnc.com/en/connect/download/viewer/windows)

In the Mac's finder, use the "Go" menu, select "Connect to server" (or press command-K), and add the VNC connection path:

```
vnc://127.0.0.1:5901
```

![macOS VNC Connection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/srecjm1et1zwgxl7wrdi.png)

Now, I have the desktop environment of that Ubuntu server in a window on my local Mac. I can install QGIS on that server or whatever GUI app I want. That remote machine has an ultra-fast network connection and only needs to stream the (low bandwidth) screen activity down my network connection. I can keep costs down by using a small AWS instance, or if I need to load more data, I can have up to 24TB of RAM and hundreds of CPUs! My lowly laptop can really be a wolf in sheep's clothing.