Install Guacamole on Docker – VNC, SSH, SFTP, and RDP like a Boss!

Wouldn't it be awesome if you are able to remotely connect to your system using Windows Remote Desktop, VNC, Telnet, SSH, SFTP, or Kubernetes protocols, just using a modern web browser and without the need for any client apps? Install Guacamole on Docker and do exactly that.

Apache's Guacamole can be handy for system administrators and tinkerers, such as myself, who run servers at home. Unfortunately, setting up Guacamole on Ubuntu and other Linux systems requires several steps and can be a pain.

I have been a fan of Docker for the last 2 years. From my Docker Server guide, you may know that I run several apps on Docker already. [Read: 60+ Best Docker Containers for Home Server Beginners 2023]

I was thrilled to learn that I could install Guacamole on Docker. So in this Guacamole Docker tutorial, I will show you how to setup Guacamole using Docker and remotely administer various systems using just a modern web browser.

I will also provide the Docker-compose file to make Guacamole setup much easier.

What is Guacamole?

Apache Guacamole, or Guacamole, is a client-less remote desktop gateway. It provides a unified HTML5 web interface to access remote systems using VNC, Telnet, RDP, Kubernetes and SSH/SFTP protocols.

Why use Guacamole? - Advantages and Features

VNC, RDP, Telnet, and SSH all require client apps on the local system to be able to connect to remote systems. For example, connecting to an SSH server on Linux from a Windows system requires an SSH client such PuTTY or similar app.

Similarly, VNC and RDP require client apps as well. But wait, what if you can't install these client apps on the local system (eg. Work computers or public computers)? Here is where Guacamole comes to save your life, as all it requires is a HTML5 web browser.

  • You can access your systems from anywhere with just a web browser
  • No configuration needed on the local system. Fire up a browser, go to your Guacamole app URL, login, and you are good to go.
  • You do not even need a physical computer. You can use Guacamole to connect to your cloud systems such as Virtual Private Servers.

Let's go ahead and configure Apache Guacamole to make our lives a little bit easier.

Install Guacamole on Docker

In my setup, I have over several systems that I SSH into (eg. USG, PiHole, Linux Server, Ubuntu VPS, couple of Raspberry Pis, etc.). Guacamole provides a unified interface for me to manage these. When needed, I can even VNC into my Linux Mint desktop for additional tasks.

With Docker you can have Guacamole running in just a few minutes without any major changes to the host system.

1. Requirements

In order to successfully follow this Guacamole Docker guide, you will need a few things ready.

  1. Docker Server with or without a reverse proxy such as Traefik: If you followed my Docker Media server guide or Docker Traefik v2 guide, you should be good here.
  2. Docker Compose: This should also be taken care of if you followed the guides linked above.
  3. MySQL Database Server: Don't worry we will talk about this later.
  4. Docker Network: We are going to be using a network named t2_proxy. This could be different in your case. If you followed the network setup in my Docker Traefik 2 guide, you should already have this.
  5. WebUI for MySQL: A WebUI for MySQL such as PhpMyAdmin or Adminer makes things very easy. On my GitHub repo, I have docker compose examples for both MariaDB (MySQL) and PhpMyAdmin. But this is optional and if you do not have one running, no problem.

The assumption is that you already are familiar with Docker and some of the useful docker commands. If not, I urge you to read my Docker Traefik 2 guide before proceeding.

2. Setup MySQL Server

As said before, Guacamole requires a MySQL Database Server. In this Guacamole Docker tutorial, we are going to be using the open-source MariaDB server.

In my case, I already have MariaDB running on my Synology NAS and I use that for all my database needs. If you are in a similar situation, you can use your existing database server.

Note: I like having database as a separate service. But this does lengthen the setup process a bit. If you prefer an easier setup for Guacamole, you may check out this Oznu's Guacamole image, which has MySQL built into the Guacamole container. As seen in the comments below, some users have preferred this method.

Alternatively, you can add MariaDB to your Docker stack using the following Docker compose snippet:

# MariaDB - MySQL Database
    container_name: mariadb
    image: linuxserver/mariadb:latest
    restart: always
      - t2_proxy
      - no-new-privileges:true
#    ports:
#      - "3306:3306"
      - $USERDIR/docker/mariadb/data:/config
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - PUID=$PUID
      - PGID=$PGID

A few notes about the MariaDB Docker Compose snippet:

  1. There are several MariaDB images on Docker Hub. We are going to use's image.
  2. The ports block is optional. Guacamole should be able to access MariaDB using hostname mariadb on port 3306. Alternatively, you can enable ports block and access MariaDB on your host system's IP on port 3306.
  3. We are mapping $USERDIR/docker/mariadb/data to /config of the container. All databases will be stored in this folder. Note that the environmental variable $USERDIR must already be set as explained in my Docker Traefik guide.
  4. Variables $PUID, $PGID, and $MYSQL_ROOT_PASSWORD must also be defined.

Start the MariaDB container and check the logs to make sure everything is OK. If you do not know what commands to use here, check the requirements section where I provided a link to basic docker commands.

That is it for setting MySQL server of Guacamole. Now let us move on to the Guacamole setup part of the guide.

3. Guacamole Database Setup and Initialization

This is explained in detail in Guacamole Wiki. But if you follow these key steps, you should be fine.

Create Guacamole Initialization Script

Guacamole requires that the database be initialized first. This involves several steps. However, Guacamole provides a script that can simplify this process.

From your host system's commandline, run this command to create the initialization script.

docker run --rm guacamole/guacamole /opt/guacamole/bin/ --mysql > guac_initdb.sql

This should output a SQL file with the name guac_initdb.sql, which has all the SQL commands needed to initialize the guacamole database.

Copy Initialization Script to MySQL Server

Next, we need to move guac_initdb.sql file into the MySQL container or the external MySQL host. We will discuss both options.

If you set up and started the MariaDB container using the docker-compose snippet given above, you should have a mariadb folder inside your docker root folder. Copy the initialization script into the mariadb folder.

As I said before, I use MariaDB on my Synology NAS. In this case, I just copied the guac_initdb.sql initialization script to a known location on my NAS.

Create MySQL Database for Guacamole

Then you need to create a MySQL database for Guacamole. If you have phpMyAdmin open, this is quite easy as shown below.

Create Database For Guacamole Using Phpmyadmian
Create Database For Guacamole Using Phpmyadmian

To do this using the commandline, you need to SSH into the external MySQL server or the MariaDB container. Describing how to SSH into an external host is outside the scope of this post. But in the case of MariaDB container, use the following command to reach the server's commandline.

docker exec -ti mariadb /bin/bash

Next, let us connect to the MySQL server. On MariaDB container, use the following command:

mysql -u root -p

On Synology NAS, use the following command to connect to MariaDB version 10:

/usr/local/mariadb10/bin/mysql -u root -p

When asked for the MySQL root password, enter the password you used while setting up MariaDB. This should get you to the MySQL prompt as shown below:

Mariadb Prompt
Mariadb Prompt

From here, the procedure is the same on both MariaDB container and external host (eg. Synology) to create the database and other relevant information.

From MySQL prompt, create a database called guacamole (you can use any name for the database) using the following command:

create database guacamole;

Next, create a username (guacdb_user) and password (my_strong_password) for Guacamole app to connect to MariaDB server. Customize the username and (strong) password to your needs.

CREATE USER 'guacdb_user' IDENTIFIED BY 'my_strong_password';

Then, we are going to provide full access for guacdb_user to the database guacamole. To do this, use the following MySQL command (pay attention to the backticks and single quotes usage):

GRANT ALL ON `guacamole%`.* TO 'guacdb_user';

Finally, flush privileges and exit using these following commands in sequence:

flush privileges;

The whole process should look something like what is shown in the screenshot below.

Create Mysql Database And User For Guacamole
Create Mysql Database And User For Guacamole

Alternatively, you can run some or all the above SQL commands on phpMyAdmin as shown below:

Guacamole Sql Commands On Phpmyadmin
Guacamole Sql Commands On Phpmyadmin

Check Guacamole MySQL Credentials

Now, make sure you are able to connect to the MariaDB server using the Guacamole database credentials:

mysql -u guacdb_user -p

Use /usr/local/mariadb10/bin/mysql -u root -p on Synology. After you enter the password (my_strong_password), you should be able to reach the MySQL prompt.

Initialize Guacamole MySQL Database

To initialize the database, we need to run the SQL script we copied over the MariaDB server previously. From the MariaDB server's commandline, run the following command (Synology Example shown):

cat /volume1/ds918/guac_initdb.sql | /usr/local/mariadb10/bin/mysql -u guacdb_user -p guacamole;

If you are using MariaDB on Docker, then use the following command instead:

cat /config/guac_initdb.sql | mysql -u guacdb_user -p guacamole;

Few notes about the above command:

  • /volume1/ds918/guac_initdb.sql is the location where the initialization script is saved on my Synology. For MariaDB container, it is /config/guac_initdb.sql (or whatever you chose previously).
  • Replace guacdb_user with the username you chose.
  • guacamole is the name of the database. Change this if you named the database differently.

When asked, enter the password (my_strong_password) and the execution should complete in a few seconds.

Confirm Proper Initialization

Before proceeding further with Guacamole setup, let us check to make sure that the guacamole database was initialized properly with all the required information. To do this, login into MariaDB server and issue the following commands from the MySQL prompt:

use guacamole;
show tables;

If you see an output like what is shown below, you should be good to go.

Guacamole Database Initialization Verification
Guacamole Database Initialization Verification

Alternatively, you can look at the database structure on phpMyAdmin to ensure that the required tables have been created (there should be several tables listed after initialization).

Guacamole Mysql Initialization Check Using Phpmyadmin
Guacamole Mysql Initialization Check Using Phpmyadmin

4. Setup Guacamole Daemon on Docker

Apache Guacamole setup requires Guacamole daemon to be running and accessible. Guacamole Daemon (guacd) is the proxy that translates various protocols to Guacamole protocol and vice versa.

Setting up guacd is quite easy with Docker. Here is the docker-compose snippet to use to start Guacamole daemon.

# Guacamole Daemon - Needed for Guacamole
    image: guacamole/guacd
    container_name: guacd
    restart: unless-stopped
      - no-new-privileges:true
      - t2_proxy

The only requirement I have found here is that guacd must be on the same network (t2_proxy) as Guacamole. There is nothing else to configure or change.

That is it. Start the guacd container and you should be ready to install Guacamole next. Again, refer to the requirements section above for the link to basic docker commands (eg. for starting and stopping containers).

5. Setup Guacamole on Docker

Phew! now that foundation is done, let us move on to Apache Guacamole Docker setup using Docker Compose. Add the following code block to your docker-compose file:

Note: In my GitHub repo (which should be your main source of reference for docker-compose examples as it has the most up-to-date information), I use several domain names: DOMAINNAME_HOME_SERVER (for my Docker Home Server on Synology), DOMAINNAME_CLOUD_SERVER (for my Dedicated Server in a Datacenter, with Proxmox), DOMAINNAME_SHB (domain name for this website), and DOMAINNAME_KHUB (domain name of another non-WordPress website I host). You may find any of these domain variables in my examples. Make sure to substitute this variable with your own.
# Guacamole - Remote desktop, SSH, on Telnet on any HTML5 Browser 
# Create all databases and tables first
    image: guacamole/guacamole:latest
    container_name: guacamole
    restart: unless-stopped
      - t2_proxy
      - no-new-privileges:true
#    ports:
#      - "$GUACAMOLE_PORT:8080"
      GUACD_HOSTNAME: guacd
      MYSQL_HOSTNAME: mariadb
      MYSQL_DATABASE: guacamole
      - "traefik.enable=true"
      ## HTTP Routers
      - "traefik.http.routers.guacamole-rtr.entrypoints=https"
      - "traefik.http.routers.guacamole-rtr.rule=Host(`guac.$DOMAINNAME_CLOUD_SERVER`)"
      - "traefik.http.routers.guacamole-rtr.tls=true"
      ## Middlewares
      - "traefik.http.routers.guacamole-rtr.middlewares=chain-authelia@file,add-guacamole" 
      - "traefik.http.middlewares.add-guacamole.addPrefix.prefix=/guacamole"
      ## HTTP Services
      - "traefik.http.routers.guacamole-rtr.service=guacamole-svc"
      - ""

Below are a few notes about the Guacamole docker-compose example.

Docker Compose Blocks

  • Network: Once again, Guacamole will part of the t2_network, which is already setup and was previously discussed in this guide.
  • Ports: I commented out the ports because I want Guacamole interface to be available only via Traefik reverse proxy. If you want access to Guacamole WebUI via ports (eg. on internal network) then enable the ports block. Also set the $GUACAMOLE_PORT environmental variable.
  • Environmental Variables: GUACD_HOSTNAME can be left as guacd. MYSQL_HOSTNAME is mariadb (name of the MariaDB service) or the IP address of the MySQL server host.

    MYSQL_PORT must be set using $DB_PORT environmental variable. The default MySQL port is 3306. The rest of the variables are Guacamole MySQL database credentials we previously set: guacdb_user and my_strong_password. Define these in the .env file as well.

Traefik 2 Labels Block

The labels block is optional and needed only if you want to put Guacamole behind Traefik reverse proxy (highly recommended).

If you do leave out the Traefik labels, then you will have to enable the ports block and access Guacamole web interface using HOST-IP:Port. You may also setup port-forwarding on your router and make Guacamole available from the internet. But I highly discourage exposing an app and port directly to the internet. Having a reverse proxy, such as Traefik, in front is more secure.

Explaining Traefik 2 labels is beyond the scope of this post. I recommend reading my Traefik 2 guide to setup Traefik 2.

Below are a few notes on the Traefik 2 labels.

  • The defined router rule will make Guacamole WebUI available at, where $DOMAINNAME_CLOUD_SERVER is defined as in the .env file.
  • We are putting Guacamole behind Authelia authentication by defining the middleware chain-authelia@file. Check my Docker Traefik 2 guide if you do not understand. You also have the option to use Google OAuth instead.
  • We are adding another middleware (add-guacamole). This middleware sets the addPrefix, which makes opening Guacamole WebUI easier. Guacaomle will now be available at instead of

Nothing else to customize. Save your docker-compose file and start the Guacamole container (shortcut dcup2 if you followed by Traefik 2 guide strictly). As always after starting the container, follow the docker logs to ensure there are no glaring errors errors.

Tip: You may use Dozzle to check the logs of all your running containers.

Be the 1 in 200,000. Help us sustain what we do.
10 / 150 by Dec 31, 2024
Join Us (starting from just $1.67/month)

Guacamole Intial Setup and Security

Now that Guacamole docker container is up and running, let's test it out. Visit and you should see the Guacamole login screen.

Guacamole Login - Default Username And Password Are Both &Quot;Guacadmin&Quot;.
Guacamole Login - Default Username And Password Are Both Guacadmin.

If you are able to get in, then great.

Guacamole Security: Delete Default User

One of the first things you should do is change the default login details. This is less of a concern if you have an authentication system in front (eg. Authelia or Google OAuth) but is still strongly recommended.

Go to Settings->Users, and add a new user.

Guacamole Security - Delete Default User
Guacamole Users

Fill out the username and password. Then scroll down to Permissions and check all of them as shown below.

New Admin User Permissions For Guacamole
New Admin User Permissions For Guacamole

The rest of the settings on this page are optional. Hit Save to save the user.

Next, logout and login as the new user you created. Once again go to Settings->Users. Click on guacadmin, scroll all the way down, and hit DELETE to delete the default Guacamole user.

Guacamole Security: Duo Multifactor Authentication

Guacamole supports Duo two-factor authentication. Setting this up requires additional configuration.

However, if your Guacamole app is behind Authelia or even Google OAuth, then you already have two-factor authentication built-in. It can be via Duo, which I use, or any other authentication method (text, Authy, Google Authenticator, etc.).

Authelia 2-Factor Authentication
Authelia 2-Factor Authentication

I highly recommend protecting yourself via Authelia or Google OAuth, as shown in my Traefik 2 tutorial.

Next, let us see how to configure Guacamole.

Using Guacamole for VNC, SSH (SFTP), and RDP

Now let us look the main reason we actually installed Guacamole - accessing our systems via VNC, SSH, SFTP, or RDP remotely using the web browser. Setup a new Guacamole connection by going to Settings->Connections.

Setup A New Guacamole Connection
Setup A New Guacamole Connection

1. VNC using Guacamole

Virtual Network Computing (VNC) is a way of connecting to GUI desktop environments. Before you can get started with this, you will need a VNC server to be running on the remote host that you want to connect to. [Read: Setup VNC Server on Ubuntu: Complete Ubuntu Remote Desktop Guide]

Assuming that you already have a VNC server running, let us look at how to configure VNC on Guacamole. I will show you the basic/minimum requirements to setup VNC on Guacamole and get started.

Guacamole Remote Vnc To Linux Mint Desktop
Guacamole Remote Vnc To Linux Mint Desktop

Add a new connection and provide some descriptive connection details as shown below. In the example below, we are connecting my Linux Mint home server. [Read: My Smart Home setup โ€“ All gadgets and apps I use in my automated home]

Add A Vnc Connection On Guacamole
Add A Vnc Connection On Guacamole

Next, scroll down to PARAMETERS and provide the VNC Host IP, port, and VNC password. The default port can vary but is typically 5900, 5901, 5902, etc.

Vnc Connection Credentials
Vnc Connection Credentials

If you know what you are doing, you can configure the rest of the VNC settings on this page. Otherwise, you can safely ignore the rest of the settings on this page and hit Save at the bottom of the page.

Return back to Guacamole home page and you should see the link to start this VNC connection.

How to return to Home Screen on Guacamole?

While on any connection, press Ctrl+Alt+Shift to activate the Guacamole context menu that provides various options, including, return to home screen.

Some of the apps in my GitHub Repo, such as jDownloader, firefox, handbrake, MakeMKV, etc., use VNC servers to make the interface available via the web browser. Using Guacamole's VNC I was able to connect to these as well.

2. SSH/SFTP using Guacamole

SSH is one of the most common remote connection protocols used by system administrators. We have covered SSH in detail through various posts and I recommend checking out some of these posts to get the best out of SSH.

Frankly, I did not understand its power until I started using it pretty much every day. The problem is SSH requires a client software or app to connect to the server. There are several awesome SSH Clients for Windows and Android platforms. However, if you have restricted permissions on the device (eg. Corporate devices) then you may not be able to install them.

Sometimes corporate connections detect and block any known remote connection protocols. So even portable SSH clients like Portable PuTTY become useless.

This where Guacamole can save the day (or the rest of your life) for you. So let's go ahead and configure Guacamole for SSH connections.

Go to Settings->Connections and add a new connection. Provide a descriptive name for the SSH connection and choose SSH for protocol, as shown below.

Configure Guacamole For Ssh Connections
Configure Guacamole For Ssh Connections

Next, under parameters, provide your SSH server host and port to use for the SSH connection (default is 22).

Provide Ssh Server Details - Apache Guacamole
Provide Ssh Server Details - Apache Guacamole

Then provide the username and password for SSH connection. Alternatively, you may use your private key and passphrase, although this did not work for me (maybe I am doing something wrong).

Guacamole Ssh Credentials | Smarthomebeginner
Enter Ssh Credentials

Optionally, if you want to be able to browse your folders using SFTP, enable the SFTP option at the end of the page and enter the remote folder you want to access.

Optionally, Enable Sftp On Guacamole Ssh Connections
Optionally, Enable Sftp On Guacamole Ssh Connections

That is it. Save the connection, return to your home screen and try it out. You should reach the command prompt of your SSH server.

Ssh Connection On Guacamole
Ssh Connection On Guacamole

While on SSH connection, if you want to access the SFTP browser, you may do so from the Guacamole context menu, which can be activated using Ctrl+Alt+Shift.

Access Sftp Browser From Guacamole Context Menu (Ctrl+Alt+Shift)
Access Sftp Browser From Guacamole Context Menu (Ctrl+Alt+Shift)

3. Windows RDP using Gaucamole

Thanks to David Woody for providing the screenshots for setting up Windows Remote Desktop Protocol with Guacamole.

Note that you will need a version of Windows that supports RDP.

As with other connections, go to Settings->Connections and add a new connection. Provide a descriptive name and choose RDP for protocol.

Setting Up New Guacamole Rdp Connection
Setting Up New Guacamole Rdp Connection

Next, provide connection details for the RDP connection as shown below: IP address or hostname, the RDP port (default is 3389), username, and password.

Guacamole Rdp Connection Settings
Guacamole Rdp Connection Settings

There are several more settings that you can configure if you know what you are doing. Otherwise, you can leave them be and you are good to go.

Apache Guacamole Setup on Docker - Final Remarks

Configuring Guacamole for SSH and VNC was one of the best things I did for my smart home setup. And with my recent move to Traefik 2, I added Authelia to significantly improve the security of Guacamole app.

In addition to VNC and SSH/SFTP, I have also tried Telnet and it worked great. However, I could not test RDP connections to Windows because the version of Windows 10 I use does not support RDP (SMH!). If RDP worked for any of you and you are willing to share the steps/screenshots, I would be glad to add it to this guide to help others (Thanks! David Woody).

I hope this Guacamole Docker tutorial was helpful and you were able to successfully setup Guacamole for remote connections. Please share any thoughts or feedback using the comments.

Be the 1 in 200,000. Help us sustain what we do.
10 / 150 by Dec 31, 2024
Join Us (starting from just $1.67/month)


Anand is a self-learned computer enthusiast, hopeless tinkerer (if it ain't broke, fix it), a part-time blogger, and a Scientist during the day. He has been blogging since 2010 on Linux, Ubuntu, Home/Media/File Servers, Smart Home Automation, and related HOW-TOs.