Apache Guacamole is open source software that is handy for remote administration or operations. It allows remote access to multiple systems, on multiple protocols, through a web interface. Its also handy to configure this capability into a bastion host, allowing remote management with minimal hassle.
Guacamole is open source and well documented, with support for several types of authentication as well as multi factor authentication. However, all of the writeups I found tended to either hardcode user passwords in the configuration file or skip the details on how to configure services. So I dug into it and documented configuration using LDAP for authentication, DUO for two factor authentication, and MySQL for holding connection configurations and mapping them to users. For this installation, I created a fresh Ubuntu 18.04 desktop and used an Active Directory domain already configured in my lab, consisting of a domain controller built on Windows Server 2016 and a Windows 10 host.
The first step in configuration of Guacamole is to build the server from source. OpenJDK and Maven must first be installed. After installing them using apt, the JAVA_HOME environmental variable must be set. It must be set both in the ~/.profile (or /etc/profile) and in the ~/.mavenrc config files.
There are a list of libraries detailed in the documentation required by Guacamole. Install these using apt.
Tomcat8 as well as supporting applications must be installed.
The code for the Guacamole server can be downloaded here. Once downloaded, the configure file must be generated using autoreconf.
Once complete, run configure with the –with-init-dir option set in order to ensure that the software will be loaded on OS startup.
After configuration, run make and make install followed by ldconfig to complete the guacamole installation. The guacamole client must then be installed. The client software can be downloaded here. Once downloaded, use maven to install it.
Installation of the client and server are complete at this point, however Guacamole is inaccessible until configuration is completed. The GUACAMOLE_HOME variable must be set in the /etc/default/tomcat8 file.
Configuration files and Guacamole extensions will be located in the /etc/guacamole directory. This directory must be created along with the extensions and the lib directory.
The guacamole-1.1.0.war file must be placed in the /var/lib/tomcat8/webapps directory. The name of the .war file place in the /var/lib/tomcat8/webapps directory will determine what the name of the web directory on the configured tomcat port will be. In this configuration, the Guacamole server will be available at http://localhost:8080/guacamole/.
The Guacamole home directory must be symbolically linked to the /usr/share/tomcat8/.guacamole directory.
The next step is to begin the initial configuration within the /etc/guacamole/guacamole.properties file. The hostname and port that Guacamole will be associated with must be defined.
If you restart the tomcat8 and guacd services at this point, the server should be accessible at the configured URL. However, no authentication has been configured so you will be unable to log in. In order to use Active Directory for LDAP authentication within Guacamole, the first step is to download the guacamole-auth-ldap-1.0.0.tar.gz file from the Apache site. The tar file must be decompressed and the .jar file must be placed in the /etc/guacamole/extensions directory.
Guacamole will require access to a service account to allow Guacamole to search for Active Directory objects and authenticate users.
The guacamole.properties file needs to account for the required LDAP parameters. The ldap-hostname parameter should point to an authentication server on the ldap-port using the ldap-encryption-method. The ldap-user-base-dn will be the base that Guacamole will look for users in. The ldap-username-attribute is the default for Windows. The ldap-search-bind-dn is the distinguished name for the account that will be used by Guacamole to search AD. And the ldap-search-bind-password is, of course, awesome.
The tomcat8 and guacd services must be restarted in order to read the changes to the guacamole.properties file. Once the restart is complete, you will be able to log in using AD user credentials! But there will be no available connections.
Connection configurations will be stored in MariaDB. In order to install MariaDB 10.4, the first step is to add the repository key for the MariaDB repo.
Next the repository needs to be added forthe appropriate server architecture.
Both the server and client applications for must now be installed.
The default time zone must be set for MariaDB using the default-time-zone parameter int he /etc/mysql/my.cnf file. This setting must be placed in the mysqld section of the my.cnf file
The database and user for Guacamole must next be created. First create the database. The database can be named whatever you want, for simplicity’s sake I’m sticking with the examples used in the documentation.
Next, create the user that guacamole will use in order to interact with the database. My super strong password reappears, ideally use something better than that.
The user that was created in the previous step must be granted privileges for the database we configured. Flush privileges to reload the grant table and this stage is done.
In order to use MySQL, we must install an extension and a library. First, the extension file, guac-auth-jdbc-1.0.0.tar.gz, must be downloaded from the Apache Guacamole website. Once decompressed, copy the guac-auth-jdbc-1.0.0.jar file to the /etc/guacamole/extensions directory.
Guacamole also requires a library in order to interact with MySQL. The MySQL Connector/J is used as a library by Guacamole to interface with MySQL. Download the file and install the .deb.
Once installed, a symbolic link must be created of the .jar file that was installed in the /etc/guacamole/lib directory.
The decompressed files for the JDBC extension contain a schema directory with configuration files for different database types. The .sql configuration files must be applied to the database.
Edit the guacamole.properties file to point to the mysql database on localhost at port 3306. Ensure that the mysql-database and mysql-username values match what was configured in the database, and use an awesome password.
The .sql configuration files should have configured a user in the database named guacadmin with the password guacadmin. Restart the tomcat8 and guacd services, and you should now be able to log in as the guacadmin user. Change the password to something strong (not my weak example password from the config file).
In order to populate users from AD, we need to establish guacadmin as an LDAP user. The way Guacamole works, it attempts authentication against all configured methods simultaneously. So in this case, it will attempt to authenticate guacadmin against both LDAP and MySQL and if either method is successful, it will log the user in. So a user named guacadmin can be created in AD and the password does not need to match the MySQL password in order to authenticate the user.
If we log in as guacadmin using AD credentials, we should be able to see all users in the LDAP user base path that we established in the guacamole.properties file by logging in and going to the Users settings in the we interface.
In order to allow AD users to log in remotely to Windows machines, they need to be given permissions in AD. The easiest way to do this is to use Group Policy. First step, add a new security group, in this case named Guac_Users. Add users to this group who should be allowed to log in remotely to Windows.
In the Group Policy Management console, right click the domain and select “Create a Group Policy in this Domain and link it here”, in this case the new policy is named Guac_Users.
Right click the new policy and select Edit, then navigate to “Computer Configuration”=>“Policies”=> “Windows Settings”=>Security Settings” and then right click “Restricted Groups” and select “Add Group”.
Select the Guac_Users group that was previously configured.
Assign the group as a member of the Remote Desktop Users group.
Select Apply and you should see the policy update to show the Guac_Users group as a member of the Remote Desktop users group.
The users should be configured and granted permissions once the GPO populates. Connections must be configured in the Guacamole web console. There are a ton of configuration options for each connection, this config is only concerned about setting up a basic connection using NLA. Log in as guacadmin and go to Settings and then Connections and select New Connection. Give it a name and select RDP for the protocol.
Scroll down to the Parameters section. Input the hostname or IP to connect to. Put in the RDP port, the domain name, and set the Security mode to NLA. Check “Ignore server certificate” to
For the username and password, Apache Guacamole has a feature called parameter tokens we can use to specify the username and password without hard coding in the config files or the database. Input ${GUAC_USERNAME} for the username and ${GUAC_PASSWORD} for the password. This will set the value of these variables to the credentials used by the user to log into the web interface, and then use those stored credentials to authenticate to the remote machine.
Save the connection and go to the Users menu. Select the user to be granted permissions to use this connection, and scroll down to the bottom. Select the connection and save the user.
Log out of the guacadmin account, log into the configured user. The configured user should automatically start logging into the host that was configured in the connection!
Note that it automatically logs in because there is only one connection configured. If more than one connection is configured then the user will be brought to a selection screen similar to the pic below.
Authentication is set up, a connection is set up, and everything is working as expected. Getting two factor authentication set up for Guacamole is relatively easy, and the last step here. In this example two factor authentication will be set up with Duo. Download the guacamole-auth-duo-1.0.0.tar.gz from here. Expand the tar file and copy the guacamole-auth-duo-1.0.0.jar file into the /etc/guacamole/extensions directory.
Log into the Duo web console and configure a new Web SDK. In order to configure Guacamole, we need three pieces of information from the Web SDK settings: the integration key, the secret key, and the api hostname. The secret key is sensitive and acts as the password from Duo for the configured application. Note these items and save the newly configured application.
The next step is to configure a user in the Duo web interface. Follow the prompts to create a new user, then associate a device with that user for use with Duo.
The last item needed for configuration is the application key. The application key must be kept secret and along with the secret key should be treated as a password. The application key must be at least 40 characters and should be random. Any random string can be used, I chose to generate a random string using the below command.
head -c 50 < /dev/urandom | sha256sum | cut -c 1-40
Now the guacamole.properties files must be updated. Input the API hostname, integration key, secret key, and application key as below.

Restart the tomcat8 and guacd processes to read the changes from the guacamole.properties. Duo requires the server time to be in sync, use chrony to sync the time.
Once synced, log in with the configured user and you should be prompted for Duo two factor authentication.
Input the two factor code and the user will be authenticated!
The frustration I felt when initially researching this was that I didn’t feel comfortable putting user credentials in a text file, or have an idea of how to manage that if implemented for a team, but the writeups I read were using that basic authentication which relies on hardcoding those creds. There’s no getting around putting sensitive data in that guacamole.properties file. We have the service account credentials, the database password for the guacamole user, and the Duo keys all stored in the file. But no user data is saved in there, and if you had to make your team use this it’s usable and scalable.