This repository defines a self-contained lab for testing LDAP authentication flows with Pocket ID and future SSO providers. It provisions:
- OpenLDAP pre-configured with TLS and optional sample data.
- phpLDAPadmin to inspect and manage entries over HTTPS.
- Pocket ID (OIDC provider) pre-wired to the LDAP directory.
- PKI helper that issues an internal CA and per-service server certificates, renewing them automatically.
Everything runs via Docker Compose, so you can iterate on schema, TLS, and IdP behavior locally or in an isolated environment.
| Path | Purpose |
|---|---|
compose/ldap-sso-pocketid.yml |
Main Docker Compose definition for the stack. |
env/ |
Environment files (*.env) that drive container configuration; templates are committed, secrets are not. |
dockerfile/ |
Custom Dockerfiles for PKI, OpenLDAP, and the Pocket ID wrapper image. |
scripts/ |
Helper scripts used inside containers (PKI automation, entrypoints). |
template/ldap-ldif/ |
Example LDIF files to seed groups and users. |
docs/ |
Additional how-tos (Pocket ID integration notes, Synology guides, etc.). |
docs/resources/ |
Supporting screenshots referenced in the docs. |
- Docker Engine 24+ and Docker Compose v2.
- Make sure your user can access the Docker socket (or run commands with
sudo). - Optional:
openssllocally if you want to inspect the generated certificates.
-
Clone the repository and move into it:
git clone https://github.com/dockopslab/ldap-sso-lab.git cd ldap-sso-lab -
Copy the provided template and tailor it to your deployment:
cp env/ldap-pocketid-template.env env/ldap-pocketid.env
-
Open
env/ldap-pocketid.envand review each section:- OpenLDAP: Define
LDAP_DOMAIN, admin credentials, ports, and TLS behavior. SetLDAP_TLS_*paths to/certs/...(they are mounted from the PKI container). Adjust base DN values to match your organization. - phpLDAPadmin: Update
LDAP_HOST, port, and bind credentials if you changed them above. KeepLDAP_SSL=truewhen using LDAPS. - Pocket ID: Set
APP_URL,TRUST_PROXY, andMAXMIND_LICENSE_KEYif geo-IP features are required. - PKI: Customize
PKI_CA_SUBJECTand the per-service SAN values. You can provide multiple DNS/IP entries by comma-separating them (e.g.,PKI_LDAP_SAN_DNS=ldap.example.local,ldap). Keep the literal,ldapsuffix so the certificate also covers the Docker hostname used by Pocket ID when dialingldaps://ldap:636. - TailScale (optional): Fill out the auth key and route settings if you plan to expose the stack over Tailscale.
- OpenLDAP: Define
-
Keep
env/ldap-pocketid.envout of version control. The.gitignorealready excludesenv/*.envfiles except templates.
The pki service (built from dockerfile/pki.Dockerfile) runs scripts/pki-init.sh, which:
- Issues a long-lived internal CA (
ca.crt/ca.key). - Creates per-service server certificates with SANs derived from
PKI_*variables. - Tracks a hash of the CN/SAN configuration and automatically regenerates certificates when those values change or when renewal thresholds are reached.
- Publishes compatibility symlinks (
ldap.crt,ldap.key,ldap-ca.crt) consumed by OpenLDAP and Pocket ID.
The custom Pocket ID image (see dockerfile/pocket-id.Dockerfile) copies the CA bundle from /certs/ca.crt into the system trust store on startup, so its Go LDAP client trusts the internal PKI without manual steps.
From the repository root:
# Build custom images (PKI, OpenLDAP, Pocket ID wrapper)
docker compose -f compose/ldap-sso-pocketid.yml build
# Start the full stack
docker compose -f compose/ldap-sso-pocketid.yml up -d
# Tail logs for troubleshooting
docker compose -f compose/ldap-sso-pocketid.yml logs -f pki openldap pocket-idVolumes defined in the compose file (pki_certs, ldap_data, ldap_config, pocketid_data) persist certificates, directory data, and Pocket ID state across restarts.
To update certificates after editing PKI_* variables, restart the PKI container and then restart the consumers:
docker compose -f compose/ldap-sso-pocketid.yml up -d --force-recreate pki
docker compose -f compose/ldap-sso-pocketid.yml restart openldap pocket-idPocket ID requires HTTPS with a valid domain in order to register passkeys and serve the OIDC endpoints. Deploy an external reverse proxy (e.g., NGINX Proxy Manager, Traefik, Caddy) that:
- Terminates TLS for your public FQDN (e.g.,
auth.example.com) using certificates issued by a trusted CA (Let’s Encrypt, internal PKI, etc.). - Proxies traffic to the Pocket ID container (
pocket-id-ldap-sso:1411), addingX-Forwarded-*headers soTRUST_PROXY=trueworks correctly. - Exposes phpLDAPadmin and any other management UI only over secure channels. When possible, keep administrative endpoints private (for example, publish them exclusively through the Tailscale container or another zero-trust tunnel instead of the public edge).
Ensure DNS records point to the proxy and that the domain configured in APP_URL matches the URL users hit, otherwise passkey registration/login will fail.
Use the LDIF samples under template/ldap-ldif/ as a starting point. You can apply them from the host once OpenLDAP is running, for example:
docker compose -f compose/ldap-sso-pocketid.yml exec openldap \
ldapadd -x -D "cn=admin,dc=example,dc=local" -W \
-f /templates/ldap-ldif/inetOrgPerson.ldifAdjust the bind DN and template path to align with your environment and mounts.
You can also upload those LDIF templates through phpLDAPadmin (phpldapadmin-ldap-sso) by using the Import feature inside the web UI, which is often more convenient for quick tweaks while iterating on the directory schema.
| Guide | Description |
|---|---|
docs/pocketid.md |
Detailed Pocket ID configuration: reverse proxy, LDAP connector, claim mapping, and OIDC app setup. |
docs/synology.md |
Steps to bind Synology DSM to the lab LDAP and enable SSO via Pocket ID. |
Feel free to extend these documents with environment-specific steps or screenshots as you harden the stack for production use.