Guacamole + LDAP: Set Up Secure Remote Access for Your Entire Team
Remote access is one of those problems that sounds simple until you're managing 50 employees who all need to connect to different machines. TeamViewer wants $50/user/month. AnyDesk's pricing is a mystery. And your security team keeps asking about audit logs.
Apache Guacamole solves this with a twist: everything runs through the browser. No client installs. No VPN headaches. Just point your team to a URL and they're in.
But the real magic happens when you connect it to LDAP. Suddenly your Active Directory users can authenticate once and access exactly the machines they're supposed to. Here's how to set it up properly.
What We're Building
A production Guacamole deployment with:
- LDAP authentication against Active Directory
- Connection templates that auto-assign based on group membership
- Optional MFA with TOTP
- Docker Compose for easy deployment
The Docker Compose Setup
version: '3.8'
services:
guacd:
image: guacamole/guacd:latest
container_name: guacd
restart: always
networks:
- guacamole
guacamole:
image: guacamole/guacamole:latest
container_name: guacamole
restart: always
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRES_HOSTNAME: postgres
POSTGRES_DATABASE: guacamole_db
POSTGRES_USER: guacamole_user
POSTGRES_PASSWORD: ${DB_PASSWORD}
# LDAP Configuration
LDAP_HOSTNAME: ${LDAP_HOST}
LDAP_PORT: 389
LDAP_ENCRYPTION_METHOD: starttls
LDAP_USER_BASE_DN: ou=Users,dc=company,dc=com
LDAP_USERNAME_ATTRIBUTE: sAMAccountName
LDAP_SEARCH_BIND_DN: cn=guacamole-svc,ou=ServiceAccounts,dc=company,dc=com
LDAP_SEARCH_BIND_PASSWORD: ${LDAP_BIND_PASSWORD}
LDAP_GROUP_BASE_DN: ou=Groups,dc=company,dc=com
LDAP_GROUP_NAME_ATTRIBUTE: cn
# TOTP (Optional MFA)
TOTP_ENABLED: "true"
TOTP_ISSUER: "YourCompany Guacamole"
ports:
- "172.17.0.1:8080:8080"
networks:
- guacamole
postgres:
image: postgres:15-alpine
container_name: guacamole-db
restart: always
environment:
POSTGRES_DB: guacamole_db
POSTGRES_USER: guacamole_user
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- ./init:/docker-entrypoint-initdb.d
- postgres_data:/var/lib/postgresql/data
networks:
- guacamole
volumes:
postgres_data:
networks:
guacamole:
driver: bridge
Before starting, initialize the database schema:
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --postgresql > init/initdb.sql
Configuring LDAP Authentication
The environment variables above handle basic LDAP auth, but you'll want to map AD groups to Guacamole permissions. Create a file at extensions/ldap-schema.xml:
<user-mapping>
<authorize
username-attribute="sAMAccountName"
password-attribute="userPassword">
<connection name="Dev Server">
<protocol>rdp</protocol>
<param name="hostname">192.168.1.100</param>
<param name="port">3389</param>
<param name="username">${GUAC_USERNAME}</param>
<param name="password">${GUAC_PASSWORD}</param>
<param name="security">nla</param>
<param name="ignore-cert">true</param>
</connection>
</authorize>
</user-mapping>
Group-Based Connection Access
The real power comes from mapping AD groups to connections. In Guacamole's admin interface:
- Create a connection group called "Engineering Servers"
- Add your RDP/SSH/VNC connections to it
- Under Permissions, grant read access to your AD group
CN=Engineering,OU=Groups,DC=company,DC=com
Now anyone in that AD group automatically sees those connections when they log in. No manual user provisioning.
Adding MFA with TOTP
The TOTP_ENABLED: "true" flag activates time-based one-time passwords. First login after enabling:
- User authenticates with LDAP credentials
- Guacamole prompts them to scan a QR code
- They enter the 6-digit code from their authenticator app
- Future logins require both password and TOTP
For users who lose their authenticator, admins can reset TOTP enrollment through the admin panel.
Connection Templates for Scale
Instead of creating connections manually, use parameterized templates. Add this to your Guacamole configuration:
# In guacamole.properties
ldap-user-attributes: department, employeeID
Then create connections with dynamic parameters:
Hostname: ${GUAC_USER_ATTR_department}-workstation.internal
Username: ${GUAC_USERNAME}
An engineer logging in gets connected to engineering-workstation.internal automatically. Sales gets sales-workstation.internal. Zero manual configuration per user.
Production Hardening
A few things you'll want in production:
SSL termination through your reverse proxy (Nginx handles this on Elestio):
location /guacamole/ {
proxy_pass http://172.17.0.1:8080/guacamole/;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Session timeout to auto-disconnect idle users:
# guacamole.properties
api-session-timeout: 60
Audit logging for compliance:
guacd-log-level: info
Troubleshooting Common Issues
LDAP connection fails: Check if your bind DN has read access to the user base. Test with ldapsearch:
ldapsearch -H ldap://your-dc.company.com -D "cn=guacamole-svc,ou=ServiceAccounts,dc=company,dc=com" -W -b "ou=Users,dc=company,dc=com" "(sAMAccountName=testuser)"
Users can't see connections: Verify the user's AD groups match exactly what you configured in Guacamole permissions. Group names are case-sensitive.
RDP connections hang: Usually a Network Level Authentication issue. Either enable NLA on the target machine or set security=rdp instead of nla in the connection settings.
TOTP not prompting: Clear browser cookies and try again. The TOTP enrollment only triggers on fresh sessions.
Deploying on Elestio
Skip the Docker setup entirely with Elestio's managed Guacamole. You get:
- Pre-configured with PostgreSQL backend
- Automatic SSL certificates
- Nginx reverse proxy ready
- Backups included
Starting at ~$16/month for a 2 CPU / 4GB instance that handles 50+ concurrent users comfortably.
What's Next
Once you have basic LDAP working, consider:
- Recording sessions for compliance (Guacamole supports this natively)
- Duo integration for enterprise MFA
- Load balancing guacd for high availability
The combination of browser-based access and AD integration makes Guacamole genuinely useful for teams. No more "install this client" emails. No more shared credentials. Just click and connect.
Thanks for reading. See you in the next one.