- Go 49.2%
- CSS 27.4%
- HTML 22.8%
- Dockerfile 0.6%
|
All checks were successful
continuous-integration/drone/push Build is passing
- Verify reset token before showing the form (GET), redirecting with an error immediately if the token is invalid or expired - Add peekResetToken to check token validity non-destructively - Fix POST form action to include query params so the URL check doesn't silently redirect to /lost before processing errors - Update page title and subtitle to reflect the reset step Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| dextpl | ||
| static | ||
| .drone.yml | ||
| .gitignore | ||
| addy.go | ||
| altcha.go | ||
| change.go | ||
| csrf.go | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| ldap.go | ||
| login.go | ||
| lost.go | ||
| main.go | ||
| ratelimit.go | ||
| README.md | ||
| renovate.json | ||
| reset.go | ||
| static.go | ||
chldapasswd
A self-hosted web portal for LDAP account management. Users can log in, view their profile, change their password, recover a lost password, and manage mail aliases — all without requiring direct LDAP access.
Features
- Password change — authenticated users can update their LDAP password (SHA-512 crypt, minimum 12 chars, requires upper/lower/digit)
- Lost password recovery — sends a one-time reset link via email (token expires in 1 hour)
- Profile view — displays LDAP attributes after login
- Mail alias management — create/delete auto-generated email aliases stored as
mailAliasin LDAP, exposed via an addy.io-compatible API - HTTP Basic Auth endpoint (
/auth) — validates credentials against LDAP, forwardsX-Remote-Userheader; suitable for use with nginxauth_request - Docker registry anonymous read — optionally allows unauthenticated
GET/HEADon registry image paths viaX-Special-Authheader - Altcha PoW CAPTCHA — proof-of-work challenge on sensitive forms, no third-party service required
- CSRF protection — token-based on state-changing forms
- Rate limiting — per-IP on login, password change, lost password, and alias API endpoints
- Security headers — CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy
Building
go build -ldflags="-s -w" -o chldapasswd
Requires Go 1.23+. A Drone CI pipeline builds and pushes nemunaire/chldapasswd:latest on each push to master.
Usage
chldapasswd [flags] [serve]
chldapasswd [flags] generate-lost-password-link <uid>
Flags
| Flag | Default | Description |
|---|---|---|
-bind |
127.0.0.1:8080 |
Listen address |
-baseurl |
/ |
URL prefix (for reverse-proxy subpath deployment) |
-config |
(none) | Path to a JSON config file for LDAP settings |
-public-url |
(none) | Base URL used in password reset emails |
-brand-name |
chldapasswd |
Brand name shown in the UI |
-brand-logo |
(none) | URL of a logo image shown in the UI |
-addy-api-secret |
(none) | HMAC secret for the alias API |
-dev |
false |
Development mode: disables HSTS and cookie Secure flag |
Environment variables
All LDAP and SMTP settings can be provided via environment variables (they override CLI flags and config file values):
| Variable | Description |
|---|---|
LDAP_HOST |
LDAP server hostname |
LDAP_PORT |
LDAP server port |
LDAP_STARTTLS |
Enable STARTTLS (1/on/true) |
LDAP_SSL |
Use LDAPS (1/on/true) |
LDAP_BASEDN |
Base DN for searches |
LDAP_SERVICEDN |
DN of the service account |
LDAP_SERVICE_PASSWORD |
Password of the service account |
LDAP_SERVICE_PASSWORD_FILE |
Path to a file containing the service password |
SMTP_HOST |
SMTP server (leave empty to use local sendmail) |
SMTP_PORT |
SMTP port |
SMTP_USER |
SMTP username |
SMTP_PASSWORD |
SMTP password |
SMTP_PASSWORD_FILE |
Path to a file containing the SMTP password |
SMTP_FROM |
Sender address for recovery emails |
PUBLIC_URL |
Public base URL (overrides -public-url) |
BRAND_NAME |
Brand name (overrides -brand-name) |
BRAND_LOGO |
Brand logo URL (overrides -brand-logo) |
ADDY_API_SECRET |
HMAC secret for the alias API |
ALIAS_ALLOWED_DOMAINS |
Comma-separated list of domains users may create aliases under |
DOCKER_REGISTRY_SECRET |
Shared secret for anonymous Docker registry read access |
JSON config file
The -config flag accepts a JSON file whose fields map directly to the LDAP struct:
{
"Host": "auth.example.com",
"Port": 636,
"Ssl": true,
"BaseDN": "dc=example,dc=com",
"ServiceDN": "cn=svc,ou=services,dc=example,dc=com",
"ServicePassword": "secret",
"MailHost": "smtp.example.com",
"MailPort": 587,
"MailUser": "mailer",
"MailPassword": "secret",
"MailFrom": "noreply@example.com"
}
HTTP endpoints
| Method | Path | Description |
|---|---|---|
GET/POST |
/ or /change |
Password change form |
GET/POST |
/login |
Login form — shows user profile on success |
GET/POST |
/lost |
Lost password form |
GET/POST |
/reset |
Password reset via token (from email link) |
GET/POST |
/auth |
HTTP Basic Auth validation for reverse-proxy use |
POST |
/api/v1/aliases |
Create a mail alias (addy.io-compatible) |
DELETE |
/api/v1/aliases/{alias} |
Delete a mail alias |
GET |
/altcha-challenge |
Fetch a PoW challenge for the Altcha widget |
Mail alias API
The alias API is compatible with the addy.io API format. Tokens are HMAC-SHA224 signed and encoded in Base32:
# Create alias
curl -X POST https://auth.example.com/api/v1/aliases \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com"}'
# Delete alias
curl -X DELETE https://auth.example.com/api/v1/aliases/abc123%40example.com \
-H "Authorization: Bearer <token>"
The token for a given uid is: base32(uid + ":" + HMAC-SHA224(apiSecret, uid)).
Alias creation is disabled unless ALIAS_ALLOWED_DOMAINS is set.
Templates
HTML templates are embedded from the static/ directory at build time. To customise the UI, edit the files in static/ before building.
The dextpl/ directory contains a matching theme for Dex to keep a consistent look across the SSO stack.
Docker
docker run -d \
-e LDAP_HOST=auth.example.com \
-e LDAP_PORT=636 \
-e LDAP_SSL=true \
-e LDAP_BASEDN=dc=example,dc=com \
-e LDAP_SERVICEDN=cn=svc,ou=services,dc=example,dc=com \
-e LDAP_SERVICE_PASSWORD=secret \
-e SMTP_HOST=smtp.example.com \
-e SMTP_PORT=587 \
-e SMTP_FROM=noreply@example.com \
-e PUBLIC_URL=https://auth.example.com \
-p 8080:8080 \
nemunaire/chldapasswd