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