https://github.com/dockopslab/ldap-sso-lab
LDAP-first lab environment that wires OpenLDAP, Pocket ID, phpLDAPadmin, and a self-managed PKI via Docker Compose so you can prototype secure SSO flows end-to-end.
https://github.com/dockopslab/ldap-sso-lab
docker docker-compose ldap openldap phpldapadmin pocket-id sso
Last synced: 17 days ago
JSON representation
LDAP-first lab environment that wires OpenLDAP, Pocket ID, phpLDAPadmin, and a self-managed PKI via Docker Compose so you can prototype secure SSO flows end-to-end.
- Host: GitHub
- URL: https://github.com/dockopslab/ldap-sso-lab
- Owner: dockopslab
- License: apache-2.0
- Created: 2025-10-26T11:15:32.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-10-26T11:52:49.000Z (6 months ago)
- Last Synced: 2025-10-26T13:16:55.430Z (6 months ago)
- Topics: docker, docker-compose, ldap, openldap, phpldapadmin, pocket-id, sso
- Language: Shell
- Homepage:
- Size: 207 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## ldap-sso-lab
This repository defines a self-contained lab for testing LDAP authentication flows with [Pocket ID](https://github.com/pocket-id/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.
---
### Repository Structure
| 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. |
---
### Prerequisites
- Docker Engine 24+ and Docker Compose v2.
- Make sure your user can access the Docker socket (or run commands with `sudo`).
- Optional: `openssl` locally if you want to inspect the generated certificates.
---
### Configure Environment Variables
1. Clone the repository and move into it:
```sh
git clone https://github.com/dockopslab/ldap-sso-lab.git
cd ldap-sso-lab
```
2. Copy the provided template and tailor it to your deployment:
```sh
cp env/ldap-pocketid-template.env env/ldap-pocketid.env
```
3. Open `env/ldap-pocketid.env` and review each section:
- **OpenLDAP**: Define `LDAP_DOMAIN`, admin credentials, ports, and TLS behavior. Set `LDAP_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. Keep `LDAP_SSL=true` when using LDAPS.
- **Pocket ID**: Set `APP_URL`, `TRUST_PROXY`, and `MAXMIND_LICENSE_KEY` if geo-IP features are required.
- **PKI**: Customize `PKI_CA_SUBJECT` and 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 `,ldap` suffix so the certificate also covers the Docker hostname used by Pocket ID when dialing `ldaps://ldap:636`.
- **TailScale (optional)**: Fill out the auth key and route settings if you plan to expose the stack over Tailscale.
4. Keep `env/ldap-pocketid.env` out of version control. The `.gitignore` already excludes `env/*.env` files except templates.
---
### Certificate Management
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.
---
### Build and Run
From the repository root:
```sh
# 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-id
```
Volumes 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:
```sh
docker compose -f compose/ldap-sso-pocketid.yml up -d --force-recreate pki
docker compose -f compose/ldap-sso-pocketid.yml restart openldap pocket-id
```
---
### Network Edge (NGINX / Ingress)
Pocket 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`), adding `X-Forwarded-*` headers so `TRUST_PROXY=true` works 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.
---
### Seeding Directory Data
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:
```sh
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.ldif
```
Adjust 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.
---
### Additional Guides
| Guide | Description |
| --- | --- |
| [`docs/pocketid.md`](docs/pocketid.md) | Detailed Pocket ID configuration: reverse proxy, LDAP connector, claim mapping, and OIDC app setup. |
| [`docs/synology.md`](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.
---
### Official References
- [OpenLDAP Project](https://www.openldap.org/)
- [phpLDAPadmin](https://github.com/leenooks/phpLDAPadmin)
- [Pocket ID](https://github.com/pocket-id/pocket-id)
- [Tailscale](https://tailscale.com/)
- [NGINX Proxy Manager](https://nginxproxymanager.com/)