Apache Guacamole is a web-accessible remote desktop gateway that supports RDP, VNC, and text-based connections via SSH and telnet.

Quick introduction[edit | edit source]

The Guacamole server contains two parts: The web application itself running on Tomcat, and the guacamole proxy service (guacd) that connects to the remote desktop endpoints. Under the hood, the RDP/VNC/SSH connection data from guacd is sent to the Guacamole server using the Guacamole protocol which is then relayed back to the user and rendered using Guacamole's HTML5 based client. As a result, the client is unaware of the underlying protocol (which actually poses several limitations which will be covered later).

Limitations[edit | edit source]

Guacamole's documentation doesn't list limitations clearly and these are the limitations that I've encountered after playing with it for a short period.

  • Guacamole must connect to a VNC enabled desktop either anonymously or with pre-defined credentials. You cannot have Guacamole 'login' for a user using their Guacamole credentials.
  • RDP works like VNC but with NLA support for RDP (I haven't tested this) which would allow the user to enter their RDP credentials when connecting. There is no way to make Guacamole pass credentials to RDP however, so you can't make Guacamole work like a VDI using a pool of desktops.
  • In VNC, sessions cannot be 'resized' on the fly. Guacamole's protocol doesn't seem to support it.
  • In VNC, copy/paste clipboard data cannot be copied out of a remote desktop; it can only be copied in. This works if I use x11vnc as the VNC server rather than the Gnome built-in screen sharing feature.
  • VNC based connections are extremely slow. Using x11vnc is slightly better than vino, but there's easily 1-2 second delays on my local instance all hosted on the same hypervisor and accessed via a local gigabit LAN connection.
  • VNC connection settings hard code authentication credentials. You cannot 'login' as a user on the remote desktop

Setup[edit | edit source]

You can either install Guacamole directly on a server or use the prebuilt Docker containers. Review the documentation at:

Setup Guacamole using Docker Compose[edit | edit source]

The easiest way to set up Guacamole is with the following docker-compose.yml stack. I am using Traefik as the reverse proxy which handles SSL termination and strips the /guacamole from the URI path, but is completely optional. If you don't use Traefik, simply remove the Traefik network and labels and serve port 8080.

First, create the following docker-compose.yml file.

version: '3.3'

services:
  guacd:
    image: guacamole/guacd
    restart: unless-stopped
    volumes:
      - /volumes/guacamole/guacd/drive:/drive:rw
      - /volumes/guacamole/guacd/record:/record:rw
    networks:
      - internal

  guacamole:
    image: guacamole/guacamole
    restart: unless-stopped
    depends_on:
      - guacd
      - db
    environment:
      GUACD_HOSTNAME: guacd
      MYSQL_HOSTNAME: db
      MYSQL_DATABASE: guacamole
      MYSQL_USER: guacamole
      MYSQL_PASSWORD: 41e930486c6de5ebda96  <-- change me
    expose:
      - "8080"
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - traefik.http.middlewares.guacamole-prefix.addprefix.prefix=/guacamole
      - traefik.http.middlewares.guacamole-https-redirect.redirectscheme.scheme=https
      # http
      - traefik.http.routers.guacamole.entrypoints=http
      - traefik.http.routers.guacamole.rule=Host(`guacamole.steamr.com`)
      - traefik.http.routers.guacamole.service=guacamole-https
      - traefik.http.routers.guacamole.middlewares=guacamole-https-redirect
      # https
      - traefik.http.routers.guacamole-https.entrypoints=https
      - traefik.http.routers.guacamole-https.rule=Host(`guacamole.steamr.com`)
      - traefik.http.routers.guacamole-https.tls=true
      - traefik.http.routers.guacamole-https.service=guacamole-https
      - traefik.http.services.guacamole-https.loadbalancer.server.port=8080
      - traefik.http.routers.guacamole-https.middlewares=guacamole-prefix
    networks:
      - internal
      - traefik

  db:
    image: mariadb:latest
    environment:
      MYSQL_ROOT_PASSWORD: 41e930486c6de5ebda96  <-- change me
      MYSQL_USER: guacamole
      MYSQL_PASSWORD: 41e930486c6de5ebda96  <-- change me
      MYSQL_DATABASE: guacamole
    restart: unless-stopped
    volumes:
      # To obtain this file, run: docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
      - /volumes/guacamole/initdb.sql:/initdb.sql
      - /volumes/guacamole/db:/var/lib/mysql/:rw
    networks:
      - internal

networks:
  internal:
  traefik:
    name: traefik
    external: true

Next, bring the container stack up:

# docker-compose pull
# docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > /volumes/guacamole/initdb.sql
# docker-compose up -d

Set up the database:

## Figure out which container is your database and then load the initial database
# docker ps | grep guacamole
# docker exec -ti $DB_CONTAINER_ID bash
root@db # mysql -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE < /initdb.sql
Guacamole Login
Guacamole Login

You should be able to reach the Guacamole server and see a login page. If not, restart the Guacamole container and try again. If you see an error message, you likely misconfigured the database connection or didn't populate the Guacamole database properly.

Login using the following credentials:

  • Username: guacadmin
  • Password: guacadmin

When setting up a new connection, enter 'guacd' as the Guacamole proxy hostname, 4822 as the port, and 'none' for encryption.

Using Guacamole[edit | edit source]

Review the documentation at https://guacamole.apache.org/doc/gug/using-guacamole.html.

Alt + Ctrl + Shift is used to bring up or hide the Guacamole menu sidebar.