--- title: "Cómo instalar Apache Guacamole con Docker en Ubuntu 24.04" description: "Despliega Apache Guacamole con Docker Compose y PostgreSQL en Ubuntu 24.04, publícalo con Nginx y HTTPS, activa TOTP y accede por SSH y RDP desde el navegador." category: "Acceso Remoto" language: es source: https://cubepath.com/es/docs/acceso-remoto/apache-guacamole-gateway-de-acceso-remoto updated: 2026-09-25 --- # Cómo instalar Apache Guacamole con Docker en Ubuntu 24.04 Apache Guacamole es una pasarela de escritorio remoto que funciona desde el navegador: los usuarios abren una página web y se conectan a servidores por SSH, RDP o VNC sin instalar ningún cliente. Solo el servidor de Guacamole necesita alcanzar los equipos de destino, así que no hace falta exponer los puertos 22 o 3389 a Internet. En este tutorial desplegarás Guacamole 1.6 con Docker Compose y PostgreSQL en Ubuntu 24.04, lo publicarás detrás de Nginx con un certificado de Let's Encrypt, activarás el doble factor TOTP y crearás tus primeras conexiones. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, al menos 2 GB de RAM y 2 vCPU, por ejemplo un VPS de CubePath. Cada sesión RDP activa consume memoria en `guacd`, así que calcula más para muchos usuarios simultáneos. - Un usuario no root con privilegios `sudo` que pertenezca al grupo `docker`. - Docker Engine y el plugin de Docker Compose instalados desde el repositorio oficial de Docker. - Un dominio o subdominio (en la guía, `your_domain`) con un registro A apuntando a la IP pública del servidor. - Conectividad de red desde este servidor hasta los equipos a los que quieras acceder (por red privada o por Internet). ## Paso 1: Preparar el directorio y los secretos Crea el directorio del proyecto y haz que pertenezca a tu usuario: ```bash sudo mkdir -p /opt/guacamole/initdb sudo chown -R "$USER": /opt/guacamole cd /opt/guacamole ``` Genera una contraseña aleatoria para la base de datos y guárdala en un archivo `.env`, que Docker Compose lee automáticamente: ```bash echo "POSTGRES_PASSWORD=$(openssl rand -base64 24)" > .env chmod 600 .env ``` ## Paso 2: Generar el esquema de la base de datos La imagen de Guacamole incluye un script que imprime el SQL necesario para crear las tablas. Guárdalo en `initdb/`, que PostgreSQL ejecutará automáticamente la primera vez que arranque con un volumen vacío: ```bash docker run --rm guacamole/guacamole:1.6.0 /opt/guacamole/bin/initdb.sh --postgresql > initdb/initdb.sql ``` Comprueba que el archivo contiene las tablas: ```bash grep -c "CREATE TABLE" initdb/initdb.sql ``` ```output 23 ``` El número exacto puede variar entre versiones; lo importante es que no sea cero. ## Paso 3: Crear el archivo de Docker Compose El despliegue tiene tres contenedores: - `guacd`: el demonio que habla SSH, RDP y VNC con los equipos de destino. - `postgres`: guarda usuarios, conexiones, permisos e historial. - `guacamole`: la aplicación web (Tomcat) que usan los navegadores. Crea el archivo: ```bash nano /opt/guacamole/compose.yaml ``` ```yaml services: guacd: image: guacamole/guacd:1.6.0 restart: unless-stopped postgres: image: postgres:16 restart: unless-stopped environment: POSTGRES_DB: guacamole_db POSTGRES_USER: guacamole_user POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - ./initdb:/docker-entrypoint-initdb.d:ro - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U guacamole_user -d guacamole_db"] interval: 10s timeout: 5s retries: 5 guacamole: image: guacamole/guacamole:1.6.0 restart: unless-stopped depends_on: guacd: condition: service_started postgres: condition: service_healthy environment: GUACD_HOSTNAME: guacd POSTGRESQL_HOSTNAME: postgres POSTGRESQL_DATABASE: guacamole_db POSTGRESQL_USERNAME: guacamole_user POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD} REMOTE_IP_VALVE_ENABLED: "true" ports: - "127.0.0.1:8080:8080" volumes: pgdata: ``` Dos detalles importantes: - El puerto 8080 solo se publica en `127.0.0.1`. Los usuarios entrarán por Nginx con HTTPS, nunca directamente a Tomcat. Además, los puertos que Docker publica en todas las interfaces se saltan las reglas de UFW, así que limitarlo a localhost es necesario. - `REMOTE_IP_VALVE_ENABLED` hace que Guacamole registre la IP real del usuario (enviada por Nginx en `X-Forwarded-For`) en lugar de la del proxy. ## Paso 4: Arrancar Guacamole Descarga las imágenes y levanta los servicios: ```bash docker compose up -d docker compose ps ``` ```output NAME IMAGE SERVICE STATUS PORTS guacamole-guacamole-1 guacamole/guacamole:1.6.0 guacamole Up 20 seconds 127.0.0.1:8080->8080/tcp guacamole-guacd-1 guacamole/guacd:1.6.0 guacd Up 31 seconds 4822/tcp guacamole-postgres-1 postgres:16 postgres Up 31 seconds (healthy) ``` Comprueba que la aplicación responde y que ha cargado la autenticación con PostgreSQL: ```bash curl -sI http://127.0.0.1:8080/guacamole/ | head -n 1 docker compose logs guacamole | grep -i "postgresql" ``` ```output HTTP/1.1 200 ... Extension "PostgreSQL Authentication" (postgresql) loaded. ``` Si no aparece esa línea, revisa las variables `POSTGRESQL_*` y los logs completos con `docker compose logs guacamole`. ## Paso 5: Publicar Guacamole con Nginx y HTTPS Instala Nginx y Certbot desde los repositorios de Ubuntu: ```bash sudo apt update sudo apt install nginx certbot python3-certbot-nginx ``` Crea el sitio de Nginx. Guacamole usa WebSocket para las sesiones, por eso se reenvían las cabeceras `Upgrade` y `Connection` y se desactiva el buffering: ```bash sudo nano /etc/nginx/sites-available/guacamole ``` ```nginx server { listen 80; listen [::]:80; server_name your_domain; location = / { return 301 /guacamole/; } location /guacamole/ { proxy_pass http://127.0.0.1:8080; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_read_timeout 1h; client_max_body_size 1g; access_log off; } } ``` `client_max_body_size` permite subir archivos a las sesiones y `proxy_read_timeout` evita que Nginx corte sesiones con poca actividad. Activa el sitio, desactiva el sitio por defecto y comprueba la sintaxis: ```bash sudo ln -s /etc/nginx/sites-available/guacamole /etc/nginx/sites-enabled/ sudo rm /etc/nginx/sites-enabled/default sudo nginx -t sudo systemctl reload nginx ``` ```output nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` Abre en el cortafuegos SSH y los puertos 80 y 443: ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw enable ``` Obtén el certificado. Certbot modifica el sitio para servirlo por HTTPS y redirigir HTTP: ```bash sudo certbot --nginx -d your_domain ``` Comprueba la renovación automática: ```bash sudo certbot renew --dry-run ``` ## Paso 6: Sustituir la cuenta de administrador por defecto Abre `https://your_domain/` en el navegador. Serás redirigido a `/guacamole/` y verás la pantalla de inicio de sesión. La base de datos se crea con el usuario `guacadmin` y la contraseña `guacadmin`, que debes eliminar cuanto antes: 1. Inicia sesión con `guacadmin` / `guacadmin`. 2. Abre el menú de usuario (arriba a la derecha) y entra en **Settings > Users > New User**. 3. Escribe tu nombre de usuario y una contraseña fuerte, marca todos los permisos de la sección **Permissions** (incluido **Administer system**) y guarda. 4. Cierra sesión, entra con el nuevo usuario y, en **Settings > Users**, abre `guacadmin` y pulsa **Delete**. ## Paso 7: Activar la autenticación de doble factor (TOTP) La imagen oficial incluye la extensión TOTP; basta con activarla con una variable de entorno. Añádela al servicio `guacamole` en `compose.yaml`: ```bash nano /opt/guacamole/compose.yaml ``` ```yaml environment: GUACD_HOSTNAME: guacd POSTGRESQL_HOSTNAME: postgres POSTGRESQL_DATABASE: guacamole_db POSTGRESQL_USERNAME: guacamole_user POSTGRESQL_PASSWORD: ${POSTGRES_PASSWORD} REMOTE_IP_VALVE_ENABLED: "true" TOTP_ENABLED: "true" ``` Recrea el contenedor para aplicar el cambio: ```bash docker compose up -d ``` En el siguiente inicio de sesión, Guacamole mostrará un código QR para registrar el dispositivo en una aplicación de autenticación (Aegis, Google Authenticator, 1Password...). A partir de ahí, cada acceso pedirá la contraseña y el código de 6 dígitos. Si un usuario pierde el dispositivo, un administrador puede reiniciar su registro TOTP desde la ficha del usuario en **Settings > Users**, en la sección de atributos de TOTP. ## Paso 8: Crear conexiones SSH y RDP Las conexiones se gestionan en **Settings > Connections > New Connection**. Para un servidor Linux por SSH: 1. **Name**: un nombre descriptivo, por ejemplo `web-01 (SSH)`. **Protocol**: `SSH`. 2. En **Parameters > Network**: **Hostname** con la IP privada o el nombre del servidor y **Port** `22`. 3. En **Authentication**: el **Username** y, preferiblemente, una **Private key** en formato OpenSSH en lugar de una contraseña. Si dejas vacíos usuario y contraseña, Guacamole los pedirá al conectar. 4. Guarda. Para un servidor Windows por RDP: 1. **Protocol**: `RDP`. **Hostname**: la IP del servidor. **Port**: `3389`. 2. En **Authentication**: **Username**, **Password** y, si pertenece a un dominio, **Domain**. 3. **Security mode**: `NLA (Network Level Authentication)`. Si el servidor usa un certificado autofirmado, marca **Ignore server certificate**. 4. Guarda. Vuelve a la pantalla de inicio (menú de usuario > **Home**) y haz clic en la conexión. Se abrirá la sesión en la misma pestaña. Pulsa `Ctrl+Alt+Shift` para abrir el menú lateral de Guacamole, desde el que puedes copiar y pegar texto o transferir archivos. Asigna las conexiones a usuarios o grupos en **Settings > Users** o **Settings > Groups**, dentro de la sección **Connections** de cada uno. Así cada persona solo ve los equipos que le corresponden. ## Paso 9: Copias de seguridad y actualizaciones Toda la configuración está en PostgreSQL. Haz una copia con `pg_dump`: ```bash cd /opt/guacamole docker compose exec -T postgres pg_dump -U guacamole_user guacamole_db | gzip > "guacamole-$(date +%F).sql.gz" ls -lh guacamole-*.sql.gz ``` Guarda esas copias fuera del servidor. Para actualizar a una versión nueva, lee primero las notas de la versión: algunas incluyen scripts de actualización del esquema (se publican junto a la extensión JDBC en la página de descargas de cada versión) que debes aplicar a la base de datos antes de cambiar los tags de `guacd` y `guacamole` en `compose.yaml` y ejecutar `docker compose pull && docker compose up -d`. ## Solución de problemas **La página carga pero las sesiones se quedan en "Connecting" o se desconectan.** Normalmente falta el soporte de WebSocket en el proxy. Comprueba que el bloque `location /guacamole/` contiene las cabeceras `Upgrade` y `Connection` y `proxy_http_version 1.1`. **Error "Connection error" al abrir una conexión.** `guacd` no alcanza el equipo de destino o la autenticación falla. Revisa sus logs: ```bash docker compose logs --tail=50 guacd ``` Los mensajes indican si se trata de un error de red, de credenciales o de seguridad RDP (por ejemplo, NLA requerido o certificado no válido). **No puedes iniciar sesión tras una reinstalación.** Si borraste el contenedor de PostgreSQL pero no el volumen `pgdata`, el script de `initdb/` no se vuelve a ejecutar y siguen valiendo los usuarios anteriores. Para empezar de cero, elimina también el volumen con `docker compose down -v` (se pierden todos los datos). **Los logs muestran la IP del proxy en lugar de la del usuario.** Confirma que `REMOTE_IP_VALVE_ENABLED` está a `"true"` y que Nginx envía `X-Forwarded-For`. ## Conclusión Tienes Apache Guacamole funcionando con Docker Compose y PostgreSQL, publicado por HTTPS con Nginx, protegido con doble factor y con conexiones SSH y RDP accesibles desde el navegador. Como siguientes pasos, activa la grabación de sesiones para auditar los accesos, integra la autenticación con LDAP, Active Directory u OpenID Connect para no gestionar usuarios a mano y cierra en los servidores de destino los puertos SSH y RDP a todo lo que no sea la IP de Guacamole.