Even though macOS has an excellent command-line environment, we sometimes need to run a real Linux system. Multipass is an excellent way to run Ubuntu on macOS (or Windows, for that matter) but it doesn't easily support running a Linux desktop. In this article we demonstrating setting up a VNC server on a Multipass Ubuntu instance, and displaying it on the macOS desktop using a VNC viewer. The same techniques should work on Windows, and even with a remote Ubuntu VPS on a cloud hosting provider.
VNC is a system for remotely accessing desktop GUI sessions from another computer. The VNC display protocol runs across the network, and allows a client program (the half that displays the remote desktop) to connect to a VNC server (the half that creates the remote desktop). There are several vendors making both VNC server and VNC client programs.
A common case for VNC is when one has installed a computer at a remote site, and to be able to manage that computer without driving to the site. You instead ensure the computer is on the Internet, then use VNC to access its desktop.
In this case we're aiming to use VNC to control an Ubuntu Linux desktop running in a virtual machine managed by Multipass. The same instructions will work for any Ubuntu instance such as a VPS rented from a web hosting provider. I'll make sure to intersperse comments on how to implement this for a remote Ubuntu instance on a VPS provider.
While many of the open source Linux GUI programs are also available for macOS, some are not. Therefore it is sometimes useful to be able to use a Linux desktop even if your primary computer is running macOS - or Windows for that matter.
I wrote an earlier article about running a single application and displaying on XQuartz, the X11 server for macOS. This article differs in that we're looking to run a whole desktop UI rather than a single application. For that article see Use Canonical's Multipass to display Linux GUI applications on macOS desktop
Setting up a Multipass virtual machine
For more details on what Multipass is, and an introduction, see: Use Canonical's Multipass to display Linux GUI applications on macOS desktop
Run this to launch a Multipass/Ubuntu instance
$ multipass launch --name vncxfce4
Launched: vncxfce4
This command launches the default Ubuntu image, at the time of this writing that is Ubuntu 18.04. The name for the image will be vncxfce4
because we will configure this image to run VNC and the XFCE4 desktop.
There are a number of commands to customize this, such as increasing the memory allocation.
Once it launches you can run this to start a Bash shell inside the instance:
$ multipass shell vncxfce4
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-96-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Fri Apr 17 08:53:09 PDT 2020
...
ubuntu@vncxfce4:~$
If instead you are using a different Ubuntu instance like a remote VPS, simply launch that instance in the appropriate way. In either case you'll have an Ubuntu system to work with.
As is typical we then update the system:
ubuntu@vncxfce4:~$ sudo apt update
...
ubuntu@vncxfce4:~$ sudo apt upgrade
...
These commands will be the same irregardless of what kind of Ubuntu instance you have. They cause an update of information about packages, and updates any packages that are currently out of date.
Installing VNCServer and Xfce4 inside Multipass
Now that the system is set up we can proceed to setting up VNC and a desktop environment. For the desktop environment we are installing Xfce4 because it is light weight.
The commands in this section will be the same irregardless of where the Ubuntu instance is running, whether it is inside Multipass or a remote server.
$ sudo apt install xfce4 xfce4-goodies tightvncserver
We'll be able to, later, install a whole slew of other Linux GUI programs. But this will give us a good start.
When I ran this it installed well over 500 packages, so expect this to take awhile.
Once all that is installed we can run vncserver
once to initialize the configuration files.
ubuntu@vncxfce4:~$ vncserver
You will require a password to access your desktops.
Password:
Verify:
Would you like to enter a view-only password (y/n)? n
xauth: file /home/ubuntu/.Xauthority does not exist
New 'X' desktop is vncxfce4:1
Creating default startup script /home/ubuntu/.vnc/xstartup
Starting applications specified in /home/ubuntu/.vnc/xstartup
Log file is /home/ubuntu/.vnc/vncxfce4:1.log
ubuntu@vncxfce4:~$
ubuntu@vncxfce4:~$ vncserver -kill :1
Killing Xtightvnc process ID 15560
This does initial setup, giving the VNC session a password, and so forth.
It set up a not-very-useful desktop environment, however, so we need to kill the VNC server to edit the startup script.
Next use your favorite text editor to edit ~/.vnc/xstartup
$ nano ~/.vnc/xstartup
The result will be:
#!/bin/sh
xrdb $HOME/.Xresources
startxfce4 &
#xsetroot -solid grey
#x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#x-window-manager &
# Fix to make GNOME work
#export XKL_XMODMAP_DISABLE=1
#/etc/X11/Xsession
The commented-out lines is what vncserver
provided to us. The uncommented lines starts up the xrdb
server and the Xfce4 environment.
It is useful to make this file executable:
ubuntu@vncxfce4:~$ sudo chmod +x ~/.vnc/xstartup
The chmod
program changes permissions on files, and chmod +x
make a file executable.
Starting the VNC server for real inside Multipass
Now that we have the VNC environment configured to launch the Xfce4 desktop, it's time to take it for a spin for real.
ubuntu@vncxfce4:~$ vncserver
New 'X' desktop is vncxfce4:1
Starting applications specified in /home/ubuntu/.vnc/xstartup
Log file is /home/ubuntu/.vnc/vncxfce4:1.log
This launches VNC with the display number 1
. What this means is the client program must be instructed to connect with port 5901
on the host.
The other thing to determine is the IP address of the Multipass instance.
$ multipass list
Name State IPv4 Image
firefox Stopped -- Ubuntu 18.04 LTS
vncxfce4 Running 192.168.64.11 Ubuntu 18.04 LTS
This is run in the macOS command-line environment rather than inside the Multipass instance. We see that the vncxfce4
Multipass instance has the IP address shown here.
In this case we are getting the IP address from Multipass. If your Ubuntu instance is on some other service, like a remote VPS provider, then you'll be told an IP address by that service. Or maybe instead you'll be told a domain name, in which case you would use the domain name instead of the IP address.
Connecting a VNC client to the VNC server in the Multipass instance
On macOS there is a built-in VNC client that Apple wants us to use for Screen Sharing between macOS computers. It is a simple VNC client and the primary downside is that it does not support encryption.
In another tutorial, I wrote up how to implement VNC on a regular Linux/Ubuntu computer, turn off the encryption, and use the macOS Screen Sharing application to connect with that Ubuntu session. See: How to set up remote desktop on Ubuntu, access it from macOS
While we could probably configure this vncserver
installation to turn off encryption, let's instead look at using a VNC client that supports encryption.
The VNC server we installed is actually tightvncserver
and the team behind this server also has a Java client that will work. See
the TightVNC website for information.
One navigates to the Download page, and downloads the TightVNC java Viewer JAR in a ZIP Archive package. As of this writing that is marked Version 2.8.3.
There is also documentation on this, but that documentation seems to be incorrect.
To run the VNC client:
$ java -jar ~/Downloads/tvnjviewer-2.8.3-bin-gnugpl/tightvnc-jviewer.jar
Apr 17, 2020 11:39:56 AM com.glavsoft.viewer.Viewer <init>
INFO: TightVNC Viewer version 2.8.3
Running this we get:
We enter the IP address, or the domain name, for the Remote Host and because the session is on VNC server 1, we enter 5901
as the port number.
After entering the password, we connect like so:
We have a full Xfce4 session running on a Multipass instance on our laptop. Very good. The only problem with this is it is slow.
Apple's Screen Sharing surprisingly works
I wanted to record the error message when Screen Sharing failed to connect, but it just worked. Plus, the Screen Sharing app has better performance than the TightVNC Java client.
To access Screen Sharing, click on the Spotlight icon in the toolbar and enter Screen Sharing. It will show you the Screen Sharing.app icon, and you double-click on it to launch the application.
Then you enter the host connection parameters. Click on Connect and you'll be shown a password dialog. After which it will connect, and we can see this:
To prove that both clients work, we have the TightVNC Java client on the left, and Apple's Screen Sharing on the right. The latter gives much better performance.
Setting up VNCServer as a Service on Ubuntu
That's fine to set this up on an ad-hoc basis. But what if we want to have this image as a dedicated Xfce4 environment we can launch and go with at any time? Therefore we want the VNC Server to automatically launch when the instance starts.
There is a file to create to describe a Service to Systemd, and then we tell Systemd to manage this service.
Let's create a new file, /etc/systemd/system/vncserver@.service
, using your favorite text editor:
$ sudo nano /etc/systemd/system/vncserver@.service
The file should contain:
[Unit]
Description=Start TightVNC server at startup
After=syslog.target network.target
[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu
PIDFile=/home/ubuntu/.vnc/%H:%i.pid
ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 :%i
ExecStop=/usr/bin/vncserver -kill :%i
[Install]
WantedBy=multi-user.target
This service description makes sense for the Multipass instance. That's because the login user name is ubuntu
and therefore this file shows that user name in several places. If your setup is different, substitute a different user name.
Then we have a series of commands to run:
ubuntu@vncxfce4:~$ sudo systemctl daemon-reload
This makes Ubuntu aware of the new service
ubuntu@vncxfce4:~$ sudo systemctl enable vncserver@1.service
Created symlink /etc/systemd/system/multi-user.target.wants/vncserver@1.service → /etc/systemd/system/vncserver@.service.
Then we enable the service. The 1
after the @
character is the display number to use.
ubuntu@vncxfce4:~$ vncserver -kill :1
Killing Xtightvnc process ID 1119
Then we need to kill the existing VNC server process.
ubuntu@vncxfce4:~$ sudo systemctl start vncserver@1
Then we start the installed VNCserver process.
ubuntu@vncxfce4:~$ sudo systemctl status vncserver@1
● vncserver@1.service - Start TightVNC server at startup
Loaded: loaded (/etc/systemd/system/vncserver@.service; indirect; vendor preset: enabled)
Active: active (running) since Fri 2020-04-17 12:42:41 PDT; 8s ago
Process: 1501 ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 :1 (code=exited, status=0/SUCCESS)
Process: 1487 ExecStartPre=/usr/bin/vncserver -kill :1 > /dev/null 2>&1 (code=exited, status=2)
Main PID: 1511 (Xtightvnc)
Tasks: 62 (limit: 1152)
And we can check the status.
It's important to also test that the VNC server does automatically start when the Multipass instance starts.
$ multipass stop vncxfce4
$ multipass start vncxfce4
The stop
command shuts down a Multipass instance. This is just like shutting down any Ubuntu computer, in that messages will be printed on logged-in terminals, and the VNC Client will disconnect.
If you're using the macOS Screen Sharing app, it will show a Reconnecting message while the instance is rebooting.
Once the instance is rebooted feel free to connect a VNC client again. Or, if you're using the Screen Sharing app, the client will automatically reconnect.
Ensuring encryption is enabled for VNC sessions over the public Internet
For a VNC session within our laptop encryption isn't so necessary. But for a VNC session running over the Internet, encryption is a very good idea.
There are paid VNC clients for macOS that support encryption and claim to have blazing fast performance. I don't know, since I haven't used those apps.
In case you wish to implement encryption, it is possible to use an SSH tunnel.
$ ssh -L 5901:127.0.0.1:5901 -C -N -l ubuntu YOUR-SERVER-IP-ADDRESS
This sets up a port 5901
on the local host (127.0.0.1
) that is connected via an SSH tunnel to the computer at YOUR-SERVER-IP-ADDRESS. It uses SSH to make this connection, and connects to the user name ubuntu
at that IP address (or domain name).
Needless to say you should supply password-less connection credentials. For example you should have previously set up an SSH key between the computers enabling you to login using SSH without a password. If the remote instance is an AWS EC2 instance, then you'll need to use the PEM key file supplied by AWS.
With the SSH tunnel, you tell the VNC client to connect with the VNC server at 127.0.0.1:5901
. SSH will take care of communicating data with the remote VNC server, and encrypting that data while it is traversing the Internet.
The SSH tunnel trick comes from How to Install and Configure VNC on Debian 9