Setup of a Guacamole HTML5 remote XFCE desktop via VNC for Ubuntu 24.04
Goal of this article is to document the setup of a Guacamole HTML5 remote XFCE desktop via VNC on Ubuntu 24.04.x. The Guacamole setup is based on Ubuntu 20.04.x LTS - Guacamole HTML5 Remotedesktop Gateway installieren mit Apache Reverse Proxy (in german, written by Bernhard Linz)
Install the guacamole server
So, let’s assume we have a fresh Ubuntu 24.04.x installation on a remote machine with DNS name test.example.org running a ssh server.
First, we become root:
sudo -iNext, we install everything that is needed to run the Apache Tomcat server. We’ll need tomcat9, since tomcat10 (that is the default for Ubuntu 24.04) is not compatible with Guacamole. So we have to add the respective repostitory first.
add-apt-repository -y -s "deb http://archive.ubuntu.com/ubuntu/ jammy main universe"
apt install make libssh2-1-dev libtelnet-dev libpango1.0-dev libossp-uuid-dev libcairo2-dev libpng-dev libvncserver-dev libvorbis-dev gcc libssh-dev libpulse-dev tomcat9 tomcat9-admin tomcat9-docs ghostscript libwebp-dev libavcodec-dev libavutil-dev libswscale-dev libjpeg-turbo8-dev libtool-bin libossp-uuid-dev libavformat-dev freerdp2-dev libwebsockets-dev libssl-devNow, on calling http://test.example.org:8080 we should see the standard Apache Tomcat “It works!” page.
As of July 2025, the current Guacamole version is 1.6.0, so we download the following files:
cd /usr/src
wget https://downloads.apache.org/guacamole/1.6.0/source/guacamole-server-1.6.0.tar.gz
wget https://downloads.apache.org/guacamole/1.6.0/binary/guacamole-1.6.0.warSo we have server source code and client binary.
Now we unpack the server code
tar xvzf guacamole-server-1.6.0.tar.gzand compile it:
cd /usr/src/guacamole-server-1.6.0
./configure --with-systemd-dir=/etc/systemd/systemThat should result in an output like this:
------------------------------------------------
guacamole-server version 1.6.0
------------------------------------------------
Library status:
freerdp ............. yes (2.x)
pango ............... yes
libavcodec .......... yes
libavformat ......... yes
libavutil ........... yes
libssh2 ............. yes
libssl .............. yes
libswscale .......... yes
libtelnet ........... yes
libVNCServer ........ yes
libvorbis ........... yes
libpulse ............ yes
libwebsockets ....... yes
libwebp ............. yes
wsock32 ............. no
Protocol support:
Kubernetes .... yes
RDP ........... yes
SSH ........... yes
Telnet ........ yes
VNC ........... yes
Services / tools:
guacd ...... yes
guacenc .... yes
guaclog .... yes
FreeRDP plugins: /usr/lib/x86_64-linux-gnu/freerdp2
Init scripts: no
Systemd units: /etc/systemd/system
Type "make" to compile guacamole-server.If that’s the case as all “yes”-entries are present, we can compile:
make
make installLast we have to configure the dynamic linker run-time bindings:
ldconfigNow we can start the systemd service that the installation has provided:
systemctl start guacd.service
systemctl status guacd.servicewhich should give us an output like
● guacd.service - Guacamole Server
Loaded: loaded (/etc/systemd/system/guacd.service; disabled; vendor preset: enabled)
Active: active (running) since Fri 2023-04-21 14:52:28 UTC; 6s ago
Docs: man:guacd(8)
Main PID: 47807 (guacd)
Tasks: 1 (limit: 2233)
Memory: 10.2M
CPU: 10ms
CGroup: /system.slice/guacd.service
└─47807 /usr/local/sbin/guacd -f
Apr 21 14:52:28 test181 systemd[1]: Started Guacamole Server.
Apr 21 14:52:28 test181 guacd[47807]: Guacamole proxy daemon (guacd) version 1.5.1 started
Apr 21 14:52:28 test181 guacd[47807]: guacd[47807]: INFO: Guacamole proxy daemon (guacd) version 1.5.1 started
Apr 21 14:52:28 test181 guacd[47807]: guacd[47807]: INFO: Listening on host 127.0.0.1, port 4822
Apr 21 14:52:28 test181 guacd[47807]: Listening on host 127.0.0.1, port 4822We stop the server in order to amend configurations:
systemctl stop guacd.serviceFirst we create the directory
mkdir /etc/guacamoleThere we create a file /etc/guacamole/guacamole.properties with the content
basic-user-mapping: /etc/guacamole/user-mapping.xml
For our purposes, this file reads like
<user-mapping>
<!-- Per-user authentication and config information -->
<!-- FIRST USER -->
<authorize
username="test01"
password="52c88bca7c5b3ab3e7ed8901ea1bc83f"
encoding="md5">
<!-- First authorized Remote connection -->
<connection name="SSH Admin">
<protocol>ssh</protocol>
<param name="hostname">10.10.10.10</param>
<param name="port">22</param>
<param name="username">test01</param>
<param name="enable-sftp">true</param>
</connection>
<!-- second authorized Remote connection -->
<connection name="Terminal Server VNC">
<protocol>vnc</protocol>
<param name="hostname">127.0.0.1</param>
<param name="port">5901</param>
<param name="server-layout">de-de-qwertz</param>
</connection>
</authorize>
</user-mapping>Of course we have to amend hostname, username, and password for our system.
The password hash can be created by
echo -n 'secretPassword' | md5sumFinally, we have to append the Guacamole home to the environment:
echo GUACAMOLE_HOME="/etc/guacamole" >> /etc/environmentIt makes sense to reboot at this point.
Now we enable the Guacamole service for automated start:
systemctl enable guacd.serviceNext, we install the client:
cp /usr/src/guacamole-1.6.0.war /var/lib/tomcat9/webapps/guacamole.warThen we have to link the property directory to the place where it is expected:
ln -s /etc/guacamole /usr/share/tomcat9/.guacamoleTo speed up the tomcat restart, we have to create the following file
touch /usr/share/tomcat9/bin/setenv.sh
chmod +x /usr/share/tomcat9/bin/setenv.shwith this content:
#!/bin/sh
export CATALINA_OPTS="$CATALINA_OPTS -Djava.security.egd=file:/dev/./urandom"Now we can start the guacamole server:
systemctl start guacd.serviceIf we now browse to
http://test.example.org:8080/guacamole/we should be offered a login and then the connection options “SSH Admin” and “Terminal Server VNC”.
The SSH connection should work already (if not, you did probably not reboot), for the VNC we need to prepare some more things, as follows.
Install the VNC server
Let’s assume that we have a user test01 as our (sudo-enabled) standard user for the machine we just prepared, and that we are now logged in as that user.
We install the needed stuff:
sudo apt install -y xfce4 xfce4-goodies tigervnc-standalone-server tigervnc-xorg-extension autocutsel xfonts-base xfonts-100dpi xfonts-75dpiThen we create a vnc password for our (non-root) user:
vncpasswdNext, we have to create the vnc startup file in our user home directory and make it executable:
cd
mkdir .vnc
touch ~/.vnc/xstartup
chmod 755 ~/.vnc/xstartupThe contents of this file is
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
exec startxfce4 For starting the VNC server on boot, we change to root again with sudo -i and create a service file /etc/systemd/system/vncserver@.service, as suggested by Install Xfce VNC remote desktop on Ubuntu.
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target
[Service]
Type=simple
User=test01
PAMName=login
PIDFile=/home/%u/.vnc/%H%i.pid
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill :%i > /dev/null 2>&1 || :'
ExecStart=/usr/bin/vncserver :%i -geometry 1440x900 -alwaysshared -fg
ExecStop=/usr/bin/vncserver -kill :%i
[Install]
WantedBy=multi-user.targetIn the Service section, we replace test01 by the username of our local user.
To enable the service by default, we make the service available at boot time by
cd /etc/systemd/system/multi-user.target.wants/
ln -s /etc/systemd/system/vncserver@.service ./vncserver@1.serviceTime for a last reboot!
Then, we should be able to login to http://test.example.com:8080/guacamole with the credentials we stored in /etc/guacamole/user-mapping.xml, click on “Terminal Server VNC”, type in the VNC password we have defined before, and see a virtual XFCE screen in our browser.
That’s it! Now we have set up a Guacamole HTML5 remote XFCE desktop via VNC for Ubuntu 24.04.
For security reasons, it makes absolutely sense to add a 2FA as described in the already mentioned (german) article by Bernhard Linz. For security reasons, it makes also sense to map the Tomcat (http port 8080) via Apache or nginx reverse proxy to https, as described in the linked article.
Addena:
1
If you have a virtual server at a provider like Netcup which provides a VNC console to the machine, after the last reboot you’ll end up in a graphical login screen that produces a deadlock. To avoid being locked out you can change the default boot target:
sudo systemctl set-default multi-user.targetAfter a reboot you’ll see the console login again.
2
In order to start applications like Firefox etc from the command line, append the following to the .bashrc file:
XAUTHORITY=$HOME/.Xauthority
export XAUTHORITY