Skip to content

Installing Guacamole

Pre-Requisites

If you know my guides, you know I generally prefer:

  • A docker host running either debian or fedora (this guide is using Fedora Server 37)
  • Visual Studio Code via SSH for administration (you can follow this post for setting that up)
  • A reverse proxy (this guide will be using Caddy, which you can read more about here)
  • That’s it!

Aside from that, we will also have (optionally) a Windows host to demonstrate the capabilities of guacamole.

Setup

Guacamole can be built from source, but the easiest way to get started (and our preference) is using the official guacamole containers. Guacamole requires three components

  • The guacamole frontend (which is a tomcat based browser utility)
  • One or more Guacd agents (a backend server that facilitates the protocol translations)
  • A Database (postgres is the preference)

We can set up all three using the following Docker Compose file:

Info

we add the directive label: disable in the compose to prevent SELinux related issues in fedora-based distributions. We are also adding two networks, one for the reverse proxy and one for internal guacamole connections.

services:
  guacamole:
    image: guacamole/guacamole:latest
    container_name: guacamole
    security_opt:
      - label:disable
    volumes:
      - ./container-data/extensions:/guacamole-home/extensions
      - /etc/localtime:/etc/localtime:ro
    environment:
      - GUACD_HOSTNAME=guacamole-guacd
      - GUACAMOLE_HOME=/guacamole-home
      - POSTGRES_HOSTNAME=guacamole-db
      - POSTGRES_DATABASE=guacamole_db
      - POSTGRES_USER=guacamole
      - POSTGRES_PASSWORD=\${POSTGRES_PASSWORD}
    ports:
      - 8080:8080
    restart: always
    networks:
      - reverseproxy-nw
      - guacamole-nw

  guacamole-guacd:
    image: guacamole/guacd:latest
    container_name: guacamole-guacd
    security_opt:
      - label:disable
    networks:
      - guacamole-nw
    restart: always
    volumes:
      - ./container-data/records:/record
      - ./container-data/drive:/drive
      - /etc/localtime:/etc/localtime:ro

  guacamole-db:
    image: postgres:13
    container_name: guacamole-db
    security_opt:
      - label:disable
    restart: always
    environment:
      - POSTGRES_DB=guacamole_db
      - POSTGRES_USER=guacamole
      - POSTGRES_PASSWORD=\${POSTGRES_PASSWORD}
    volumes:
      - ./container-data/db:/var/lib/postgresql/data
      - /etc/localtime:/etc/localtime:ro
      - ./container-data/db-init/initdb.sql:/docker-entrypoint-initdb.d/initdb.sql # can be removed after initialization
    networks:
      - guacamole-nw

networks:
  guacamole-nw:
  reverseproxy-nw:
    external: true

We also want to put in a .env file with the postgres password.

POSTGRES_PASSWORD=mysupersecretpassword

You can see me do the following in /mnt/containers/guacamole below:

Initialise the Database

Unfortunately guacamole doesn’t automatically initialize a new database, we have to do it manually. Luckily that’s not too hard. You can run the following to initialise the database (changing the absolute path if necessary):

mkdir -p /mnt/containers/guacamole/container-data/db-init
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgres > /mnt/containers/guacamole/container-data/db-init/initdb.sql

Starting the container

Let’s bring it up!

 docker-compose up -d

If all goes well, you should find a prompt at http://<your-ip>:8080/guacamole

Info

If you get an error, the DB initialization probably did not go through properly. Delete any volume data (postgres will only run initialization automatically the first time) and repeat the steps.

Setting up a Reverse Proxy

Success! Well except we’re running over unencrypted http and using an IP instead of a domain. Let’s set up a reverse proxy to fix these problems.

Info

If you do not have a reverse proxy, you can follow my caddy guide here or my nginx proxy manager guide here.

First, a caddyfile. We’ve done a couple extra steps to help secure our connection:

remote.<yourdomain>.com {
    # only allow connections from internal subnets
    @localOnly {
        remote_ip forwarded 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
    }
    handle @localOnly {
        # redirect all root paths to the guacamole subpath
        @notGuac {
            not path /guacamole*
        }
        redir @notGuac /guacamole/
        reverse_proxy guacamole:8080 {
            # allow long timeouts to prevent resetting active sessions
            flush_interval -1
        }
    }
}

Final Test

Alright, with the reverse proxy setup, we should now have a functional login screen! Attempt to log in with guacadmin/guacadminand see if you get in.

Info

You can now disable the port mapping in the docker compose file if you wish.

Moving On

Alright, we have a guacamole server going. Spectacular! Now we actually need to do something with it. Let’s cover that in Configuring Guacamole.