Apache Guacamole is a free and open-source remote desktop gateway that allows you to connect to your computer/server remotely using different protocols such as SSH, RDP, and VNC. Apache Guacamole is maintained by Apache Software Foundation, and licensed with Apache License 2.0.
Apache Guacamole is a clientless remote desktop gateway. You can access Apache Guacamole using only a web browser from anywhere at any time. Using Apache Guacamole is recommended if you have multiple remote operating systems with different protocols, such as Windows with RDP, and Linux system with VNC and SSH.
In this tutorial, you will install Apache Guacamole – Remote Desktop/Server Gateway – via Docker on an Ubuntu 22.04 server. This includes Nginx installation and configuration as a reverse proxy for Apache Guacamole. In the end, you will have Apache Guacamole running as a Docker container and secure the installation via SSL/TLS certificates on top of the Nginx reverse proxy.
Prerequisites
To start with this tutorial, you must have the following requirements:
- A Linux server running Ubuntu 22.04 server.
- A non-root user with sudo/root administrator privileges.
- A domain name pointed to the server IP address.
That’s it. when the requirements are ready, you can now start Apache Guacamole installation.
Installing Docker Engine and Docker Compose
In this tutorial, you will run and install Apache Guacamole as a container service via Docker and Docker compose. This example uses a fresh and generic Ubuntu 22.04 server, so this includes the Docker and Docker compose installation.
To start, run the below apt command to install basic dependencies. Input y when prompted and press ENTER to proceed.
sudo apt install ca-certificates curl gnupg lsb-release
Output:
Next, run the below command to add the GPG key and repository for Docker packages.
sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Output:
After that, update and refresh your Ubuntu package index via the apt command below.
sudo apt update
Output:
With the Docker repository added, you can now install the Docker engine and Docker Compose plugin using the below apt command. When prompted, input y, then press ENTER to proceed.
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Output:
The Docker service will start and enable automatically. You can verify the Docker service via the following systemctl command utility.
sudo systemctl is-enabled docker sudo systemctl status docker
You should get an output that the Docker service is enabled and will be run automatically at boot. And the status of the Docker service is running.
Lastly, to allow your non-root user to run the Docker container, you must add your user to the ‘docker‘ group. Run the below usermod command below to add your user to the ‘docker‘ group. Also, be sure to change the username with your user.
sudo usermod -aG docker alice
You can now log in as your user and run the Docker container via the below command.
su - alice docker run hello-world
When successful, you should get the hello-world message from the Docker container like the following screenshot.
With the Docker and Docker compose installed, you will next start creating a project directory for Apache Guacamole deployment.
Setting up Project Directory
First, ensure that you’ve logged in as your non-root user by running executing the following command.
su - alice
Create a new project directory ‘~/guacamole-server’ and move your working directory into it.
mkdir -p guacamole-server; cd guacamole-server/
Then, within the ‘~/guacamole-server‘ directory, create a new directory ‘init‘, and the ‘docker-compose.yml‘ file.
mkdir -p init touch docker-compose.yml
Next, run the following ‘docker pull‘ command to download the necessary Docker images for the Apache Guacamole installation. You’ll download three different images, guacd as the proxy manager, guacamole as front-end of Apache Guacamole, and the postgres:13 which will be used as the database backend for the Apache Guacamole container.
docker pull guacamole/guacd docker pull guacamole/guacamole docker pull postgres:13
Downloading the guacd image.
Downloading guacamole image.
Downloading PostgreSQL 13 image.
When necessary Docker images are downloaded, execute the following command to run a new guacamole container and run the ‘initdb.sh‘ script to generate database schema for your deployment. With this, you will generate a guacamole database schema to ‘init/initdb.sql’.
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > init/initdb.sql
Verify the content of the guacamole database schema via the cat command below.
cat init/initdb.sql
Output:
Setting up docker-compose.yml
Now that the necessary Docker images have been downloaded, you can begin configuring the ‘docker-compose.yml‘ script and set up the Apache Guacamole installation.
Start by opening the config file ‘docker-compose.yml‘ using the following nano editor command.
nano docker-compose.yml
Add the following lines to the file.
version: '3.7' # networks networks: guacnet: driver: bridge # services services: guacd: container_name: guac_guacd image: guacamole/guacd networks: guacnet: restart: always postgres: container_name: guac_postgres environment: PGDATA: /var/lib/postgresql/data/guacamole POSTGRES_DB: guacamole_db POSTGRES_PASSWORD: 'ChangeThisPassword' POSTGRES_USER: guacamole_user image: postgres:13 networks: guacnet: restart: always volumes: - ./init:/docker-entrypoint-initdb.d:ro - ./data:/var/lib/postgresql/data:rw guacamole: container_name: guac_guacamole depends_on: - guacd - postgres environment: GUACD_HOSTNAME: guacd POSTGRES_DATABASE: guacamole_db POSTGRES_HOSTNAME: postgres POSTGRES_PASSWORD: 'ChangeThisPassword' POSTGRES_USER: guacamole_user image: guacamole/guacamole links: - guacd networks: guacnet: ports: - 8080:8080/tcp restart: always
Save and close the file ‘docker-compose.yml‘ when finished.
With this ‘docker-compose.yml‘ script, you will create three containers/services as below:
- guacd – the main component of Apache Guacamole that will be used to proxy to multiple protocols such as SSH, RDP, VNC, etc.
- postgres – the database backend for your Apache Guacamole installation. Your data will be stored in this container.
- guacamole – the Apache Guacamole web application that is connected to PostgreSQL and guacd services. This container will expose port 8080 on your host machine.
Starting Apache Guacamole
Before you start, ensure that you’re in the ‘guacamole-server’ project directory. Then, run the following ‘docker compose‘ command to create and start Apache Guacamole deployment.
docker compose up -d
You should receive an output like this – There are 3 different containers guac_postgres, guac_guacd, and guac_guacamole created and started.
Verify the list of running services/containers on your Apache Guacamole project via the following command.
docker compose ps
If you see the ‘STATUS‘ is ‘Up‘, then the container/service is running. On the ‘PORTS‘ section you should see exposed ports by container to the host machine.
The ‘guac_guacamole‘ container exposed TCP port 8080 on both the container and Docker host. With this, you can access your Apache Guacamole installation.
Open up your web browser and visit your server IP address followed by port 8080 (i.e: http://192.168.5.100:8080/). You will see the Apache Guacamole login page.
Log in via default user ‘guacadmin‘ and password ‘guacadmin‘. Then press Login to confirm.
When successful, you should get the Apache Guacamole user dashboard.
With that, confirms that the Apache Guacamole installation via Docker and Docker compose is finished and successful. But, for this tutorial, there are still a few actions that need to be performed to secure your Apache Guacamole deployment.
In addition, when you counter an error on your Apache Guacamole deployment, you can check the logs for each container via the ‘docker compose‘ command below.
Basic usage ‘docker compose‘ for checking logs.
docker compose logs docker compose logs SERVICE
Checking logs for specific containers/service via the ‘docker compose‘ command.
docker compose logs guacamole docker compose logs guacd docker compose logs postgres
Installing Nginx Web Server
For this tutorial, you will be running the Apache Guacamole with Nginx reverse proxy. In this section, you will install the Nginx web server and Certbot tool for generating SSL/TLS certificates. Then, you’ll verify the Nginx service to ensure that the service is enabled and running.
Run the following apt command to install Nginx, Certbot, and Certbot Nginx plugin. Input y when prompted for confirmation and press ENTER to proceed.
sudo apt install nginx certbot python3-certbot-nginx
After Nginx and Certbot are installed, run the following command to verify the Nginx service status. This will ensure that the Nginx service is enabled and running on your system.
sudo systemctl is-enabled nginx sudo systemctl status nginx
The output ‘enabled‘ confirm that the Nginx service is enabled and will be run automatically upon system bootup. The output ‘active (running)‘ confirms that the Nginx service is running.
Setup UFW Firewall
With Nginx installed, you will next set up the UFW firewall that is installed by default on your Ubuntu system. In this section, you will add the OpenSSH service to open port 22 and add ‘Nginx Full’ services to open both HTTP and HTTPS ports on ufw. Then, you will start and enable ufw. Lastly, you will verify the status of ufw firewall.
Enter the following command to add the OpenSSH and ‘Nginx Full‘ services to the ufw firewall. The output ‘Rules updated‘ confirms that the new rule is added to ufw.
sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full'
Next, enter the following command to start and enable the ufw firewall. Input y when prompted and press ENTER to proceed.
sudo ufw enable
You should now get an output such as ‘Firewall is active and enabled on system startup‘, which means the ufw firewall is running and it’s enabled and will start automatically upon system startup.
Verify the status of the ufw firewall by entering the following command.
sudo ufw status
You should get the status of the ufw firewall ‘active‘ and enabled services ‘OpenSSH‘ that will open the SSH port 22 and ‘Nginx Full‘ service that will open both HTTP and HTTPS ports.
Setup Nginx as a Reverse Proxy
In order to secure your Apache Guacamole deployment, you will be using Nginx as a reverse proxy and enable HTTPS secure connections on top of it.
In this section, you’ll create a new Nginx server block configuration that will be used as a reverse proxy for Apache Guacamole, then generate SSL/TLS certificates via Certbot and Letsencrypt to secure the Apache Guacamole deployment.
Create a new Nginx server block configuration ‘/etc/nginx/sites-available/guacamole.conf‘ using the following nano editor command.
sudo nano /etc/nginx/sites-available/guacamole.conf
Add the following lines to the file and be sure to change the domain name in the configuration below. With this, you’ll set up Nginx as a reverse proxy for the Apache Guacamole container that exposed port 8080 on the Docker host machine.
server { listen 80; server_name guacamole.hwdomain.io; root /var/www/html; index index.html index.htm index.nginx-debian.html; access_log /var/log/nginx/guac_access.log; error_log /var/log/nginx/guac_error.log; location / { proxy_pass http://127.0.0.1:8080/guacamole/; proxy_buffering off; proxy_http_version 1.1; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_cookie_path /guacamole/ /; } }
Save and close the file when finished.
Next, run the below command to activate the Nginx server block file ‘/etc/nginx/sites-available/guacamole.conf‘. Then, verify the Nginx configuration to ensure that you have the proper settings.
sudo ln -s /etc/nginx/sites-available/guacamole.conf /etc/nginx/sites-enabled/ sudo nginx -t
If successful, you should get an output such as ‘test successful – syntax ok‘.
Now run the following systemctl command utility to restart the Nginx service and apply the changes.
sudo systemctl restart nginx
Output:
At this point, the Apache Guacamole is running with Nginx as a reverse proxy with your domain name – this example uses the domain ‘guacamole.hwdomain.io’. Now to secure your Apache Guacamole deployment, you will need to generate SSL/TLS certificates via Certbot and Letsencrypt.
Enter the following certbot command to generate new SSL certificates for your Nginx virtual host. Be sure to change the details domain name and email address in the following command.
sudo certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email [email protected] -d guacamole.hwdomain.io
After generated, your SSL certificates will be available in the ‘/etc/letsencrypt/live/guacamole.hwdomain.io/‘ directory. Also, your Nginx server block will automatically be changed with SSL enabled and automatically redirect from HTTP to HTTPS.
Accessing Apache Guacamole
Open your web browser and visit the domain name of your Apache Guacamole installation (i.e: https://guacamole.hwdomain.io/).
Log in with the default user and password ‘guacadmin‘.
When successful, you should get the Apache Guacamole user dashboard.
At this point, you’ve now finished the Apache Guacamole installation via Docker and Docker compose. Also, you’ve configured Nginx as a reverse proxy for Apache Guacamole and secured it via SSL/TLS certificates from Letsencrypt.
In the next step, you’ll learn the basic usage of Apache Guacamole.
Basic Usage of Apache Guacamole
In this step, you will learn the basic usage of Apache Guacamole. You will be deleting the default guacadmin user to secure your deployment, setup new admin user for Apache Guacamole, setup connection group, then lastly setting up a new SSH connection.
Through the end, you will also verify your new connection by connecting to SSH server via Apache Guacamole.
Creating New User
Click on the top right ‘guacadmin‘ menu and select ‘Settings‘.
Select the ‘Users‘ tab and you should see the default ‘guacadmin‘ user. Click the ‘New User‘ button to create a new Apache Guacamole user.
Input the details username that will be used for logging in and input the password and repeat.
On the ‘PROFILE‘ section, input user details such as full name, email address, and organization name.
On the ‘PERMISSIONS‘ section, select all options to make this user an administrator for your Apache Guacamole installation.
Click Save to confirm and create the new user. Then, log out from the default ‘guacadmin‘ user.
Next, log in with your new user and verify user configurations.
If successful, you should see the Apache Guacamole user dashboard.
Now click your user and select ‘Settings‘. Then click on the ‘Users‘ tab to verify the list of users on your Apache Guacamole. You should see the new user is created.
Click on the default user ‘guacadmin‘ to get details information about the default user. Scroll to the bottom page and click the ‘Delete‘ button to remove the default ‘guacadmin‘ user.
Click Delete again to confirm.
After the default ‘guacadmin‘ user is deleted, the only remaining user on Apache Guacamole is your new user.
With that, you’ve now created a new admin user on Apache Guacamole and deleted the default ‘guacadmin’ user. Deleting the default user ‘guacadmin’ will mitigate password-guessing attacks.
Creating New Connection
Ensure that you’ve been on the Apache Guacamole ‘Settings‘ page.
Select the ‘Connections‘ tab and click the ‘New Group‘ button to create a new connection group.
Input the group name, and location, and select the type. In this example, you will create a new group ‘SSH-SERVER‘. You can also set up limits of connection for every connection in this group within the ‘CONCURRENCY LIMITS‘ section.
Click Save to confirm.
Now you should get the group ‘SSH-SERVER‘ on the list of connections.
Next, click the ‘New Connection‘ button to create a new connection on Apache Guacamole.
Input the connection name, select the default location, and select the protocol for this connection. In this example, you will create an SSH connection ‘Test SSH‘ that will be available in the ‘SSH-SERVER‘ group.
On the ‘PARAMETERS‘ section, input details of host or IP address, port, username, password, and SSH key (when enabled).
Scroll to the bottom page and click Save to confirm.
With that, you should now get the new connection ‘Test SSH‘ available on the ‘SSH-SERVER‘ group.
To connect to the new ‘Test SSH‘ connection, move back to the Apache Guacamole home user dashboard and you should see the list of your connections.
Click the ‘Test SSH‘ connection to connect.
When you do not provide a password on your details connection, you should be prompted for the password to your SSH server.
With this in mind, you have now created a new user, deleted the default user guacadmin, set up a connection group, and created a connection on Apache Guacamole.
Conclusion
In this tutorial, you learned how to deploy Apache Guacamole via Docker and Docker Compose on an Ubuntu 22.04 server. You’ve deployed Apache Guacamole with PostgreSQL as the database backend and Nginx as a reverse proxy at the front. In addition to that, you’ve also secured Apache Guacamole deployment with SSL/TLS certificates from Letsencrypt and configured ufw firewall.
Through the end, you’ve also learned the basic administration of Apache Guacamole. From creating a user, deleting a user, setting a connection group, and creating a new connection on Apache Guacamole.
With all of this, you basic Apache Guacamole deployment. To learn more, check the Apache Guacamole’s official documentation. You can add third-party integration such as LDAP authentication, Radius authentication, TOTP two-factor authentication, SAML, and many more.