Installing Apache Guacamole on Docker, configuring HTTPS access and Active Directory integration


Basic configuration


install Docker Engine - Community and Docker Compose as described here

create the /etc/docker/guacamole/docker-compose.yml file

version: '3'

networks:
  net:
    ipam:
      config:
        - subnet: 192.168.100.1/24

volumes:
  db:
  shared:

services:
  db:
    container_name: guacamole_db
    image: mysql/mysql-server
    networks:
      - net
    volumes:
      - db:/var/lib/mysql
    restart: always

  guacd:
    container_name: guacamole_guacd
    image: guacamole/guacd
    networks:
      - net
    volumes:
      - shared:/home/guacd/shared
    restart: always

  guacamole:
    depends_on:
      - db
      - guacd
    container_name: guacamole_guacamole
    image: guacamole/guacamole
    networks:
      - net
    ports:
      - 8080:8080
    environment:
      - GUACD_HOSTNAME=guacd
      - MYSQL_HOSTNAME=db
      - MYSQL_DATABASE=guacamole
      - MYSQL_USER=guacamole
      - MYSQL_PASSWORD=some_pass
    restart: always

create the containers

docker-compose -f /etc/docker/guacamole/docker-compose.yml up --no-start

create the database initialization file

docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > /tmp/initdb.sql

copy the created file into the database container

docker cp /tmp/initdb.sql guacamole_db:/tmp/initdb.sql

start the database container

docker container start guacamole_db

search the database log for the automatically generated root password

docker logs guacamole_db | grep PASSWORD

log in to the MySQL CLI

docker exec -it guacamole_db mysql -u root -p

change the root password

alter user 'root'@'localhost' identified by 'another_pass';

create a new database

create database guacamole;

create a new user

create user 'guacamole'@'%' identified with mysql_native_password by 'some_pass';

grant the user full access to the database

grant all privileges on guacamole.* to 'guacamole'@'%';

initialize the database

use guacamole;
source /tmp/initdb.sql;

log out of the MySQL CLI

quit;

start the guacd container

docker container start guacamole_guacd

create a new folder inside the container in which files copying to and from the remote host will be stored

docker exec -it guacamole_guacd mkdir /home/guacd/shared
docker exec -it guacamole_guacd chown guacd:guacd /home/guacd/shared

note: for every user the corresponding subfolder will be created

start the guacamole container

docker container start guacamole_guacamole

open a web browser, navigate to the http://guacamole.domain.local:8080/guacamole/ web page and log in with the username "guacadmin" and the password "guacadmin"

click "Setting - Connections" and create a new connection

Edit connection
   Name - test
   Protocol - rdp
Parameters
   Network
      Hostname - test.domain.local
      Port - 3389
   Authentication
      Security mode - RDP encryption
   Clipboard
      Line endings - Windows (CRLF)
   Device redirection
      Enable drive - enabled
      Drive name - Shared Drive
      Drive path - /home/guacd/shared/${GUAC_USERNAME}
      Automatically create drive - enabled

note: depending on the remote host another connection settings may be needed, e. g. "NLA" security mode

return to the main page and try to establish a connection

note: in order to copy files to and from the remote host you should first open the side panel with the "Ctrl + Shift + Alt" combination


Configure HTTPS


edit the /etc/docker/guacamole/docker-compose.yml file

version: '3'

networks:
  net:
    ipam:
      config:
        - subnet: 192.168.100.1/24

volumes:
  db:
  shared:
  proxy:

services:
  db:
    container_name: guacamole_db
    image: mysql/mysql-server
    networks:
      - net
    volumes:
      - db:/var/lib/mysql
    restart: always

  guacd:
    container_name: guacamole_guacd
    image: guacamole/guacd
    networks:
      - net
    volumes:
      - shared:/home/guacd/shared
    restart: always

  guacamole:
    depends_on:
      - db
      - guacd
    container_name: guacamole_guacamole
    image: guacamole/guacamole
    networks:
      - net
    environment:
      - GUACD_HOSTNAME=guacd
      - MYSQL_HOSTNAME=db
      - MYSQL_DATABASE=guacamole
      - MYSQL_USER=guacamole
      - MYSQL_PASSWORD=some_pass
    restart: always

  proxy:
    depends_on:
      - guacamole
    container_name: guacamole_proxy
    image: nginx
    networks:
      - net
    ports:
      - 443:443
    volumes:
      - proxy:/etc/nginx
    restart: always

recreate and restart the containers

docker-compose -f /etc/docker/guacamole/docker-compose.yml up -d

connect to the proxy container

docker exec -ti guacamole_proxy /bin/bash

install "nano" text editor

apt-get update && apt-get install -y nano

edit the /etc/nginx/conf.d/default.conf file

  listen 443 ssl;

  ssl_certificate /etc/nginx/server.crt;
  ssl_certificate_key /etc/nginx/server.key;

  location /guacamole/ {
      proxy_pass http://guacamole:8080;
      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;
      access_log off;
   }

disconnect from the container

exit

generate a private key, issue a certificate and copy them into the container

docker cp /root/server.crt guacamole_proxy:/etc/nginx/server.crt
docker cp /root/server.key guacamole_proxy:/etc/nginx/server.key

note: information about managing certificates and private keys can be found here and here

restart the container

docker container restart guacamole_proxy


Configure LDAPS


edit the /etc/docker/guacamole/docker-compose.yml file

version: '3'

networks:
  net:
    ipam:
      config:
        - subnet: 192.168.100.1/24

volumes:
  db:
  shared:
  proxy:

services:
  db:
    container_name: guacamole_db
    image: mysql/mysql-server
    networks:
      - net
    volumes:
      - db:/var/lib/mysql
    restart: always

  guacd:
    container_name: guacamole_guacd
    image: guacamole/guacd
    networks:
      - net
    volumes:
      - shared:/home/guacd/shared
    restart: always

  guacamole:
    depends_on:
      - db
      - guacd
    container_name: guacamole_guacamole
    image: guacamole/guacamole
    networks:
      - net
    environment:
      - GUACD_HOSTNAME=guacd
      - MYSQL_HOSTNAME=db
      - MYSQL_DATABASE=guacamole
      - MYSQL_USER=guacamole
      - MYSQL_PASSWORD=some_pass
      - LDAP_HOSTNAME=dc.domain.local
      - LDAP_PORT=636
      - LDAP_ENCRYPTION_METHOD=ssl
      - LDAP_SEARCH_BIND_DN=CN=guacamole,OU=Special Users,DC=domain,DC=local
      - LDAP_SEARCH_BIND_PASSWORD=one_more_pass
      - LDAP_USER_BASE_DN=OU=Employees,DC=domain,DC=local
      - LDAP_USERNAME_ATTRIBUTE=sAMAccountName
      - LDAP_USER_SEARCH_FILTER=(&(objectclass=user)(memberOf=CN=Guacamole users,OU=Local Groups,DC=domain,DC=local))
    restart: always

  proxy:
    depends_on:
      - guacamole
    container_name: guacamole_proxy
    image: nginx
    networks:
      - net
    ports:
      - 443:443
    volumes:
      - proxy:/etc/nginx
    restart: always

add the root certificate into the keystore

docker cp /tmp/root.crt guacamole_guacamole:/tmp/root.crt
docker exec -ti -u root guacamole_guacamole keytool -trustcacerts -alias domain.local -import -keystore /opt/java/openjdk/jre/lib/security/cacerts -storepass changeit -file /tmp/root.crt

recreate and restart the containers

docker-compose -f /etc/docker/guacamole/docker-compose.yml up -d

note 1: in this configuration we've just configured the authentication but in order to grant a user access to a connection, this user must be manually created in the web console first

note 2: in order to configure LDAP instead of LDAPS you should change the value of the "LDAP_PORT" and "LDAP_ENCRYPTION_METHOD" variables to "389" and "none" respectively

Leave a Reply