Deploy Guacamole

Some cred to: https://frigi.ch/en/2023/01/install-guacamole-on-docker-with-traefik-postgres-and-2fa/ (I use MariaDB instead of postgres)

  1. Spin up the database container (needed to extract the intidb.sql - there are probably other ways but most seems to be doing it like this)

  2. example docker-compose

services:
  guacdb:
    container_name: guacamoledb
    image: mariadb:11.2
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: '<insert-root-password>'
      MYSQL_DATABASE: 'guacamole_db'
      MYSQL_USER: 'guacamole_user'
      MYSQL_PASSWORD: '<insert-user-password>'
    volumes:
      - 'guac_mariadb_data:/var/lib/mysql'
volumes:
  guac_mariadb_data:
  1. ssh to your docker node and run: docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql

  2. Then copy the initdb.sql into the database container deployment: docker cp initdb.sql guacamoledb:/initdb.sql

  3. Enter the shell on the database container: docker exec -it guacamoledb bash

  4. Import: cat initdb.sql | mariadb -u root -p guacamole_db (enter root password when asked)

  5. exit

  6. Stop the db container: docker-compose down

  7. Edit the docker-compose.yml

  8. default port is 8080, change to whatever depending on how you reverse proxy it

services:
  guacdb:
    container_name: guacamoledb
    image: mariadb:latest
    restart: unless-stopped
    networks:
      - traefik-proxy
    environment:
      MYSQL_ROOT_PASSWORD: '<root-password>'
      MYSQL_DATABASE: 'guacamole_db'
      MYSQL_USER: 'guacamole_user'
      MYSQL_PASSWORD: '<mysql-user-pass>'
    volumes:
      - 'guac_mariadb_data:/var/lib/mysql'
  guacd:
    container_name: guacd
    image: guacamole/guacd:latest
    restart: unless-stopped
    networks:
      - traefik-proxy
  guacamole:
    container_name: guacamole
    image: guacamole/guacamole:latest
    restart: unless-stopped
    networks:
      - traefik-proxy
    environment:
      GUACD_HOSTNAME: "guacd"
      MYSQL_HOSTNAME: "guacdb"
      MYSQL_DATABASE: "guacamole_db"
      MYSQL_USER: "guacamole_user"
      MYSQL_PASSWORD: "<mysql-user-pass>"
      TOTP_ENABLED: "true"
    depends_on:
      - guacdb
      - guacd
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.guac.rule=Host(`guacamole.domain.com`)"
      - "traefik.http.routers.guac.entrypoints=websecure"
      - "traefik.http.routers.guac.tls=true"
      - "traefik.http.services.guac.loadbalancer.server.port=8080"
      - "traefik.http.routers.guac.tls.certresolver=letsencrypt"
      - "traefik.http.routers.guac.tls.domains[0].main=domain.com"
      - "traefik.http.routers.guac.tls.domains[0].sans=*.domain.com"
      - "traefik.http.middlewares.add-guacamole.addprefix.prefix=/guacamole"
      - "traefik.http.routers.guac.middlewares=add-guacamole"
volumes:
  guac_mariadb_data:
networks:
  traefik-proxy:
    external: true
  1. Take note of:

      - "traefik.http.middlewares.add-guacamole.addprefix.prefix=/guacamole"
      - "traefik.http.routers.guac.middlewares=add-guacamole"

Which adds the prefix /guacamole to the url, so https://guacamole.domain.com becomes https://guacamole.domain.com/guacamole which is required for the offical image

Last updated