Guacamole
Apache Guacamole is a web-accessible remote desktop gateway that supports RDP, VNC, and text-based connections via SSH and telnet.
Quick introduction
The Guacamole server contains two parts: The web application itself running on Tomcat, and the guacamole proxy service (guacd) that connects to the remote desktop endpoints. Under the hood, the RDP/VNC/SSH connection data from guacd is sent to the Guacamole server using the Guacamole protocol which is then relayed back to the user and rendered using Guacamole's HTML5 based client. As a result, the client is unaware of the underlying protocol (which actually poses several limitations which will be covered later).
Limitations
Guacamole's documentation doesn't list limitations clearly and these are the limitations that I've encountered after playing with it for a short period.
- Guacamole must connect to a VNC enabled desktop either anonymously or with pre-defined credentials. You cannot have Guacamole 'login' for a user using their Guacamole credentials.
- RDP works like VNC but with NLA support for RDP (I haven't tested this) which would allow the user to enter their RDP credentials when connecting. There is no way to make Guacamole pass credentials to RDP however, so you can't make Guacamole work like a VDI using a pool of desktops.
- In VNC, sessions cannot be 'resized' on the fly. Guacamole's protocol doesn't seem to support it.
In VNC, copy/paste clipboard data cannot be copied out of a remote desktop; it can only be copied in.This works if I use x11vnc as the VNC server rather than the Gnome built-in screen sharing feature.- VNC based connections are extremely slow. Using x11vnc is slightly better than vino, but there's easily 1-2 second delays on my local instance all hosted on the same hypervisor and accessed via a local gigabit LAN connection.
- VNC connection settings hard code authentication credentials. You cannot 'login' as a user on the remote desktop
Setup
You can either install Guacamole directly on a server or use the prebuilt Docker containers. Review the documentation at:
Setup Guacamole using Docker Compose
The easiest way to set up Guacamole is with the following docker-compose.yml
stack. I am using Traefik as the reverse proxy which handles SSL termination and strips the /guacamole
from the URI path, but is completely optional. If you don't use Traefik, simply remove the Traefik network and labels and serve port 8080.
First, create the following docker-compose.yml
file.
version: '3.3'
services:
guacd:
image: guacamole/guacd
restart: unless-stopped
volumes:
- /volumes/guacamole/guacd/drive:/drive:rw
- /volumes/guacamole/guacd/record:/record:rw
networks:
- internal
guacamole:
image: guacamole/guacamole
restart: unless-stopped
depends_on:
- guacd
- db
environment:
GUACD_HOSTNAME: guacd
MYSQL_HOSTNAME: db
MYSQL_DATABASE: guacamole
MYSQL_USER: guacamole
MYSQL_PASSWORD: 41e930486c6de5ebda96 <-- change me
expose:
- "8080"
labels:
- traefik.enable=true
- traefik.docker.network=traefik
- traefik.http.middlewares.guacamole-prefix.addprefix.prefix=/guacamole
- traefik.http.middlewares.guacamole-https-redirect.redirectscheme.scheme=https
# http
- traefik.http.routers.guacamole.entrypoints=http
- traefik.http.routers.guacamole.rule=Host(`guacamole.steamr.com`)
- traefik.http.routers.guacamole.service=guacamole-https
- traefik.http.routers.guacamole.middlewares=guacamole-https-redirect
# https
- traefik.http.routers.guacamole-https.entrypoints=https
- traefik.http.routers.guacamole-https.rule=Host(`guacamole.steamr.com`)
- traefik.http.routers.guacamole-https.tls=true
- traefik.http.routers.guacamole-https.service=guacamole-https
- traefik.http.services.guacamole-https.loadbalancer.server.port=8080
- traefik.http.routers.guacamole-https.middlewares=guacamole-prefix
networks:
- internal
- traefik
db:
image: mariadb:latest
environment:
MYSQL_ROOT_PASSWORD: 41e930486c6de5ebda96 <-- change me
MYSQL_USER: guacamole
MYSQL_PASSWORD: 41e930486c6de5ebda96 <-- change me
MYSQL_DATABASE: guacamole
restart: unless-stopped
volumes:
# To obtain this file, run: docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
- /volumes/guacamole/initdb.sql:/initdb.sql
- /volumes/guacamole/db:/var/lib/mysql/:rw
networks:
- internal
networks:
internal:
traefik:
name: traefik
external: true
Next, bring the container stack up:
# docker-compose pull
# docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > /volumes/guacamole/initdb.sql
# docker-compose up -d
Set up the database:
## Figure out which container is your database and then load the initial database
# docker ps | grep guacamole
# docker exec -ti $DB_CONTAINER_ID bash
root@db # mysql -u root -p$MYSQL_ROOT_PASSWORD $MYSQL_DATABASE < /initdb.sql
You should be able to reach the Guacamole server and see a login page. If not, restart the Guacamole container and try again. If you see an error message, you likely misconfigured the database connection or didn't populate the Guacamole database properly.
Login using the following credentials:
- Username: guacadmin
- Password: guacadmin
When setting up a new connection, enter 'guacd
' as the Guacamole proxy hostname, 4822
as the port, and 'none
' for encryption.
Setting up a VNC connection
Log in as an administrator and navigate to 'Settings', then 'Connections'. Click on 'New Connection'. Specify the following:
- guacd: If using the Docker compose stack above, the hostname would just be 'guacd' on port 4822 without encryption
- parameters: The hostname to your VNC server. Port is typically 5900. I leave all other fields blank. I use X11vnc as my VNC server which starts up with my login.
- Audio: The 'Audio server name' should point to a PulseAudio service. To make this work, you will have to tweak PulseAudio to allow remote connections via TCP. Edit
/etc/pulse/default.pa
and uncomment out the line 'load-module module-native-protocol-tcp'. Add the following arguments to the module such that the final linke looks like this:load-module module-native-protocol-tcp auth-ip-acl=10.1.2.11/32 auth-anonymous=1
. Restart PulseAudio (killall pulseaudio
should work and it should be restarted automatically or just reboot). Verify it's working by runningss -lntp | grep 4713
.
Using Guacamole
Review the documentation at https://guacamole.apache.org/doc/gug/using-guacamole.html.
Alt + Ctrl + Shift
is used to bring up or hide the Guacamole menu sidebar.
Tasks
Changing the default /guacamole URI path
The default URI path for Guacamole is /guacamole
(Eg. http://server:8080/guacamole). You may wish to change it so that Guacamole is served on the root path (/).
The official Docker image
If using the Guacamole Docker image, restart the container with an environment variable WEBAPP_CONTEXT=ROOT
.
Direct install on a server
If using Guacamole on a server directly, you will need to rename the guacamole Tomcat war file:
- Navigate to
/var/lib/tomcat8/webapps/
and delete the guacamole directory. - Rename the
guacamole.war
file toROOT.war
. - Restart Tomcat
Traefik reverse proxy
If you're using Traefik as the reverse proxy, you can create a middleware that adds the /guacamole prefix transparently. Use the following configs with Traefik v2.
traefik.http.middlewares.guacamole-prefix.addprefix.prefix=/guacamole
traefik.http.routers.guacamole.middlewares=guacamole-prefix
Troubleshooting
Incorrect VNC sessions screen size
I encountered an issue with x11vnc where the screen size is about 10-15 times taller than it should be. The contents of the extraneous areas appear to be bits and pieces of other windows and overlays. The cause of this was that x11vnc was started with the ncache option which is used to expand the framebuffer for caching windows and window contents. This however requires a VNC client that supports this option which Guacamole's proxy (guacd) doesn't seem to support.
To fix this issue, re-run x11vnc with the -noncache
option.