Apache Guacamole: Session recordings and playback in-browser — version 2
Assuming you’ve installed Apache Guacamole as per my manual installation blog post, this article guides you through enabling graphical session recording playback in the browser.
Create record directory
We need to create the directory where all the sessions records will be stored.
mkdir ${HOME}/docker-stack/guacamole/record
That folder requires some specific permissions:
- The frontend (guacamole/guacd) container can write to the directory.
- The backend (guacamole/guacamole) container can read from the directory, as well as read any files that are placed within the directory.
In order to meet these requirements, we need to get the UID of the guacamole_backend
container:
root@instance:/# docker exec -it guacamole_backend id
uid=1000(guacd) gid=1000(guacd) groups=1000(guacd)
And the GID of the guacamole_frontend
container:
root@instance:/# docker exec -it guacamole_frontend id
uid=1001(guacamole) gid=1001(guacamole) groups=1001(guacamole)
Then we modify the permissions and ownerships :
sudo chown -R 1000:1001 ${HOME}/docker-stack/guacamole/record
sudo chmod -R 2750 ${HOME}/docker-stack/guacamole/record
Update docker-compose
We need to edit the ${HOME}/docker-stack/guacamole/docker-compose.yml
file we created in the installation blog post:
- The record folder should be mounted as a volume to both the
guacamole_backend
container and theguacamole_frontend
container. - We must set the
RECORDING_SEARCH_PATH
environment variable
So the complete version of the new ${HOME}/docker-stack/guacamole/docker-compose.yml
file be like:
version: '3.9'
# networks
# create a network 'guacamole_net' in mode 'bridged'
networks:
guacamole_net:
driver: bridge
haproxy_net:
external: true
# services
services:
# guacd
guacd:
container_name: guacamole_backend
image: guacamole/guacd:1.5.3
networks:
guacamole_net:
restart: always
volumes:
- ./drive:/drive:rw
- ./record:/var/lib/guacamole/recordings:rw
# postgres
postgres:
container_name: guacamole_database
environment:
PGDATA: /var/lib/postgresql/data/guacamole
POSTGRES_DB: guacamole_db
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
POSTGRES_USER: '${POSTGRES_USER}'
image: postgres:15.0
networks:
guacamole_net:
restart: always
volumes:
- ./init:/docker-entrypoint-initdb.d:ro
- ./data:/var/lib/postgresql/data:rw
# guacamole
guacamole:
container_name: guacamole_frontend
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRESQL_DATABASE: guacamole_db
POSTGRESQL_HOSTNAME: postgres
POSTGRESQL_PASSWORD: '${POSTGRES_PASSWORD}'
POSTGRESQL_USER: '${POSTGRES_USER}'
POSTGRESQL_AUTO_CREATE_ACCOUNTS: true
RECORDING_SEARCH_PATH: '/var/lib/guacamole/recordings'
image: guacamole/guacamole:1.5.3
links:
- guacd
networks:
- guacamole_net
- haproxy_net
restart: always
volumes:
- ./drive:/drive:rw
- ./record:/var/lib/guacamole/recordings:ro
What changed?
Check out the output of the diff
command:
version: '3.9'
# networks
# create a network 'guacamole_net' in mode 'bridged'
networks:
guacamole_net:
driver: bridge
haproxy_net:
external: true
# services
services:
# guacd
guacd:
container_name: guacamole_backend
image: guacamole/guacd:1.5.3
networks:
guacamole_net:
restart: always
volumes:
- ./drive:/drive:rw
+ - ./record:/var/lib/guacamole/recordings:rw
# postgres
postgres:
container_name: guacamole_database
environment:
PGDATA: /var/lib/postgresql/data/guacamole
POSTGRES_DB: guacamole_db
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
POSTGRES_USER: '${POSTGRES_USER}'
image: postgres:15.0
networks:
guacamole_net:
restart: always
volumes:
- ./init:/docker-entrypoint-initdb.d:ro
- ./data:/var/lib/postgresql/data:rw
# guacamole
guacamole:
container_name: guacamole_frontend
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRESQL_DATABASE: guacamole_db
POSTGRESQL_HOSTNAME: postgres
POSTGRESQL_PASSWORD: '${POSTGRES_PASSWORD}'
POSTGRESQL_USER: '${POSTGRES_USER}'
POSTGRESQL_AUTO_CREATE_ACCOUNTS: true
+ RECORDING_SEARCH_PATH: '/var/lib/guacamole/recordings'
image: guacamole/guacamole:1.5.3
links:
- guacd
networks:
- guacamole_net
- haproxy_net
restart: always
volumes:
- ./drive:/drive:rw
+ - ./record:/var/lib/guacamole/recordings:ro
Now let’s apply these changes:
docker compose -f ${HOME}/docker-stack/guacamole/docker-compose.yml up -d
Testing
Edit the “Screen Recording” section of one of your existing connection settings. Enter the special value ${HISTORY_PATH}/${HISTORY_UUID}
in the “Recording path” input box.
Check the “Automatically create recording path” box.
Demo
Thank you for reading this article all the way to the end! I hope you found the information and insights shared here to be valuable and interesting. Get in touch with me on LinkedIn.
I appreciate your support and look forward to sharing more content with you in the future. Until next time!
This post also appears on my personal Blog.