lldap
A lightweight LDAP server for centralized user account management.
lldap is a simplified LDAP server designed for self-hosting that provides a clean web UI for managing users and groups. It supports a minimal but sufficient LDAP subset for use with compatible apps (Gitea, Nextcloud, Keycloak user federation, etc.). Self-hosting gives you a single source of truth for user identities without paying for a directory service.
Alternatives considered
Cloud Hosted
| Tool | Open Source | Free Tier | Monthly Cost |
|---|---|---|---|
| Azure Entra ID | No | Limited | From $6/user |
Self Hosted
| Tool | Open Source | Full Features | Notes |
|---|---|---|---|
| OpenLDAP | Yes | Yes | More complete but much harder to configure |
| FreeIPA | Yes | Yes | Full identity stack; heavy for homelab |
| Active Directory | No | No | Windows-only; enterprise-grade complexity |
Installation
Architecture
- Deployment: Single
lldapdeployment in thelldapnamespace - Image:
nitnelave/lldap(alpine variant), digest-pinned via Renovate - Storage: Longhorn PVC (
lldap-data, annotatedk8up.io/backup: "true") for SQLite database and config - Networking: ClusterIP service with separate ports for LDAP and web UI; HTTPRoute via public gateway
Security
- No
runAsUseris set, so the container starts as the image's default user, which is root; privilege escalation is blocked and all capabilities are dropped - Longhorn PVC encrypted at rest via SOPS-managed keys
Updates
Managed by Renovate. Image is digest-pinned.
Data Management
- Database: SQLite stored on
lldap-dataLonghorn PVC (annotatedk8up.io/backup: "true") - Backups: k8up
Schedules to Hetzner and Backblaze via restic, covering the Longhorn PVC.
User Management
lldap is an LDAP provider — it does not consume OIDC. Provides the user directory for Keycloak federation and other LDAP-compatible services. Users and groups managed via the lldap web UI.
Configuration Management
- Bind DN and password, JWT secret from SOPS-encrypted secret
- LDAP base DN and other settings configured in the Deployment env vars
Usage
Manage users and groups through the web UI. Connect applications via LDAP bind using the configured service account. lldap can feed into Keycloak's user federation to provide SSO backed by a central directory.
Cluster-specific deviations from the above live in the per-cluster README — see k8s/apps/lldap/talos/README.md.
Cluster Deployment
lldap — Talos cluster
- Image:
nitnelave/lldap:v0.6.3-alpine@sha256:2a8454b668c1aba7157e832eab0e242e1e7eb5fb7591d7e7774ba05286511ca8
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app.kubernetes.io/name: lldap
name: lldap
namespace: lldap
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app.kubernetes.io/name: lldap
strategy:
rollingUpdate: null
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: lldap
spec:
automountServiceAccountToken: false
containers:
- env:
- name: LLDAP_SMTP_OPTIONS__ENABLE_PASSWORD_RESET
value: 'true'
- name: LLDAP_HTTP_URL
value: https://account.web.kueber.eu
- name: LLDAP_SMTP_OPTIONS__SERVER
valueFrom:
secretKeyRef:
key: host
name: allinkl-smtp-credentials
- name: LLDAP_SMTP_OPTIONS__PORT
valueFrom:
secretKeyRef:
key: port
name: allinkl-smtp-credentials
- name: LLDAP_SMTP_OPTIONS__SMTP_ENCRYPTION
value: STARTTLS
- name: LLDAP_SMTP_OPTIONS__USER
valueFrom:
secretKeyRef:
key: username
name: allinkl-smtp-credentials
- name: LLDAP_SMTP_OPTIONS__PASSWORD
valueFrom:
secretKeyRef:
key: password
name: allinkl-smtp-credentials
- name: LLDAP_SMTP_OPTIONS__FROM
valueFrom:
secretKeyRef:
key: from
name: allinkl-smtp-credentials
envFrom:
- secretRef:
name: lldap
image: nitnelave/lldap:v0.6.3-alpine@sha256:2a8454b668c1aba7157e832eab0e242e1e7eb5fb7591d7e7774ba05286511ca8
name: lldap
ports:
- containerPort: 3890
- containerPort: 17170
resources:
limits:
memory: 128Mi
requests:
cpu: 25m
memory: 64Mi
volumeMounts:
- mountPath: /data
name: lldap-data
priorityClassName: tier-3
restartPolicy: Always
securityContext:
seccompProfile:
type: RuntimeDefault
volumes:
- name: lldap-data
persistentVolumeClaim:
claimName: lldap-data