services:
ldap:
profiles: ["ldap-posix"]
image: osixia/openldap:1.5.0
container_name: ${PROJECT_NAME:-devops}-ldap
hostname: ldap-posix.example.com
ports:
- "389:389"
- "636:636"
environment:
- LDAP_ORGANISATION=Example Corp POSIX
- LDAP_DOMAIN=example.com
- LDAP_ADMIN_PASSWORD=admin_password
- LDAP_CONFIG_PASSWORD=config_password
- LDAP_READONLY_USER=true
- LDAP_READONLY_USER_USERNAME=readonly
- LDAP_READONLY_USER_PASSWORD=readonly_password
- LDAP_TLS=false
- LDAP_LOG_LEVEL=256
# IMPORTANT: Keep config so we can disable memberOf overlay after setup
- LDAP_REMOVE_CONFIG_AFTER_SETUP=false
volumes:
- ldap-data:/var/lib/ldap
- ldap-config:/etc/ldap/slapd.d
command: --copy-service --loglevel debug
ldap-admin:
profiles: ["ldap-posix"]
image: osixia/phpldapadmin:0.9.0
container_name: ${PROJECT_NAME:-devops}-ldap-admin
ports:
- "6443:443"
environment:
- PHPLDAPADMIN_LDAP_HOSTS=ldap
- PHPLDAPADMIN_HTTPS=false
depends_on:
- ldap
labels:
- "ldap.admin.url=http://localhost:6443"
ldap-seed:
profiles: ["ldap-posix"]
image: osixia/openldap:1.5.0
container_name: ${PROJECT_NAME:-devops}-ldap-seed
depends_on:
- ldap
volumes:
- ./ldap-posix-seed.ldif:/seed.ldif:ro
entrypoint: /bin/bash
command:
- -c
- |
echo 'Waiting for LDAP POSIX server to be ready...';
for i in $$(seq 1 30); do
if ldapsearch -x -H ldap://ldap:389 -b 'dc=example,dc=com' '(objectClass=*)' dn 2>/dev/null | grep -q 'dc=example,dc=com'; then
echo 'LDAP server is ready';
break;
fi;
echo 'Attempt '$$i'/30: LDAP not ready, waiting...';
sleep 2;
done;
echo 'Disabling memberOf overlay for pure POSIX mode...';
ldapmodify -x -H ldap://ldap:389 -D 'cn=admin,cn=config' -w config_password <<'EOFMOD' || echo 'memberOf overlay may already be disabled';
dn: olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config
changetype: delete
EOFMOD
echo 'Loading POSIX seed data...';
ldapadd -x -H ldap://ldap:389 -D 'cn=admin,dc=example,dc=com' -w admin_password -f /seed.ldif || true;
echo 'LDAP POSIX seed data loaded';
echo 'SEED_COMPLETE' > /tmp/seed_status;
tail -f /dev/null
phoenix:
environment:
# Enable LDAP authentication
- PHOENIX_ENABLE_AUTH=true
- PHOENIX_ADMINS=
- PHOENIX_DISABLE_BASIC_AUTH=false
# OAuth2 Dev IDP Configuration
- PHOENIX_OAUTH2_DEV_ALLOW_SIGN_UP=true
- PHOENIX_OAUTH2_DEV_AUTO_LOGIN=false
# Role syncing via OIDC
- PHOENIX_OAUTH2_DEV_SCOPES=roles
- PHOENIX_OAUTH2_DEV_ROLE_ATTRIBUTE_PATH=role
- PHOENIX_OAUTH2_DEV_ROLE_MAPPING=admin:ADMIN,editor:MEMBER,viewer:VIEWER
# LDAP Configuration
- PHOENIX_LDAP_HOST=ldap
- PHOENIX_LDAP_PORT=389
- PHOENIX_LDAP_TLS_MODE=none
- PHOENIX_LDAP_BIND_DN=cn=readonly,dc=example,dc=com
- PHOENIX_LDAP_BIND_PASSWORD=readonly_password
- PHOENIX_LDAP_USER_SEARCH_BASE_DNS=["ou=users,dc=example,dc=com"]
- PHOENIX_LDAP_USER_SEARCH_FILTER=(uid=%s)
- PHOENIX_LDAP_ATTR_EMAIL=mail
- PHOENIX_LDAP_ATTR_DISPLAY_NAME=displayName
# POSIX MODE: Use GROUP_SEARCH_FILTER instead of memberOf attribute
- PHOENIX_LDAP_ATTR_MEMBER_OF=
- PHOENIX_LDAP_GROUP_SEARCH_BASE_DNS=["ou=posix-groups,dc=example,dc=com"]
- PHOENIX_LDAP_GROUP_SEARCH_FILTER=(&(objectClass=posixGroup)(memberUid=%s))
# memberUid contains username (e.g., "admin"), not DN
- PHOENIX_LDAP_GROUP_SEARCH_FILTER_USER_ATTR=uid
- PHOENIX_LDAP_GROUP_ROLE_MAPPINGS=[{"group_dn":"cn=admins,ou=posix-groups,dc=example,dc=com","role":"ADMIN"},{"group_dn":"cn=members,ou=posix-groups,dc=example,dc=com","role":"MEMBER"},{"group_dn":"cn=viewers,ou=posix-groups,dc=example,dc=com","role":"VIEWER"},{"group_dn":"*","role":"VIEWER"}]
- PHOENIX_LDAP_ALLOW_SIGN_UP=true
depends_on:
- ldap
labels:
- "phoenix.auth.mode=ldap-posix"
- "phoenix.auth.ldap=enabled"
volumes:
ldap-data:
ldap-config: