How to setup Apache Guacamole on Debian

In this article, I'd like to discuss how I set up Apache Guacamole on Debian Server to access my own Virtual Machines.

Apache Guacamole is a Remote Desktop Gateway with SSH, VNC, RDP support.

Because it is based on HTML5, all you need is a browser to connect.

It is free and open source software with Apache License Version 2.0

Apache Guacamole Installer

To install Apache Guacamole with Database and Tomcat, I recommend using guac-install as mentioned in Guacamole.

$ curl -L -O
$ chmod +x
$ sudo ./ --mysqlpwd password --guacpwd password --nomfa --installmysql

Create SSL Certs using certbot

To create SSL Certs for my domain (, I used certbot for certonly as following:

$ certbot certonly --agree-tos --email {my-email-address} --webroot -w /var/lib/letsencrypt/ -d

SSL Conf for Reverse Proxy to Guacamolde

Apache supports reverse proxy configurations through mod_proxy.

Apache 2.4.5 and later also support proxying of WebSocket through a sub-module called mod_proxy_wstunnel.

Both of these modules will need to be enabled for proxying of Guacamole to work properly.

$ sudo vi /etc/apache2/sites-available/

<VirtualHost *:443>
        Header always unset X-Frame-Options
        ErrorLog ${APACHE_LOG_DIR}/vm_error.log
        CustomLog ${APACHE_LOG_DIR}/vm_access.log combined

        <Location />
          Order allow,deny
          Allow from all
          #Require all granted
          ProxyPass http://localhost:8080/guacamole/ flushpackets=on
          ProxyPassReverse http://localhost:8080/guacamole/

        <Location /websocket-tunnel>
          Order allow,deny
          Allow from all
          #Require all granted
          ProxyPass ws://localhost:8080/guacamole/websocket-tunnel
          ProxyPassReverse ws://localhost:8080/guacamole/websocket-tunnel

        SSLEngine On
        SSLCertificateFile /etc/letsencrypt/live/
        SSLCertificateKeyFile /etc/letsencrypt/live/

Enable Reverse Proxy for SSL Conf

To enable Reverse Proxy module for your Apache SSL Configuration:

$ sudo a2enmod proxy proxy_http proxy_wstunnel
$ sudo a2ensite
$ sudo reload apache2

SSH Connection with PrivateKey

It took a while to figure out why Guacamole is keep asking for Passphrase when my PrivateKey does not have one.

It turns out Guacamole only supports PrivateKey with legacy PEM format.

To convert your default private key format on Debian system to legacy PEM format:

$ cd ~/.ssh
$ cp id_rsa id_rsa.old
$ ssh-keygen -f ~/.ssh/id_rsa -p -m pem

## before
$ cat id_rsa.old | head -2

## after
$ cat id_rsa | head -2

Here is what it says in the man page:

     -m key_format
             Specify a key format for the -i (import) or -e (export) conversion options.  The supported key formats are:
             “RFC4716” (RFC 4716/SSH2 public or private key), “PKCS8” (PEM PKCS8 public key) or “PEM” (PEM public key).
             The default conversion format is “RFC4716”.  Setting a format of “PEM” when generating or updating a sup‐
             ported private key type will cause the key to be stored in the legacy PEM private key format.

Apache Guacamole Diagram

Here is a rough diagram for Apache Guacamole:


Apache Guacamole Login with SSL

Here is a login window with SSL Cert for Apache Guacamole:


Apache Guacamole Login with TFA

To login Apache Guacamole with TFA (Two-Factor Authentication) such as Google Authenticator, I had to install guacamole-auth-totp in the Guacamole Extensions directory.

$ curl -L -O
$ tar xf guacamole-auth-totp-1.3.0.tar.gz
$ cd guacamole-auth-totp-1.3.0
$ sudo cp guacamole-auth-totp-1.3.0.jar /etc/guacamole/extensions
$ sudo systemctl restart tomcat9 guacd

Here is QR Code to register for the first time:


BTW, I had to clear all browsing data (cache) in order to see the QR Code.

Once registered, I was prompted for auth code every time I login:


More Screenshots