Tasty tasty guacamole
- Context
- Installing guacamole with docker-compose and traefik
- Errors and Pitfalls
- 404 Not Found
- Error: An error has occurred and this action cannot be completed
- guacamole-db | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
- Table ‘guacamole_db.guacamole_user’ doesn’t exist
- Image credit
tl;dr: Some parts of another guide no longer work, the biggest pitfall is execution permission on the directory of the database init script
Context
A million years ago in 2018 I installed guacamole for reasons that I forget.
As the link says, guacamole is clientless remote desktop software from Apache, so you can remote in without needing a client. Nifty. I wanted this installed here in the distant present as I’d been at my mum’s frequently for reasons of boiler replacement, gas network fixing pressure, and such. My laptop works fine but there were a couple of times I missed having the context of my home setup. I might have gotten away with ssh access as usual but wanted the option of GUI. So I returned to guacamole.
Installing guacamole with docker-compose and traefik
Since I couldn’t find the details of how I installed guacamole in the annals of history, I started anew. There is a guide, enticingly titled: “Install Guacamole on Docker with Traefik and 2FA“. I don’t particularly need the 2FA aspect, but I do use traefik! Please check this page for the issue with that guide; it was a useful starting point for me, but I had to track down some issues.
Apache themselves do a ‘guacamole with docker’ setup guide but make no mention of docker-compose. It is helpful in some aspects though.
docker-compose.yaml
version: '3.4' services: guacd: image: guacamole/guacd container_name: guacd hostname: guacd restart: unless-stopped volumes: - ./guacd/drive:/drive:rw - ./guacd/record:/record:rw networks: - guacamole_network guacamole: image: guacamole/guacamole container_name: guacamole hostname: guacamole restart: unless-stopped depends_on: - guacd - guacamole-db environment: GUACD_HOSTNAME: guacd POSTGRES_HOSTNAME: guacamole-db POSTGRES_DATABASE: guacamole_db POSTGRES_USER: guacamole_user POSTGRES_PASSWORD: ${GUACAMOLE_PASSWORD} #MYSQL_HOSTNAME: guacamole-db #MYSQL_DATABASE: guacamole_db #MYSQL_USER: guacamole_user #MYSQL_PASSWORD: ${GUACAMOLE_PASSWORD} #TOTP_ENABLED: 'true' links: - guacd labels: - 'traefik.enable=true' - 'traefik.http.routers.guacamole.rule=Host(`guacamole.${DOMAIN}`)' - "traefik.http.routers.guacamole.service=guacamole" #- 'traefik.http.routers.guacamole.entrypoints=web-secure' - 'traefik.http.routers.guacamole.tls=true' - "traefik.http.routers.guacamole.tls.certresolver=myresolver" - "traefik.http.routers.guacamole.middlewares=guac-auth,guacprefix" - "traefik.http.middlewares.guac-auth.basicauth.users=USERNAME:PASSWORD" - "traefik.http.middlewares.guacprefix.addprefix.prefix=/guacamole" - "traefik.http.services.guacamole.loadBalancer.server.port=8080" #- "traefik.http.routers.guacamole.tls.domains[0].main=*.${DOMAIN}" #- "traefik.http.routers.guacamole.tls.options=myTLSOptions@file" #- "traefik.http.routers.guacamole.middlewares=guacamoleMdl" networks: - guacamole_network - traefik_default guacamole-db: #image: mysql/mysql-server image: postgres:13.4-buster container_name: guacamole-db hostname: guacamole-db environment: POSTGRES_USER: guacamole_user POSTGRES_PASSWORD: '${GUACAMOLE_PASSWORD}' POSTGRES_DB: guacamole_db PGDATA: /var/lib/postgresql/data/guacamole restart: unless-stopped volumes: #- ./init/initdb.sql:/initdb.sql #DB configuration file - ./init/:/docker-entrypoint-initdb.d # make sure dir is `chmod +x` - ./pgdata:/var/lib/postgresql/data:Z #- ./guac-data/database:/var/lib/mysql/:rw networks: - guacamole_network networks: traefik_default: external: true guacamole_network: external: false
Or download it here: docker-compose.yaml
I’ve left the changes I made from the linked guide in. You should do a couple of things before using this:
- create a
.env
file in the same directory withGUACAMOLE_PASSWORD
andDOMAIN
variables set (and set up DNS for guacamole.whateverthatdomainis.tld) - change or remove the
basicauth
middleware to set a username and password; guacamole itself has password based auth and can be set up for 2FA so this isn’t terribly necessary, but I keep non-public things away from prying eyes
if you need to generate the password hash, I have a guide on how to generate the hash without htpasswd - change the network to match whatever you are using for traefik (and any other naming convention alignments)
- create directories for guacd, guacamole itself and the database data
Generate the database initialisation file
This differs from the linked guide! You will see in the docker-compose.yaml above that the database initialisation file is stored in a directory- this is because the enclosing directory needs the execution bit set (see eg in this other docker-compose.yaml), or it will be ignored. So run:
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql > ./init/initdb.sql
If you prefer MySQL / MariaDB, substitute --mysql
in that command.
Aug 2023 note: this command has been updated from --postgres
to --postgresql
thanks to @Liam’s comment below!
Start it up and log in
The guacamole instance should be accessible on https://guacamole.yourdomain.tld
with the default login being guacadmin / guacadmin like the other guide, unless you changed this. Regardless, you should do as they suggest:
I suggest you duplicate the default account and create a new administrator account. Then login with the new account and delete the default one.
https://frigi.ch/en/2021/07/install-guacamole-on-docker-with-traefik-and-2fa/
Errors and Pitfalls
I spent some time chasing down errors, so in case you find yourself down a similar rabbit hole, here’s what they might be and why.
404 Not Found
Following the guide and filling in the relevant details (really the password and the appropriate traefik labels), you’ll probably see something like this:
For whatever reason, the addprefix
middleware in that guide didn’t work for me off the bat.
Error: An error has occurred and this action cannot be completed
When you fix that or add /guacamole/
to the URL, you’ll probably see:
Ah, hmm. Let’s do as it suggests and check the logs:
guacamole | 11:13:46.067 [http-nio-8080-exec-4] ERROR o.a.g.rest.RESTExceptionMapper - Unexpected internal error: guacamole | ### Error querying database. Cause: org.postgresql.util.PSQLException: The connection attempt failed. guacamole | ### The error may exist in org/apache/guacamole/auth/jdbc/user/UserMapper.xml guacamole | ### The error may involve org.apache.guacamole.auth.jdbc.user.UserMapper.selectOne guacamole | ### The error occurred while executing a query guacamole | ### Cause: org.postgresql.util.PSQLException: The connection attempt failed.
The connection attempt failed? But the log reports:
guacamole-db | .2022-12-09 10:58:15.134 UTC [48] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432" guacamole-db | 2022-12-09 10:58:15.227 UTC [49] LOG: database system was shut down at 2022-12-09 10:58:03 UTC guacamole-db | 2022-12-09 10:58:15.253 UTC [48] LOG: database system is ready to accept connections guacamole-db | done guacamole-db | server started
Strange.
guacamole-db | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
Looking further up you’ll see:
guacamole-db | CREATE DATABASE guacamole-db | guacamole-db | guacamole-db | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/* guacamole-db | guacamole-db | waiting for server to shut down....2022-12-09 10:58:23.005 UTC [48] LOG: received fast shutdown request guacamole-db | 2022-12-09 10:58:23.056 UTC [48] LOG: aborting any active transactions guacamole-db | 2022-12-09 10:58:23.393 UTC [48] LOG: background worker "logical replication launcher" (PID 55) exited with exit code 1 guacamole-db | 2022-12-09 10:58:23.407 UTC [50] LOG: shutting down
If you don’t have execution permissions set on the directory containing the database init script, it gets skipped!
Table ‘guacamole_db.guacamole_user’ doesn’t exist
If like me you got to this point and were getting a "table 'guacamole_db.guacamole_user' doesn't exist
” error, it might be related to the log line:
guacamole-db | PostgreSQL Database directory appears to contain a database; Skipping initialization
If you are fixing the permissions issue on the database initialisation script, make sure to remove the existing database before you start up again! ie
docker-compose down
rm ./pgdata/
docker-compose up -d
Image credit
The featured image on this article is ‘guacamole’ by stu_spivack on Flickr
Appreciate the work here Rob! Successfully up and running behind Traefik.
Only thing I noticed was in the command to generate initdb.sql
Seems the base image has been updated for the database container and intead of –postgres it needs to be –postgresql.
This is the case when using the postgres:13.4-buster image referenced in your docker compose file.
Nonetheless top work!
Hi Liam, thanks both for the kind words and the note on the command needing updated- I’ve edited that in. Cheers for the heads up!