Salut à tous, dans le dernier TP on s’est penché sur la définition d’une Stack dans Portainer pour un service VSFTPD. Aujourd’hui on va regarder comment déployer une Stack Docker Guacamole avec plusieurs images docker, toujours dans Portainer. L’objectif du jour étant d’avoir un service Guacamole sur notre serveur à la fin du TP.
Rappel des articles de la série « Docker et Portainer » :
- Docker et Portainer part 1 – Les conteneurs pour les nuls ;
- Docker et Portainer part 2 – Stack vsftpd mono-image ;
- Docker et Portainer part 3 – Docker Guacamole via une Stack multi-images ;
- Docker et Portainer part 4 – OpenVPN, Network et Splunk ;
- Docker et Portainer part 5 – Customiser un conteneur PHP-FPM ;
- Docker et Portainer part 6 – NextCloud avec Docker, Déployer un « Cloud » personnel ;
- Docker et Portainer part 7 – Mettre à jour Portainer ;
- Docker et Portainer part 8 – Déployer un jitsi meet avec docker ;
- Docker et Portainer part 9 – Monitoring des performances docker avec Splunk.
- Docker et Portainer part 10 – The Hive & Cortex et installation Docker….
Guacamole ? bon appétit !
Apache Guacamole plus exactement, et qui n’a rien à voir avec la recette mexicaine de purée d’avocat, est un client VNC, RDP, et SSH (comme un PuTTY ou mremoteng) qui à la particularité d’être « client-less » ou plus exactement « full-web ».
On installe donc Guacamole sur un serveur et on y accède avec son navigateur web comme dans la capture ci-dessous.
Le gros intérêt au delà d’avoir un client SSH dans son navigateur, c’est que c’est le serveur qui effectue la connexion VNC, RDP ou SSH sur le port concerné. Et donc d’un point de vu réseau le poste client ne fait donc que du HTTPS sur le 443 vers le serveur.
Le gros avantage c’est que lorsque vous bossez dans un environnement « sécurisé », ou soit-disant :-), qui n’autorise pas ces ports en sortie (pour rappel TCP/22 pour SSH, TCP/3389 pour RDP et TCP/5900 pour VNC par défaut). C’est que si vous avez accès au net, vous aurez accès à votre guacamole, qui lui aura accès à votre ou vos serveur(s) sur ces ports.
Et d’un point de vu réseau c’est beaucoup plus « propre » (et discret…) que de faire du SSH sur le port 443, que soit en direct (on a vu… qui a dit proxy SOCKS ?) ou avec un frontal SSLH devant votre serveur par exemple.
Stack Docker Guacamole
Alors la bonne nouvelle c’est que la doc du projet est super complète, y compris pour docker. La mauvaise c’est qu’elle est bien verbeuse et que se la palucher tout d’un bout à l’autre demande « un certain temps« . Alors comme pour le dernier TP sur VSTFPD on pourrait aller sur le docker hub et chercher un image toute prête mono-conteneur qui implémente Guacamole.
Bon dans mon cas, je voulais m’en servir pour administrer le serveur et j’étais pas trop chaud pour reprendre une image inconnue vu que le système Guacamole reste assez complexe. Les options était donc de partir des sources ou des 2 images officielles d’Apache Guacamole sur le docker hub et regrouper le tout dans une Stack (pour vous faire ce TP).
Pour rappel un service Guacamole est composé de 3 éléments :
- Une base de données : MySql ou PostGreSQL
- Un moteur du service : Guacd
- L’interface Web qui fait le lient avec le service : Guacamole
La base de données : MariaDB
Le seul service qu’il faut configurer c’est la base de donnée, donc on peut commencer par construire une stack juste avec elle, la configurer puis rajouter les 2 autres éléments. Voici le code du docker-compose.yml pour faire ça :
version: "2"
services:
guacdb:
container_name: guacdb
hostname: guacdb
image: mariadb:latest
volumes:
- guac_db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=4n!R00TPasswordUmayWant
expose:
- "3306"
Il faut déployer cette Stack dans Portainer comme je vous l’ai montré pour VSFTPD. Une fois le service running, il faut initialiser la base de données. Heureusement l’image docker « Guacamole » intègre le script pour ça. Donc sur votre hôte, saisissez la commande suivante pour copier le script en local :
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
Il faut ensuite exécuter la succession de commandes suivantes pour initialiser la base de données (doc).
docker exec -i guac_database sh -c 'mysqladmin -u root -p"$MYSQL_ROOT_PASSWORD" create guacamole_db' docker exec -i guac_database sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" guacamole_db -e "CREATE DATABASE guacamole;"' docker exec -i guac_database sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" guacamole_db -e "CREATE USER \"guac\" IDENTIFIED BY \"PasswordServiceGuac\";"' docker exec -i guac_database sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" guacamole_db -e "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE ON guacamole.* TO \"guac\"@\"%\";"' docker exec -i guac_database sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" guacamole_db -e "FLUSH PRIVILEGES;"' docker exec -i guac_database sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" guacamole_db ' < initdb.sql
Et la base de données est configurée.
Le service : GuacD
Le service GuacD ne nécessite pas de configuration particulière donc sa partie dans la Stack est assez directe :
guacd:
container_name: guacd
hostname: guacd
image: "guacamole/guacd:latest"
restart: always
volumes:
- "guacd_data:/data"
- "guacd_conf:/conf:ro"
expose:
- "4822"
Notez que j’utilise ici expose
et non pas ports
pour décrire le port réseau sur lequel le service s’exécute. J’y reviendrai un peu après.
l’IHM : Guacamole
Enfin il nous reste à exposer le service web, et pour ça la dernière partie de notre Stack se définie ainsi, il suffit de l’ajouter dans la Stack et de déployer le tout.
guacamole:
image: "guacamole/guacamole:latest"
container_name: guacamole
hostname: guacamole
restart: always
depends_on:
- guacd
- guacdb
volumes:
- "guac_data:/data"
- "guac_conf:/conf:ro"
ports:
- "8084:8084"
links:
- "guacdb:database"
- "guacd:guacd"
environment:
- "GUACD_HOSTNAME=guacd"
- "GUACD_PORT=4822"
- "MYSQL_HOSTNAME=database"
- "MYSQL_PORT=3306"
- "MYSQL_DATABASE=guacamole"
- "MYSQL_USER=guac"
- "MYSQL_PASSWORD=PasswordServiceGuac"
- "GUACAMOLE_HOME=/data"
Notez ici que j’utilise ports
pour indiquer les ports accessibles depuis l’extérieur de docker. Qui est différent d’expose qui documente simplement les ports exposé par le conteneur, sans les rendre joignable de l’extérieur.
Premier accès à Docker Guacamole
A partir de là, vous devriez pouvoir accéder sur le port 8084 de votre serveur en HTTP et avoir cette belle page de login.
Le login par défaut est guacadmin / guacadmin
et je vous recommande de changer rapidement.
Vous pourrez ensuite allez dans Paramètres->Connexions->Nouvelle Connexion
et définir les paramètre de votre serveur SSH.
Celui-ci apparaitra alors sur la page d’accueil, et il vous suffit de cliquer dessus pour vous y connecter.
Et voilà, vous avez un client SSH accessible en Web depuis votre Serveur.
« Hey attends 2s là, on est pas sur le port HTTPS là, c’est le 8084 qui est configuré. Je pourrais pas me connecter depuis un environnement ou ce port est filtré au final. »
un type qui suit.
C’est bien il y en a qui suivent, et effectivement ici tous est configuré pour tourner sur le 8084. Mais on peut avoir un quick-fix en « NATant » ce port sur le 80 de notre serveur par exemple, directement dans notre conf docker en remplaçant notre section ports
de Guacamole avec :
ports:
- "80:8084"
qui exposera alors le port 80 et redirigera le trafic vers le 8084 de notre Guacamole.
La stack Docker Guacamole complète
Pour les feignasses ; oui, là, vous au fond, près du radiateur :
version: "2"
services:
guacdb:
container_name: guacdb
hostname: guacdb
image: mariadb:latest
volumes:
- guac_db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=AvousdeVoir
expose:
- "3306"
guacd:
container_name: guacd
hostname: guacd
image: "guacamole/guacd:latest"
restart: always
volumes:
- "guacd_data:/data"
- "guacd_conf:/conf:ro"
expose:
- "4822"
guacamole:
image: "guacamole/guacamole:latest"
container_name: guacamole
hostname: guacamole
restart: always
depends_on:
- guacd
- guacdb
volumes:
- "guac_data:/data"
- "guac_conf:/conf:ro"
ports:
- "80:8084"
links:
- "guacdb:database"
- "guacd:guacd"
environment:
- "GUACD_HOSTNAME=guacd"
- "GUACD_PORT=4822"
- "MYSQL_HOSTNAME=database"
- "MYSQL_PORT=3306"
- "MYSQL_DATABASE=guacamole"
- "MYSQL_USER=guac"
- "MYSQL_PASSWORD=trolololo
- "GUACAMOLE_HOME=/data"
Conclusion
Et voilà, normalement vous devriez avoir un Guacamole fonctionnel. Mais il reste quand même quelques soucis :
- On a un seul port 80 par serveur… et si on veut exposer un autre conteneur dessus on devra choisir entre lui et Guacamole.
- De plus le service n’est pas chiffré avec HTTPS, c’est un peu con pour un truc qui ne sert que pour des protocoles d’administration.
Mais du coup plutôt que se concentrer sur comment mettre HTTPS sur un Guacomale dockerisé, je vous proposerai la prochaine fois d’étudier une solution généralisable qui sera valable pour tous nos dockers dans la plateforme.
Et donc dans le prochain TP docker je vous parlerai Nginx Proxy Manager ou NPM pour rediriger le trafic web HTTP(S) arrivant sur la machine vers les bon services en fonction du nom de domaine utilisé et des networks pour permettre à nos différents conteneurs de se parler. Mais, stop aux spoilers, et d’ici là, Geekez-bien.