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