A fast Docker setup for Apache Guacamole on Ubuntu 24.04 — RDP / VNC / SSH, session recording, LDAP, IP banning, time/IP restrictions, and a ready-to-brand login page.
中文版說明請見: README.zh-tw.md
- Zero to Guacamole in minutes – scripts handle Docker install, DB init, permissions, and service start.
- Opinionated defaults – recording enabled out of the box; security toggles are one env var away.
- Brand-ready – a sample branding extension plus a one-click pack script.
- Operational tooling – scripts for restart, status, and logs so you can troubleshoot quickly.
If this saves you time, please ⭐ the repo. It helps others discover it.
- Ubuntu 24.04 LTS
sudo
privileges- Internet access to pull Docker images
- Port 80/tcp available on the host (customizable in
docker-compose.yml
)
Run everything from the repository root.
- Make scripts executable
chmod +rx *.sh
- Install Docker & Compose
./00_install_docker.sh
- Bootstrap everything (DB schema, recording dir permissions, containers)
./01_manager.sh init-all
- Restart services when configs change
./02_restart.sh
- Check container health
./03_check.sh
- Tail/export logs
./04_log.sh
Open the UI: http://<your-host>
.
⚠️ Default admin:guacadmin / guacadmin
Immediately sign in, change the password, create a second admin, verify it works, and disableguacadmin
.
- Raw protocol recordings are persisted under
./recordings/
on the host (mounted to/var/lib/guacamole/recordings
). - The web UI includes a built-in player for playback.
- Convert to
.m4v/.mp4
only when you need to share/archive (saves disk in day-to-day ops).
Script | What it does |
---|---|
00_install_docker.sh |
Installs Docker & Compose |
01_manager.sh |
Manager with subcommands (init-all , status , logs , exec , …) |
02_restart.sh |
Restarts the stack |
03_check.sh |
Prints docker compose ps and health |
04_log.sh |
Follows and saves logs under ./log/ |
Enable features by switching values to "true"
(restart after changes):
# --- Web add-ons ---
RECORDING_ENABLED: "true" # 🎥 Session recording & playback
LDAP_ENABLED: "true" # 🔐 LDAP auth (configure guacamole.properties)
TOTP_ENABLED: "false" # 🔑 2FA (TOTP)
BAN_ENABLED: "true" # 🚫 IP ban on repeated failures
RESTRICT_ENABLED: "true" # 🕘 Source/time access restrictions
JSON_ENABLED: "false" # 🔗 JSON auth (custom portal/SSO)
Recommended starting points
- Just to get going: keep
RECORDING_ENABLED
andBAN_ENABLED
on. - Corporate/School login: turn on
LDAP_ENABLED
and configure properties. - Stricter environments: enable
TOTP_ENABLED
andRESTRICT_ENABLED
.
Apply changes with
./02_restart.sh
.
File lives at repo root (./guacamole.properties
) and is mounted to /etc/guacamole/guacamole.properties
.
# ===== LDAP (adjust to your tree) =====
ldap-hostname: ldap.school.edu.tw
ldap-user-base-dn: dc=school,dc=edu,dc=tw
ldap-group-base-dn: cn=groups,dc=school,dc=edu,dc=tw
ldap-search-bind-dn: uid=root,cn=users,dc=school,dc=edu,dc=tw
ldap-search-bind-password: your_password
ldap-group-name-attribute: cn
ldap-member-attribute: memberUid
ldap-member-attribute-type: uid
# ===== Recording (must match compose mount) =====
recording-search-path=/var/lib/guacamole/recordings
# ===== Languages =====
allowed-languages: en
# ===== API session idle timeout (minutes) =====
api-session-timeout: 120
# ===== Ban (when BAN_ENABLED is true) =====
#ban-max-invalid-attempts: 5
#ban-address-duration: 300
# ===== Debug logging =====
#log-level: trace
Notes
- LDAP: DNs must match your directory structure. If unsure, verify with
ldapsearch
. - Recording path must align with the volume mount (
/var/lib/guacamole/recordings
here). - Session timeout: 60–120 minutes is common; too short frustrates users.
- Ban: a sane baseline is 5 failed attempts → 5 minutes ban.
- Sign in as admin → Settings → Connections → New Connection
- Choose RDP and fill in:
- Hostname:
10.0.0.10
orserver.school.edu.tw
- Username/Password: can use
${GUAC_USERNAME}
/${GUAC_PASSWORD}
to reuse portal login - Ignore certificate errors: enable if your RDP server uses self-signed certs
- Display: fixed resolution or “resize to client”
- Recording: enable; path template
${HISTORY_PATH}/${HISTORY_UUID}
is clean and unique
- Hostname:
- Save → return to Home → click the card to connect
Location: extensions/guacamole-branding-example/
What you can change
- Text/labels:
translations/en.json
- Login HTML:
html/warning.html
- Image (keep the filename):
resources/images/saturn/saturn.png
Pack & apply
cd extensions/guacamole-branding-example
chmod +x 01_pack_branding.sh # first time
./01_pack_branding.sh # builds ../guacamole-branding-example.jar
cd ../../
./02_restart.sh # reload web
# Force-refresh your browser (Ctrl+F5 / Cmd+Shift+R)
More details: extensions/guacamole-branding-example/README.md
├── 00_install_docker.sh
├── 01_manager.sh
├── 02_restart.sh
├── 03_check.sh
├── 04_log.sh
├── docker-compose.yml
├── guacamole.properties
├── recordings/ # Session recordings (persisted)
├── log/ # Log files
└── extensions/
└── guacamole-branding-example/
├── 01_pack_branding.sh
├── README.md
├── guac-manifest.json
├── html/warning.html
├── translations/en.json
└── resources/images/saturn/saturn.png
- UI doesn’t load
Port 80 may be taken. Change the mapping in compose from80:8080
to8080:8080
and usehttp://<host>:8080
. - LDAP login fails
Verify bind DN/password and base DNs withldapsearch
. Check theguacamole
container logs via./04_log.sh
. - No recordings
Confirm permissions onrecordings/
(theinit-all
step sets them) and that recording is enabled on the connection. - Logo doesn’t change
Re-pack the branding JAR, restart the stack, then hard-refresh the browser. - LDAP tooling you can use
Try Apache Directory Studio for an easy GUI to inspect your directory tree.
- Put Guacamole behind a reverse proxy and enable HTTPS
- Turn on BAN and RESTRICT to reduce brute force and control access windows
- Prefer central auth (LDAP/SSO) + TOTP
- Keep images up to date within a vetted minor line (e.g., 1.6.x)
- Back up the DB and the
recordings/
volume