Web-based LDAP administration interface for managing users, groups, and computers.
Supports both Active Directory and OpenLDAP with per-user credential binding.
- Browse, search, and filter users, groups, and computers
- View and edit user details, group memberships, and attributes
- Per-user LDAP credential binding (no shared admin account required)
- Active Directory and OpenLDAP support with automatic detection
- Direct-bind authentication fallback for non-person accounts
- Configurable via environment variables or command-line flags
- LDAP connection pooling with health checks
- LRU caching with background refresh
- Distroless Docker image (13 MB, nonroot, read-only filesystem)
- Multi-platform builds (linux/amd64, linux/arm64, darwin, windows)
docker run -d --name ldap-manager \
-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 \
-p 3000:3000 \
ghcr.io/netresearch/ldap-manager:latestOpen http://localhost:3000 and log in with your LDAP credentials.
The project includes a complete development environment with OpenLDAP, seed data, ACL configuration, and an nginx TLS reverse proxy:
docker compose --profile dev upThis starts:
- OpenLDAP with pre-configured users (
admin/admin,jdoe/password,jsmith/password) - nginx TLS reverse proxy on https://localhost:8443
- phpLDAPadmin on http://localhost:8080
- ldap-manager with live reload
Prerequisites: Go 1.26+, templ CLI.
templ generate
go build -o ldap-manager ./cmd/ldap-manager
./ldap-manager \
--ldap-server ldaps://dc1.example.com:636 \
--active-directory \
--base-dn DC=example,DC=com \
--readonly-user readonly \
--readonly-password readonlyThe server listens on port 3000 by default. Set the PORT environment variable to override.
Go + Fiber + Templ on the backend; Pico CSS +
a hand-written internal/web/static/app.css + vendored htmx on the
frontend. No Node.js toolchain — vendored files are refreshed with
bash scripts/vendor.sh, which verifies SHA-256 checksums against
scripts/vendor.lock.
All options can be set via environment variables, a .env file, or command-line flags. Run ./ldap-manager --help for the full list.
| Environment Variable | Flag | Default | Description |
|---|---|---|---|
LDAP_SERVER |
--ldap-server |
(required) | LDAP URI (ldap:// or ldaps://) |
LDAP_BASE_DN |
--base-dn |
(required) | Base DN for LDAP searches |
LDAP_IS_AD |
--active-directory |
false |
Enable Active Directory mode |
LDAP_READONLY_USER |
--readonly-user |
Service account DN for background cache | |
LDAP_READONLY_PASSWORD |
--readonly-password |
Service account password | |
LDAP_TLS_SKIP_VERIFY |
--tls-skip-verify |
false |
Skip TLS certificate verification |
PORT |
3000 |
HTTP listen port | |
COOKIE_SECURE |
--cookie-secure |
true |
Require HTTPS for cookies |
PERSIST_SESSIONS |
--persist-sessions |
false |
Persist sessions to BoltDB |
SESSION_DURATION |
--session-duration |
30m |
Session lifetime |
LOG_LEVEL |
--log-level |
info |
Log level (trace, debug, info, warn, error) |
When no readonly user is configured, the app uses per-user LDAP credentials for all operations and the background cache is disabled.
For production deployments behind Traefik:
docker network create traefik
# In .env:
TRAEFIK_ENABLE=true
TRAEFIK_HOST=example.com
# Access: https://ldap-manager.example.com| Users List | User Detail |
|---|---|
![]() |
![]() |
| Groups List | Group Detail |
|---|---|
![]() |
![]() |
Published to GitHub Container Registry:
- 13 MB distroless runtime (nonroot UID 65532, read-only filesystem, no shell)
- Multi-platform:
linux/amd64,linux/arm64,linux/arm/v7 - OCI-compliant labels and health check built in
docker run -d --name ldap-manager \
-v /etc/ssl/certs:/etc/ssl/certs:ro -p 3000:3000 \
ghcr.io/netresearch/ldap-manager:latest \
--ldap-server ldaps://dc1.example.com:636 \
--base-dn DC=example,DC=comFull documentation is available in docs/:
- Documentation Index - Complete navigation with cross-references
- Installation Guide - Setup and deployment
- Configuration Reference - All options
- Architecture Overview - System design
- Development Setup - Local environment
- Contributing - Code standards and workflow
LDAP Manager's login page conforms to WCAG 2.2 Level AAA in comfortable density (the default on touch devices, narrow viewports, and under prefers-reduced-motion). In compact density (the default on desktop), the login page meets Level AA; all AAA success criteria are met except 2.5.5 Target Size (Enhanced), which is a deliberate density-preference trade-off.
Conformance is enforced in CI by a contrast unit test (internal/web/contrast_test.go) and an axe-core AAA pass on every E2E run (internal/e2e/axe_test.go). Additional routes will be brought under the same guarantee as they migrate in subsequent slices.
The relationship graph view at /graph (and the List | Graph mode toggle on the user, group, and computer list pages) meets WCAG 2.2 Level AA. An equivalent flat edge table is always rendered below the visual canvas, providing an AAA-equivalent text alternative for every interaction and relationship the canvas displays. The graph pages are covered by the same axe-core ratchet (internal/e2e/axe_graph_test.go).
Contributions welcome! Please open a Pull Request.
This project uses Conventional Commits and formats code with gofumpt + goimports.



