Guacamole + LDAP: Set Up Secure Remote Access for Your Entire Team

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:

  1. Create a connection group called "Engineering Servers"
  2. Add your RDP/SSH/VNC connections to it
  3. 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:

  1. User authenticates with LDAP credentials
  2. Guacamole prompts them to scan a QR code
  3. They enter the 6-digit code from their authenticator app
  4. 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.