Although most Linux cloud server administration is done over the command line, there may be cases where you want to run a graphical desktop on your server that interacts with your local keyboard and mouse. VNC (Virtual Network Computing) allows you to manage your Linux server through a familiar graphical interface.
In this article, we’ll install and set up a lightweight VNC server package, TightVNC, that is suitable even for slower internet connections, and then create a secure tunnel to that VNC server using SSH.
To follow this guide, you will need the following:
- A Debian 9 server, and a server user with root privileges
- A VNC client that supports VNC connections performed over SSH tunneling. For Mac OSX, you can use the built-in Screen Sharing application (other alternative applications are also available). For Windows, options include the TightVNC client.
- Firewall rules, if any are configured on your Debian server, must permit inbound traffic on port 5901
Step 1: Install the graphical desktop packages
Linux offers a variety of different desktop environments, such as XFCE, Unity, and Gnome. This article will guide you through installing XFCE as the desktop that you will use to connect VNC from a remote location. Run the following commands to install XFCE on your Debian server:
apt install xfce4 xfce4-goodies
Next, install the TightVNC server package:
apt install tightvncserver
Step 2: Create a VNC user on your server
To keep in line with security best practices, you should have SSH login to your server as the root user disabled and instead log in remotely through other users that have sudo privileges. For this exercise, we’ll also create a new user with sudo permissions that can access the VNC server remotely.
Create the new user and set its server password with the following commands:
sudo useradd -m -s /bin/bash myvncuser sudo passwd myvncuser
Next, add your new user to the sudo group to grant root privileges:
sudo usermod -a -G sudo myvncuser
And finally, log in as your new user and use its root privileges to begin working with the VNC server:
su - myvncuser
Step 4: Run VNC server to create first-time setup files
From this point onward, since we’ll be running commands on the server and on the local machine, the location where the command is being run will be displayed in front of the shell prompt (the ‘$’ character). For this exercise, the Cloud Server name is lucky-puffin-86.
Run the first-time VNC server initialization for your user with the following command:
The screen output walks you through setting a VNC-specific password (limited to 8 characters), then you’re prompted on whether you wish to create a view-only password. The view-only password is used to provide a user with a shared screen view, but they will not be able to control the mouse or keyboard:
You will require a password to access your desktops. Password: Warning: password truncated to the length of 8. Verify: Would you like to enter a view-only password (y/n)? y Password: Warning: password truncated to the length of 8. Verify: xauth: file /home/myvncuser/.Xauthority does not exist xauth: (argv):1: bad display name "lucky-puffin-86:1" in "add" command xauth: file /home/myvncuser/.Xauthority does not exist New 'X' desktop is lucky-puffin-86:1 127.0.0.1 localhost Creating default startup script /home/myvncuser/.vnc/xstartup Starting applications specified in /home/myvncuser/.vnc/xstartup Log file is /home/myvncuser/.vnc/lucky-puffin-86:1.log
Step 5: Configure the VNC startup settings
Now that we’ve started VNC server for the first time, some basic configuration files were created. We also want to set some commands to be run automatically every time vncserver starts up.
First, stop the running VNC server process:
vncserver -kill :1
Notice the :1 that we’re specifying here. VNC runs on server port 5901 by default, which is noted as :1 when working with vncserver in the command line. VNC can be run on multiple display ports, which would be 5902 labeled as :2, 5903 as :3, as so on.
Next, create a backup of its default startup script file:
mv ~/.vnc/xstartup ~/.vnc/xstartup.bak
Now use vim (or your favorite text editor) to create a new xstartup file:
Paste the following 3 lines of text into your new file:
#!/bin/bash xrdb $HOME/.Xresources startxfce4 &
Be sure to save your new xstartup file. The first command tells VNC server to refer to the .Xresources associated with that user. This file determines some of the graphical settings for the desktop environment, but for this exercise, we won’t be making any changes to it. The second command tells the VNC server to run XFCE, the desktop environment we installed in the first step.
Since we’re calling for the VNC server to run other commands from its startup, grant executable privileges to your new startup file with the following command:
sudo chmod +x ~/.vnc/xstartup
Step 6: Restart VNC server
Now that configuration is complete, start the VNC server again. The command and output will resemble the following:
myvncuser@lucky-puffin-86:~$ vncserver New 'X' desktop is lucky-puffin-86:1 Starting applications specified in /home/myvncuser/.vnc/xstartup Log file is /home/myvncuser/.vnc/lucky-puffin-86:1.log
Now we’re finished with configuration, and you’re ready to connect to your server’s graphical desktop remotely.
Testing your connection
To test your connection to your new server desktop environment, we need to create an SSH tunnel that will be forwarded to the VNC server’s localhost connection. For Linux and OSX local machines, you can set this up using the terminal. For Windows local machines, this can be set up by using the SSH tunnel options for your chosen SSH client (most likely, this will be PuTTY).
Step 1: Set up a secure SSH tunnel between your local machine and the server
Set up a secure SSH tunnel by running the following command on your local machine (you can open up a new window or tab in Terminal, for example). Replace server_ip with the IP address of your Cloud Server:
mylaptop:~ me$ ssh -L 5901:127.0.0.1:5901 -N -f -l myvncuser server_ip
You will be prompted to enter the vnc user’s server password that we previously set up during Installing VNC, step 2.
Step 2: Use your VNC client to connect to the desktop
Using a VNC client such as Mac OSX’s built-in Screen Sharing or any other client mentioned here, you can now connect to localhost:5901. You will be prompted to enter the vncserver password (not the same as the user’s server password unless you made them identical). The tunnel we set up in step 1 should now connect you to the server’s desktop environment:
Set TightVNC to run as a service
We’ve left things in such a way that you’ll have to log in to the command line and manually start vncserver each time the server restarts. To set your VNC server to run at startup (and to make it easier to start and stop in general), we can configure the server to run tightvnc as a systemd service.
If you’re unfamiliar with systemd, it can be used to control a number of different server resources — in our case, a service we’re going to tie to vncserver — through something called a unit file.
One more time, let’s stop the VNC server so we can change configuration files:
vncserver -kill :1
Now create a new systemd unit file with the following command:
sudo vim /etc/systemd/system/vncserver@.service
Copy and paste the following configuration into the file, replacing myvncuser with your desired username:
[Unit] Description=Start TightVNC server at startup After=syslog.target network.target [Service] Type=forking User=myvncuser Group=myvncuser WorkingDirectory=/home/myvncuser PIDFile=/home/myvncuser/.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
Again, be sure to save when you exit your text editor. Next, run the following two commands to have systemd detect and use the new resource:
sudo systemctl daemon-reload sudo systemctl enable email@example.com
Now use systemd to start VNC server. Notice the ‘@1’ suffix used in these commands, this is referencing which display port should be used, in our case :1.
sudo systemctl start vncserver@1
If everything is configured properly, the terminal won’t receive any text output. You can always check on the status of systemd services like so, especially if you ran into any error messages or problems:
sudo systemctl status vncserver@1
When it starts correctly, vncserver should look similar to the following when checking it using systemctl status:
$ sudo systemctl status firstname.lastname@example.org ● email@example.com - Start TightVNC server at startup Loaded: loaded (/etc/systemd/system/vncserver@.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2019-11-21 16:59:14 UTC; 11min ago Process: 24157 ExecStartPre=/usr/bin/vncserver -kill :1 > /dev/null 2>&1 (code=exited, status=2) Process: 24161 ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 :1 (code=exited, status=0/SUCCESS) Main PID: 24169 (Xtightvnc) Tasks: 107 (limit: 1161) Memory: 168.3M
Congratulations on your new server GUI, and happy clicking!