Apache Guacamole
No necesita la instalación de agentes o ningún tipo de software cliente. Gracias a HTML5, una vez Guacamole está instalado en un servidor, lo único necesario para acceder a tu desktop es un Navegador WEB.
un despliegue típico de Guacamole incluye tres servicios separados:
- guacamole/guacd: es el servicio guacd. guacamole-server tiene soporte para VNC, RDP, SSH, telnet, y Kubernetes.
- guacamole/guacamole: proporciona las aplicaciones web de Guacamole ejecutadas en Tomcat con soporte para WebSocket.
- mysql o postgresql: proporciona la base de datos que usará Guacamole para validación y guarda los datos de configuración de las conexiones.
Requisitos
-
- Docker instalado
siguiendo los pasos deinstalar - Portainer
configurado siguiendo los pasos deinstalar portainer. (opcional)instalado NGINXProxymanagerInversosiguiendoTraefiklos pasos de instalaro NGINX Proxy Manager.(opcional)Opcional pero recomendadoTraefik
configurado siguiendo los pasos deinstalar Traefik. (opcional) - Docker instalado
Enlaces
Imagenes
- guacamole/guacamole – Docker Image | Docker Hub
- guacamole/guacd – Docker Image | Docker Hub
- mariadb – Official Image | Docker Hub
Portainer- Agregar nuevo «stack»Portainer
Add a new stack – Portainer Documentation
Web editor
En Portainer «Stack» agregamos nuevo usando el editor WEB pegando el contenido del fichero «docker-compose.yml» y el contenido del fichero de variables modificando los valores necesarios
Fichero de variablesVariables
TZ=Europe/Madrid
VERSION=1.6.0
GUACD_HOSTNAME=guacd
MYSQL_HOSTNAME=guacdb
MYSQL_ROOT_PASSWORD=#GeneraPassword
MYSQL_DATABASE=guacamole_db
MYSQL_USER=guacamole_user
MYSQL_PASSWORD=#GeneraPassword
MYSQL_AUTO_CREATE_ACCOUNTS=true
MARIADB_AUTO_UPGRADE=1
Fichero docker-compose inicial
services:
guacdb:
container_name: guacdb
image: mariadb
restart: unless-stopped
env_file: stack.env
volumes:
- db:/var/lib/mysql
networks:
- backend
volumes:
db:
networks:
backend:
proxy:
external: true
Iniciando la base de datos
Si la base de datos no ha sido iniciada aun con el esquema de Guacamole, será un paso previo usando Guacamole. Un script para generar lo necesario en SQL está incluido en la imagen de Guacamole .
# Genera script SQL para iniciar una nueva base de datos
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > guac_db.sql
# Copia script de inicialización en el contenedor
docker cp guac_db.sql guacdb:/guac_db.sql
# Inicializa la base de datos
docker exec -it guacdb bash -c "cat /guac_db.sql | mariadb -u root -p guacamole_db"
Ampliando el fichero docker-compose
services:
guacdb:
container_name: guacdb
image: mariadb
restart: unless-stopped
env_file: stack.env
volumes:
- db:/var/lib/mysql
networks:
- backend
guacd:
container_name: guacd
image: guacamole/guacd:$VERSION
restart: unless-stopped
tmpfs:
- /drive:rw,noexec,nosuid,nodev,size=1g
networks:
- backend
guacamole:
container_name: guacamole
image: guacamole/guacamole:$VERSION
restart: unless-stopped
env_file: stack.env
depends_on:
- guacdb
- guacd
ports:
- 8080:8080
networks:
- backend
- proxy
volumes:
db:
networks:
backend:
proxy:
external: true
En este punto ya puedes ir a http://my.docker.ip.address:8080/guacamole y entrar con guacadmin/guacadmin.
Publicando detrás de un proxy
Crear registro DNS
En el proveedor que aloja el servidor DNS público, crear un registro DNS que resuelva la IP pública que llega al Proxy hacia un nombre del estilo "guacamole.domain.com"
NGINX proxy
Using a reverse proxy for SSL termination — Apache Guacamole Manual v1.6.0
Para publicar el contenedor detrás de NGINX proxy, como el stack está en la red proxy solo deberás crear un nuevo host
Crear un nuevo "proxy host"
Añade un nuevo proxy host con el nombre de dominio creado en el paso anterior redirigido hacia el nombre del contenedor y el puerto que use:

Si queremos eliminar el "path" /guacamole de la URL, agregamos en las propiedades avanzadas del proxy host la siguiente configuración avanzada:
location / {
proxy_pass http://guacamole:8080/guacamole/;
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;
}
Traefik

Para publicar el contenedor detrás del proxy Traefik, deberás añadir al fichero docker-compose.yaml las siguientes etiquetas al servicio guacamole
labels:
- traefik.enable=true
- traefik.http.routers.guacamole.rule=Host(`guacamole.$DOMAIN`)
- traefik.http.routers.guacamole.tls=true
- traefik.http.routers.guacamole.tls.certresolver=letsencrypt
- traefik.http.routers.guacamole.middlewares=guacamole-prefix
- traefik.http.middlewares.guacamole-prefix.addprefix.prefix=/guacamole
Validación de usuarios
OpenID (Azure AD)
En el caso de usar usuarios validados con AzureID no se podrán hacer modificaciones desde el UI. Para configurar permisos usar mejor grupos.
Microsoft
Registra la aplicación siguiendo estos pasos:
- Validate en el portal de Azure (https://portal.azure.com/) en el servicio de "Microsoft Entra ID"
- En Administrar -> Registro de aplicaciones -> Nuevo Registro

Añade este contenido al fichero de variables .env
AZURE_TENANT_ID=#Id. de directorio (inquilino)
OPENID_ENABLED=true
OPENID_CLIENT_ID=#Id. de aplicación (cliente)
OPENID_REDIRECT_URI=https://guacamole.$DOMAIN
OPENID_AUTHORIZATION_ENDPOINT=https://login.microsoftonline.com/${AZURE_TENANT_ID}/oauth2/v2.0/authorize
OPENID_JWKS_ENDPOINT=https://login.microsoftonline.com/${AZURE_TENANT_ID}/discovery/v2.0/keys
OPENID_ISSUER=https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0
OPENID_USERNAME_CLAIM_TYPE=email
OPENID_SCOPE=openid email profile
EXTENSION_PRIORITY=openid
En la configuración de la "Autenticación" seleccionar "Tokens de id."

Microsoft Active Directory (LDAP)
Nota: Si configuramos la conexión con Active Directory, tenemos que crear en nuestro Directorio Activo (dentro de nuestra Base DN) un usuario llamado "guacadmin", y NO debe tener la misma contraseña que el usuario de MySQL. Podremos validarnos con usuarios LDAP y usuarios MySQL
Añade este contenido al fichero de variables .env
# Active Directory
LDAP_HOSTNAME=DIRECCIÓN_IP_CONTROLADOR_DE_DOMINIO
LDAP_PORT=389 # O seguro: 636
LDAP_USER_BASE_DN=OU=ruta,DC=dominio,DC=local
LDAP_USERNAME_ATTRIBUTE=samAccountName
LDAP_CONFIG_BASE_DN=OU=ruta,DC=dominio,DC=local
LDAP_ENCRYPTION_METHOD=none # O seguro: ssl, starttls
LDAP_SEARCH_BIND_DN=cn=usuario_LDAP,OU=ruta,DC=dominio,DC=local
LDAP_SEARCH_BIND_PASSWORD=password
LDAP_USER_SEARCH_FILTER=(memberOf=CN=guacamoleUsers,OU=ruta,DC=dominio,DC=local)
Para estar seguro que esto funciona, podemos acceder al contenedor «guacamole» y ejecutar el siguiente comando para ver si se ha añadido la configuración de LDAP al fichero guacamole.properties:
docker exec -it guacamole bash
cat /home/guacamole/.guacamole/guacamole.properties
Y podremos ver el contenido del fichero guacamole.properties
Autologin a traves de URL
http://my.docker.ip.address:8080/guacamole/#/?serverid=ZZZZZZ&username=USER&password=PASS
Parameter tokens
The values of connection parameters can contain «tokens» which will be replaced by Guacamole when used. These tokens allow the values of connection parameters to vary dynamically by the user using the connection, and provide a simple means of forwarding authentication information without storing that information in the connection configuration itself, so long as the remote desktop connection uses the same credentials as Guacamole.
Each token is of the form ${TOKEN_NAME}, where TOKEN_NAME is some descriptive name for the value the token represents. Tokens with no corresponding value will never be replaced, but should you need such text within your connection parameters, and wish to guarantee that this text will not be replaced with a token value, you can escape the token by adding an additional leading «$», as in «$${TOKEN_NAME}».
${GUAC_USERNAME}
The username of the current Guacamole user. When a user accesses this connection, this token will be dynamically replaced with the username they provided when logging in to Guacamole.
${GUAC_PASSWORD}
The password of the current Guacamole user. When a user accesses this connection, this token will be dynamically replaced with the password they used when logging in to Guacamole.


