Complete guide to configuring LDAP Manager for different environments and use cases.
LDAP Manager supports multiple configuration approaches with the following precedence order:
- Command-line flags (highest priority)
- Environment variables
.env.localfile.envfile- Default values (lowest priority)
These settings must be configured for LDAP Manager to function:
| Setting | Environment Variable | CLI Flag | Description | Example | Required |
|---|---|---|---|---|---|
| LDAP Server | LDAP_SERVER |
--ldap-server |
LDAP server URI with protocol and port | ldaps://dc1.example.com:636 |
Yes |
| Base DN | LDAP_BASE_DN |
--base-dn |
Base Distinguished Name for searches | DC=example,DC=com |
Yes |
| Readonly User | LDAP_READONLY_USER |
--readonly-user |
Service account username | readonly |
No |
| Readonly Password | LDAP_READONLY_PASSWORD |
--readonly-password |
Service account password | secure_password123 |
No |
LDAP Manager supports two operating modes based on whether a service account is configured:
Service Account Mode (both LDAP_READONLY_USER and LDAP_READONLY_PASSWORD set):
- Background cache refreshes LDAP data every 30 seconds
- Health checks verify LDAP connectivity
- Service account used for initial user lookup during authentication
Per-User Credentials Mode (no service account configured):
- Each request uses the logged-in user's own LDAP credentials
- No background cache (data fetched fresh per request)
- Health checks report simplified status
- Requires Active Directory with UPN-based authentication (
user@domain) - Users must have sufficient LDAP permissions to read directory data
The LDAP server must be specified as a complete URI:
# Standard LDAP (unencrypted, port 389)
LDAP_SERVER=ldap://ldap.example.com:389
# Secure LDAP (encrypted, port 636) - Required for Active Directory
LDAP_SERVER=ldaps://dc1.example.com:636
# Alternative secure port
LDAP_SERVER=ldaps://directory.company.org:3269The Base DN defines the root of your directory search scope:
# Standard domain
LDAP_BASE_DN=DC=example,DC=com
# Organizational unit scope
LDAP_BASE_DN=OU=Users,DC=company,DC=org
# Multi-level domain
LDAP_BASE_DN=DC=subdomain,DC=example,DC=com| Setting | Environment Variable | CLI Flag | Default | Description |
|---|---|---|---|---|
| Active Directory | LDAP_IS_AD |
--active-directory |
false |
Enable Active Directory specific features and attributes |
Active Directory Notes:
- Must use
ldaps://(secure LDAP) for connections - Enables AD-specific user attributes (sAMAccountName, userPrincipalName, etc.)
- Optimizes group membership queries for AD schema
| Setting | Environment Variable | CLI Flag | Default | Description |
|---|---|---|---|---|
| Persist Sessions | PERSIST_SESSIONS |
--persist-sessions |
false |
Store sessions in BBolt database |
| Session Path | SESSION_PATH |
--session-path |
db.bbolt |
Path to session database file |
| Session Duration | SESSION_DURATION |
--session-duration |
30m |
Session timeout duration |
Use Go duration syntax:
# Minutes
SESSION_DURATION=30m
# Hours
SESSION_DURATION=2h
# Mixed units
SESSION_DURATION=1h30m
# Days (as hours)
SESSION_DURATION=24hMemory Storage (Default)
- Fast performance
- No persistent storage
- Sessions lost on application restart
- Suitable for development and testing
BBolt Database Storage
- Persistent across restarts
- Slightly slower performance
- Requires disk space and file permissions
- Recommended for production
| Setting | Environment Variable | CLI Flag | Default | Description |
|---|---|---|---|---|
| Log Level | LOG_LEVEL |
--log-level |
info |
Logging verbosity level |
Valid log levels (in order of verbosity):
trace- Extremely detailed debuggingdebug- Detailed debugging informationinfo- General informational messageswarn- Warning messageserror- Error messages onlyfatal- Fatal errors onlypanic- Panic level messages
| Setting | Environment Variable | CLI Flag | Default | Description |
|---|---|---|---|---|
| Listen Address | LISTEN_ADDR |
--listen |
:3000 |
Server listen address and port |
For traditional LDAP servers like OpenLDAP:
# .env.local
LDAP_SERVER=ldap://openldap.company.local:389
LDAP_BASE_DN=DC=company,DC=local
LDAP_READONLY_USER=cn=readonly,dc=company,dc=local
LDAP_READONLY_PASSWORD=readonly_password
LDAP_IS_AD=false
# Optional settings
LOG_LEVEL=info
PERSIST_SESSIONS=true
SESSION_DURATION=1hFor Microsoft Active Directory:
# .env.local
LDAP_SERVER=ldaps://dc1.ad.example.com:636
LDAP_BASE_DN=DC=ad,DC=example,DC=com
LDAP_READONLY_USER=readonly@ad.example.com
LDAP_READONLY_PASSWORD=Complex_Password123!
LDAP_IS_AD=true
# Production settings
LOG_LEVEL=warn
PERSIST_SESSIONS=true
SESSION_PATH=/data/sessions.bbolt
SESSION_DURATION=30mFor Active Directory environments where each user authenticates with their own credentials:
# .env.local
LDAP_SERVER=ldaps://dc1.ad.example.com:636
LDAP_BASE_DN=DC=ad,DC=example,DC=com
LDAP_IS_AD=true
# No LDAP_READONLY_USER or LDAP_READONLY_PASSWORD
# Users authenticate with their own AD credentials via UPN (user@domain)
LOG_LEVEL=info
PERSIST_SESSIONS=true
SESSION_DURATION=30mFor local development and testing:
# .env.local
LDAP_SERVER=ldap://localhost:389
LDAP_BASE_DN=DC=dev,DC=local
LDAP_READONLY_USER=cn=admin,dc=dev,dc=local
LDAP_READONLY_PASSWORD=admin
LDAP_IS_AD=false
# Development settings
LOG_LEVEL=debug
PERSIST_SESSIONS=true
SESSION_PATH=dev-session.bbolt
SESSION_DURATION=8hFor production deployments with load balancing:
# .env.local
LDAP_SERVER=ldaps://ldap-cluster.prod.company.com:636
LDAP_BASE_DN=DC=prod,DC=company,DC=com
LDAP_READONLY_USER=svc_ldap_readonly
LDAP_READONLY_PASSWORD=very_secure_password_here
LDAP_IS_AD=true
# Production optimization
LOG_LEVEL=error
PERSIST_SESSIONS=true
SESSION_PATH=/persistent/sessions.bbolt
SESSION_DURATION=15m
LISTEN_ADDR=:8080docker run -d \
-e LDAP_SERVER=ldaps://dc1.example.com:636 \
-e LDAP_BASE_DN="DC=example,DC=com" \
-e LDAP_READONLY_USER=readonly \
-e LDAP_READONLY_PASSWORD=password \
-e LDAP_IS_AD=true \
-e LOG_LEVEL=info \
-e PERSIST_SESSIONS=true \
-e SESSION_PATH=/data/sessions.bbolt \
-v /host/data:/data \
-p 3000:3000 \
ghcr.io/netresearch/ldap-managerversion: "3.8"
services:
ldap-manager:
image: ghcr.io/netresearch/ldap-manager:latest
environment:
LDAP_SERVER: ldaps://dc1.example.com:636
LDAP_BASE_DN: DC=example,DC=com
LDAP_READONLY_USER: readonly
LDAP_READONLY_PASSWORD: password
LDAP_IS_AD: "true"
LOG_LEVEL: info
PERSIST_SESSIONS: "true"
SESSION_PATH: /data/sessions.bbolt
SESSION_DURATION: 30m
volumes:
- ./data:/data
- /etc/ssl/certs:/etc/ssl/certs:ro
ports:
- "3000:3000"
restart: unless-stopped# Create .env file
cat > .env << EOF
LDAP_SERVER=ldaps://dc1.example.com:636
LDAP_BASE_DN=DC=example,DC=com
LDAP_READONLY_USER=readonly
LDAP_READONLY_PASSWORD=password
LDAP_IS_AD=true
EOF
# Use with Docker
docker run -d --env-file .env -p 3000:3000 ghcr.io/netresearch/ldap-manager# Mount custom CA certificates
docker run -d \
-v /path/to/ca-certificates:/etc/ssl/certs:ro \
# ... other options
ghcr.io/netresearch/ldap-managerAdd certificates to the system trust store:
# Linux
sudo cp ldap-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
# Then restart LDAP ManagerPrinciple of Least Privilege:
- Create dedicated service account for LDAP Manager
- Grant only read permissions to necessary directory branches
- Use strong, unique passwords
- Regularly rotate credentials
Active Directory Example:
# Create service account
New-ADUser -Name "LDAP-Manager-Readonly" -UserPrincipalName "ldap-readonly@domain.com" -AccountPassword (ConvertTo-SecureString "StrongPassword123!" -AsPlainText -Force) -Enabled $true
# Grant read permissions to specific OUs
dsacls "OU=Users,DC=domain,DC=com" /G "LDAP-Manager-Readonly:GR"
dsacls "OU=Groups,DC=domain,DC=com" /G "LDAP-Manager-Readonly:GR"Cookie Security:
- HTTP-only cookies (XSS protection)
- SameSite=Strict policy (CSRF protection)
- Secure flag when using HTTPS
Session Timeout:
- Balance security vs. usability
- Shorter timeouts for sensitive environments
- Consider user activity patterns
LDAP Manager automatically manages connection pooling. Monitor performance with debug logging:
LOG_LEVEL=debugLDAP directory data is cached automatically with 30-second refresh intervals. This is currently not configurable but provides optimal balance of performance and data freshness.
For Docker deployments, set appropriate resource limits:
services:
ldap-manager:
# ... other config
deploy:
resources:
limits:
memory: 512M
cpus: "0.5"
reservations:
memory: 256M
cpus: "0.25"LDAP Manager validates configuration on startup and provides clear error messages:
# Missing required settings
FATAL the option --ldap-server is required
FATAL the option --base-dn is required
# Invalid format
FATAL could not parse log level: invalid level "verbose"
FATAL invalid LDAP server URI: must start with ldap:// or ldaps://
# Duration parsing errors
FATAL could not parse environment variable "SESSION_DURATION" (containing "30minutes") as duration# Test configuration without starting server
./ldap-manager --help
# Start with debug logging to verify settings
LOG_LEVEL=debug ./ldap-manager
# Test LDAP connectivity
ldapsearch -H ldaps://dc1.example.com:636 -D readonly -w password -b "DC=example,DC=com" "(objectClass=*)" dnCannot connect to LDAP server:
# Test network connectivity
telnet dc1.example.com 636
# Test LDAPS certificate
openssl s_client -connect dc1.example.com:636 -showcerts
# Verify credentials
ldapsearch -H ldaps://dc1.example.com:636 -D readonly -w password -b "DC=example,DC=com" -s baseCertificate verification failed:
- Add server certificate to system trust store
- Use appropriate certificate volume mounts in Docker
- Verify certificate chain is complete
Invalid credentials:
- Test readonly user credentials with ldapsearch
- Verify user format (DN vs. UPN for Active Directory)
- Check account is not locked or expired
Permission denied:
- Verify service account has read access to Base DN
- Check organizational unit permissions
- Ensure account can read user/group attributes
Sessions not persisting:
- Verify
PERSIST_SESSIONS=trueis set - Check session file path permissions
- Monitor disk space for session storage
Session timeout too short/long:
- Adjust
SESSION_DURATIONvalue - Use appropriate Go duration format
- Consider user workflow requirements
Slow LDAP queries:
- Enable debug logging to identify slow operations
- Check LDAP server performance and indexing
- Consider using LDAP replica for read operations
- Monitor network latency to LDAP server
High memory usage:
- Monitor session count and storage
- Check for connection leaks in debug logs
- Consider shorter session timeouts
- Use resource limits in Docker
# .env.local - Development
LDAP_SERVER=ldap://localhost:389
LDAP_BASE_DN=DC=dev,DC=local
LDAP_READONLY_USER=cn=admin,dc=dev,dc=local
LDAP_READONLY_PASSWORD=admin
LOG_LEVEL=debug
SESSION_DURATION=8h# .env.local - Staging
LDAP_SERVER=ldaps://ldap-staging.company.com:636
LDAP_BASE_DN=DC=staging,DC=company,DC=com
LDAP_READONLY_USER=readonly@staging.company.com
LDAP_READONLY_PASSWORD=${STAGING_LDAP_PASSWORD}
LDAP_IS_AD=true
LOG_LEVEL=info
PERSIST_SESSIONS=true
SESSION_DURATION=1h# .env.local - Production
LDAP_SERVER=ldaps://ldap.company.com:636
LDAP_BASE_DN=DC=company,DC=com
LDAP_READONLY_USER=svc_ldap_readonly@company.com
LDAP_READONLY_PASSWORD=${PROD_LDAP_PASSWORD}
LDAP_IS_AD=true
LOG_LEVEL=warn
PERSIST_SESSIONS=true
SESSION_PATH=/data/sessions.bbolt
SESSION_DURATION=30m
LISTEN_ADDR=:8080For advanced deployment scenarios, see the Deployment Guide.