This will build a Docker image for an OpenLDAP Server with Fusion Directory Schema's Included. It includes all the functions in the OpenLDAP Image such as Multi-Master Replication, TLS, and other features.
See Branches for more details
Dockerized OpenLDAP server with FusionDirectory Schema Support
This will build a Docker image for an OpenLDAP Server with Fusion Directory Schema's Included. It includes all the functions in the OpenLDAP Image such as Multi-Master Replication, TLS, and other features.
See Branches for more details
Hello again!
So after testing this fix on clean installation i get the following error (with DEBUG_MODE
) when the OpenLDAP container starts:
adding new entry "cn=<READONLY_USER_USER>,dc=example,dc=com"
5ef4dfdf conn=1005 op=1 do_add: invalid dn (cn=<READONLY_USER_USER>,dc=example,dc=com)
5ef4dfdf conn=1005 op=1 RESULT tag=105 err=34 text=invalid DN
ldap_add: Invalid DN syntax (34)
additional info: invalid DN
5ef4dfdf conn=1005 op=2 UNBIND
5ef4dfdf conn=1005 fd=12 closed
[cont-init.d] 10-openldap: exited 34.
Any Ideas?
openldap-fusiondirectory-app | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
openldap-fusiondirectory-app | [s6-init] ensuring user provided files have correct perms...exited 0.
openldap-fusiondirectory-app | [fix-attrs.d] applying ownership & permissions fixes...
openldap-fusiondirectory-app | [fix-attrs.d] 01-run: applying...
openldap-fusiondirectory-app | [fix-attrs.d] 01-run: exited 0.
openldap-fusiondirectory-app | [fix-attrs.d] 01-s6: applying...
openldap-fusiondirectory-app | [fix-attrs.d] 01-s6: exited 0.
openldap-fusiondirectory-app | [fix-attrs.d] 02-zabbix: applying...
openldap-fusiondirectory-app | [fix-attrs.d] 02-zabbix: exited 0.
openldap-fusiondirectory-app | [fix-attrs.d] 03-logrotate: applying...
openldap-fusiondirectory-app | [fix-attrs.d] 03-logrotate: exited 0.
openldap-fusiondirectory-app | [fix-attrs.d] done.
openldap-fusiondirectory-app | [cont-init.d] executing container initialization scripts...
openldap-fusiondirectory-app | [cont-init.d] 01-permissions: executing...
openldap-fusiondirectory-app | [cont-init.d] 01-permissions: exited 0.
openldap-fusiondirectory-app | [cont-init.d] 02-zabbix: executing...
openldap-fusiondirectory-app | [cont-init.d] 02-zabbix: exited 0.
openldap-fusiondirectory-app | [cont-init.d] 03-cron: executing...
openldap-fusiondirectory-app | **** [cron] Enabling Cron
openldap-fusiondirectory-app | [cont-init.d] 03-cron: exited 0.
openldap-fusiondirectory-app | [cont-init.d] 04-smtp: executing...
openldap-fusiondirectory-app | **** [smtp] Disabling SMTP Features
openldap-fusiondirectory-app | [cont-init.d] 04-smtp: exited 0.
openldap-fusiondirectory-app | [cont-init.d] 09-nginx: executing...
openldap-fusiondirectory-app | [cont-init.d] 09-nginx: exited 0.
openldap-fusiondirectory-app | [cont-init.d] 10-openldap: executing...
openldap-fusiondirectory-app | ** [openldap] First time install detected
openldap-fusiondirectory-app | ** [openldap] Using NIS schema type
openldap-fusiondirectory-app | ** [openldap] Starting OpenLDAP Initialization Sequence
openldap-fusiondirectory-app | ** [openldap] Waiting for OpenLDAP to be ready
openldap-fusiondirectory-app | ** [openldap] Add bootstrap schemas
openldap-fusiondirectory-app | ** [openldap] Convert Schemas to LDIF
openldap-fusiondirectory-app | ** [openldap] Adding Converted Schemas
openldap-fusiondirectory-app | ** [openldap] Setting Config Password
openldap-fusiondirectory-app | ** [openldap] Setting Security
openldap-fusiondirectory-app | ** [openldap] Add bootstrap LDIFs
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/01-config-password.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/01-config-password.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/02-security.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/02-security.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/03-memberOf.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/03-memberOf.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/04-refint.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/04-refint.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/05-index.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/05-index.ldif
openldap-fusiondirectory-app | ** [openldap] Adding ppolicy Schema
openldap-fusiondirectory-app | ** [openldap] Adding read only user
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/readonly-user/readonly-user.ldif
openldap-fusiondirectory-app | ** [openldap] Processing file /assets/slapd/config/bootstrap/ldif/readonly-user/readonly-user-acl.ldif
openldap-fusiondirectory-app | ** [openldap] Starting TLS configuration. Please wait...
openldap-fusiondirectory-app | ** [openldap] Disabling replication config
openldap-fusiondirectory-app | ** [openldap] Found Custom Scripts to Execute
openldap-fusiondirectory-app | ** [openldap] Running Script /assets/custom-scripts/002-update-schemas.sh
openldap-fusiondirectory-app | ** [openldap] Running Script /assets/custom-scripts/001-install-fusiondirectory.sh
openldap-fusiondirectory-app | ** [openldap-fusiondirectory] First time Fusion Directory install detected
openldap-fusiondirectory-app | ** [openldap-fusiondirectory] Reapplying Fusion Directory core schema
openldap-fusiondirectory-app |
openldap-fusiondirectory-app | SASL/EXTERNAL authentication started
openldap-fusiondirectory-app | SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
openldap-fusiondirectory-app | SASL SSF: 0
openldap-fusiondirectory-app | executing 'ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/fusiondirectory/core*_update.ldif'
openldap-fusiondirectory-app | SASL/EXTERNAL authentication started
openldap-fusiondirectory-app | SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
openldap-fusiondirectory-app | SASL SSF: 0
openldap-fusiondirectory-app | ldapmodify: wrong attributeType at line 88, entry "cn={6}core-fd-conf,cn=schema,cn=config"
openldap-fusiondirectory-app | Insertion failed!
It remains saying the LDAP server is unavailable. I had it working until a few days ago, no changes in deployment etc, but it is failing now
Deploy the manifests
LDAP connection should be succesful
Log file is too long, compresses as zip
openldap-57b9b76c9f-9r67h.log.zip
Kubernetes 1.23
In the log, there is this error:
/assets/functions/00-container: line 860: 835 Killed "$@"
The servicename in Kubernetes is openldap.
I hope the debug logs will do. Hope to hear from you.
I have been trying to get this installed for a couple days now, always ending with LDAP errors. I finally tracked down the issue in the custom script when attempting to add all of the needed custom users (Step 2 of /install/assets/custom-scripts/001-install-fusiondirectory.sh). It looks like the script isn't able to add the users based on the log files:
ldap | SASL/EXTERNAL authentication started
ldap | SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
ldap | SASL SSF: 0
ldap | modifying entry "olcDatabase={1}mdb,cn=config"
The Read Only user, ppolicy, schemas, etc. all execute just fine.
I'm open to any ideas on this one.
Hello,
Do someone already succeed to automatically fill the "OU" an "O" attributes of users in the LDAP according to their DN. For example for a user with DN cn=marc, ou=people, ou=marketing, ou=commercial-division, dn=example, dn=org the OU atributes could be automatically fill with ou=marketing or ou=marketing/commercial-division ...or something like that
There is an issue with the parsing of DOMAIN env variable if the domain contains a subdomain
even if BASE_DN env is set explicitely.
e.g :
awesome.domain.tld
results in dc=awesome,dc=tld
When starting 1.4 image, with no previous data, a segfault occurs.
To reproduce, run the container and wait for the error to occur.
To retry, just open a shell and run the following (
rm -rf /etc/openldap/slapd.d/* /var/lib/openldap/* ; kill 1
No segfault, which would allow initial setup to run smoothly until it's end.
[DEBUG] /etc/cont-init.d/10-openldap ** [openldap] Bootstrap LDIF: Processing file /assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ ldap_add_or_modify /assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ local ldif_file=/assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ sed -i 's|<BASE_DN>|dc=sso|g' /assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ sed -i 's|<BACKEND>|mdb|g' /assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ grep -iq changetype /assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ silent ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f /assets/slapd/config/bootstrap/ldif/01-acls.ldif
+ '[' TRUE = TRUE ']'
+ ldapmodify -Y EXTERNAL -Q -H ldapi:/// -f /assets/slapd/config/bootstrap/ldif/01-acls.ldif
ldap_sasl_interactive_bind_s: Can't contact LDAP server (-1)
[cont-init.d] 10-openldap: exited 255.
[cont-init.d] 99-container: executing...
+ PROCESS_NAME=container
+ var_false FALSE
+ '[' FALSE = FALSE ']'
+ output_off
+ '[' TRUE = TRUE ']'
+ set +x
611e7acd slapd starting
**********************************************************************************************************************
**********************************************************************************************************************
**** ****
**** ERROR - Some initialization scripts haven't completed - All services are now halted ****
**** - The following scripts in '/etc/cont-init.d' did not pass their completion check ****
**** ****
**********************************************************************************************************************
**********************************************************************************************************************
10-openldap
**********************************************************************************************************************
**********************************************************************************************************************
**** ****
**** This could have happened for a variety of reasons. Please make sure you have followed the README ****
**** relating to this image and have proper configuration such as environment variables and volumes set ****
**** ****
**** If you feel that you have encountered a bug, please submit an issue on the revision control system ****
**** and provide full debug logs by setting the environment variable 'DEBUG_MODE=TRUE' ****
**** ****
**********************************************************************************************************************
**********************************************************************************************************************
[cont-init.d] 99-container: exited 1.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
This is a request to support MemberOf, switchable from an environment variable
I have a simple setup based on your examples/docker-compose.yml file, using your tiredofit/openldap-fusiondirectory
and tiredofit/fusiondirectory
images.
I'm able to log-in in fusiondirectory web page with the default fd-admin
user, but errors arise immediately saying:
LDAP operation failed!
Object: cn=99478028f7d19f714c3d523ae3031b91,ou=locks,ou=fusiondirectory,dc=mydomain,dc=com
Error: Insufficient access (no write access to parent, while operating on 'cn=99478028f7d19f714c3d523ae3031b91,ou=locks,ou=fusiondirectory,dc=mydomain,dc=com' using LDAP server 'ldap://openldap:389')
I put everything with default values except my domain, and I'm not using TLS.
What I'm doing wrong? I was expecting everything in place to allow fd-admin user to have write access permissions.
Hi,
Sorry for my ignorance, but how can I access the UI fo FusionDirectory (which host/port)?
I've downloaded example docker-compose.yaml locally and run docker-compose up
(after running docker network create services
).
I can see a log of fusiondirectory without any errors.
How can I now access the UI?
I'm running docker on my Mac.
Thanks!
on creating a brand new blank directory, the fuskiondirectory schemas are not applied, I see errrors like
gpg-fd does not exists in the LDAP, skipping… for every schema.
create new container, certs already existing.
the schemas would be installed correctly
I help myself entering the container and do something like
cd /etc/openldap/schema/fusiondirectory/
fusiondirectory-insert-schema -i mail-fd.schema
fusiondirectory-insert-schema -i mail-fd-conf.schema
fusiondirectory-insert-schema -i personal-fd.schema
Hi,
I am attempting to run this, OpenLDAP and FusionDirectory on a raspberry pi 4 however on run the only log I get is
standard_init_linux.go:211: exec user process caused "exec format error",
I believe that this is caused by these containers not being built for Arm64 devices however I am not 100% certain of this. Any help on this would be amazing.
Thanks!
Nextcloud schema doesn't install.
Set PLUGIN_NEXTCLOUD
to "TRUE"
.
Try to enable Nexctloud in the GUI. It gives the error :
Error: Invalid syntax - <b>objectClass: nextcloudAccount</b> (objectClass: value #3 invalid per syntax, [...]
I logged in the LDAP with ApacheDirectoryStudio and found no schema for Nextcloud.
Presence of Nextcloud schema which adds the nextcloudAccount objectClass.
Error: Invalid syntax - <b>objectClass: nextcloudAccount</b> (objectClass: value #3 invalid per syntax, [...]
Hardware : RPi 4B
OS : DietPi v8.12.1 (Debian Bullseye aarch64)
Docker compose 2.14.1 (platform linux/arm64/v8)
Image : tiredofit/openldap-fusiondirectory:2.6-1.4-latest
The file install/assets/custom-scripts/001-install-fusiondirectory.sh
at line 265 has a mistake :
PLUGIN_NEXTCLOUD=${PLUGIN_KOPANO:-"FALSE"}
instead of :
PLUGIN_KOPANO=${PLUGIN_KOPANO:-"FALSE"}
Hello,
Im not sure about what i need to put in the hostname part of docker-compose.yml, and in the HOSTNAME env variable.
Thanks
I have spent a fair amount of time trying to figure this out but the image gets stuck during the init script when waiting for OpenLDAP to start. The openldap section nevers exits and never completes startup. I havent gotten any errors in the output, so not totally sure whats causing it.
[cont-init.d] 10-openldap: executing...
** [openldap] First time install detected
** [openldap] Using NIS schema type
** [openldap] Starting OpenLDAP Initialization Sequence
** [openldap] Waiting for OpenLDAP to be ready
Hi,
Could you generate a new version based on the new openldap image please ?
Only the latest tag is up to date.
Best,
Jerome
Hello Dave,
I think I had solved this but it came back. The issue appears intermittently and I'm pretty sure I'm missing something obvious.
After running the docker-compose
when I try to query the server using ldapsearch it always fails (at least for the server I'm expecting it not to fail for).
ldapsearch -x -b "dc=CURRENT,dc=local" -H ldap://localhost:389
> # extended LDIF
> #
> # LDAPv3
> # base <dc=CURRENT,dc=com> with scope subtree
> # filter: (objectclass=*)
> # requesting: ALL
> #
> # search result
> search: 2
> result: 32 No such object
> # numResponses: 1
However, if I run for this command for an old domain (the one I set my env values with, in the previous runs)
ldapsearch -x -b "dc=OLD,dc=com" -H ldap://localhost:389
This one works fine. It looks like even after removing the docker and image and making sure my docker-compose.yml
file has correct values, my server refuses to reply for the expected domain and always seems to reply on the domain that I had configured previously.
This happened earlier when I kept querying for the domain OLD
but the server always kept refusing on that. And queries for example
domain would run fine (which was my domain from the previous runs). I don't remember how i fixed it, some random combination or docker -rm
docker rmi
with start
stop
worked.
But nothing seems to be working this time. What am I missing?
To be sure, on both the occasions I also ran env
inside the containers to see what are the actual values for the domain
inside the container. And to my surprise, these were the same values which were defined in my docker-compose.yml
(so I'm sure that I'm not passing a wrong yml file during docker-compose.yml up
) and yet ldapsearch
refuses to respond on it.
I tried running the latest versions of this and tiredofit/docker-fusiondirectory images and was having issues when updating the config. Upon saving changes (or even without changes) it would complain that the attribute fdGivenNameRequired
could not be found. This is due to a recent change in FusionDirectory, see the merge where this is introduced
This prevents the creation of the cn=config entity so the listed errors are longer. I managed to get only the one error by creating the cn=config by hand and then trying to apply the configuration again.
tiredofit/openldap-fusiondirectory:1.4
and tiredofit/fusiondirectory:1.4
with an appropriate configuration in a fresh environmentThe configuration tool sets the new values without any erros.
version: '2.2'
services:
openldap-fusiondirectory:
image: tiredofit/openldap-fusiondirectory:1.4
container_name: openldap-fusiondirectory
volumes:
- ./backup:/data/backup
- ./data:/var/lib/openldap
- ./config:/etc/openldap/slapd.d
- ./certs:/certs
environment:
- HOSTNAME=openldap-fusiondirectory
- LOG_LEVEL=256
- DOMAIN=example.io
- BASE_DN=dc=example,dc=io
- ADMIN_PASS=password
- CONFIG_PASS=password
- FUSIONDIRECTORY_ADMIN_USER=fd-admin
- FUSIONDIRECTORY_ADMIN_PASS=password
- ORGANIZATION=Example Org
- ENABLE_READONLY_USER=FALSE
- READONLY_USER_USER=reader
- READONLY_USER_PASS=reader
- ENABLE_TLS=TRUE
- TLS_CRT_FILENAME=cert.pem
- TLS_KEY_FILENAME=key.pem
- TLS_ENFORCE=FALSE
-TLS_CIPHER_SUITE=ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:-DHE-DSS:-RSA:!aNULL:!MD5:!DSS:!SHA
- TLS_VERIFY_CLIENT=never
- SSL_HELPER_PREFIX=ldap
- ENABLE_REPLICATION=FALSE
#- REPLICATION_CONFIG_SYNCPROV=binddn="cn=admin,cn=config" bindmethod=simple credentials="admin" searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1
#- REPLICATION_DB_SYNCPROV=binddn="cn=admin,dc=example,dc=org" bindmethod=simple credentials="admin" searchbase="dc=example,dc=org" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1
#- REPLICATION_HOSTS=ldap://ldap1.example.com ldap://ldap2.example.com ldap://ldap3.example.com
- REMOVE_CONFIG_AFTER_SETUP=FALSE
- ENABLE_BACKUP=TRUE
- BACKUP_INTERVAL=0400
- BACKUP_RETENTION=10080
- ENABLE_ZABBIX=TRUE
- ZABBIX_HOSTNAME=openldap-fusiondirectory-app
- PLUGIN_ALIAS=TRUE
- PLUGIN_APPLICATIONS=TRUE
- PLUGIN_AUDIT=TRUE
- PLUGIN_DEVELOPERS=TRUE
- PLUGIN_DOVECOT=TRUE
- PLUGIN_DSA=TRUE
- PLUGIN_INVITATIONS=TRUE
- PLUGIN_LDAPDUMP=TRUE
- PLUGIN_LDAPMANAGER=TRUE
- PLUGIN_MAIL=TRUE
- PLUGIN_NEXTCLOUD=TRUE
- PLUGIN_NIS=TRUE
- PLUGIN_PERSONAL=TRUE
- PLUGIN_PPOLICY=TRUE
- PLUGIN_PUBLIC_FORMS=TRUE
- PLUGIN_QUOTA=TRUE
- PLUGIN_SSH=TRUE
- PLUGIN_WEBSERVICE=TRUE
networks:
- main
restart: always
ldapadmin:
image: osixia/phpldapadmin:0.9.0
container_name: ldapadmin-fusiondirectory
environment:
- PHPLDAPADMIN_LDAP_HOSTS=openldap-fusiondirectory
networks:
- main
ports:
- 7443:443
depends_on:
- openldap-fusiondirectory
fusiondirectory-app:
container_name: fusiondirectory-app
image: tiredofit/fusiondirectory:1.4
volumes:
- ./logs:/www/logs
#- ./custom:/assets/fusiondirectory
#- ./plugins-custom:/assets/plugins-custom
environment:
- VIRTUAL_HOST=ldap.example.io
- VIRTUAL_NETWORK=main
- VIRTUAL_PORT=80
- LETSENCRYPT_HOST=ldap.example.io
- [email protected]
- ZABBIX_HOSTNAME=fusiondirectory-app
- LDAP1_HOST=openldap-fusiondirectory
- LDAP1_BASE_DN=dc=example,dc=io
- LDAP1_ADMIN_DN=cn=admin,dc=example,dc=io
- LDAP1_ADMIN_PASS=password
- LDAP1_PORT=389
- LDAP1_NAME=Production
- PLUGIN_ALIAS=TRUE
- PLUGIN_APPLICATIONS=TRUE
- PLUGIN_AUDIT=TRUE
- PLUGIN_DEVELOPERS=TRUE
- PLUGIN_DOVECOT=TRUE
- PLUGIN_DSA=TRUE
- PLUGIN_INVITATIONS=TRUE
- PLUGIN_LDAPDUMP=TRUE
- PLUGIN_LDAPMANAGER=TRUE
- PLUGIN_MAIL=TRUE
- PLUGIN_NEXTCLOUD=TRUE
- PLUGIN_NIS=TRUE
- PLUGIN_PERSONAL=TRUE
- PLUGIN_PPOLICY=TRUE
- PLUGIN_PUBLIC_FORMS=TRUE
- PLUGIN_QUOTA=TRUE
- PLUGIN_SSH=TRUE
- PLUGIN_WEBSERVICE=TRUE
ports:
- 7080:80
networks:
- main
depends_on:
- openldap-fusiondirectory
restart: unless-stopped
networks:
main:
external: TRUE
I'm new to LDAP in general and I'm just trying out FusionDirectory, but I suppose adding the updated schema would solve this problem
Hello,
tiredofit/fusiondirectory:2.6.2
with tiredofit/openldap-fusiondirectory:6.7.0
starts properly
tiredofit/fusiondirectory:2.6.2
with tiredofit/openldap-fusiondirectory:7.0.1
ends with error ¨FATAL: Error when connecting the LDAP. Server said 'Could not bind to cn=admin,dc=home,dc=lan (while operating on LDAP server ldap://OpenLDAPServer:389)'.¨ on the Fusion Directory start page.
The docker-compose.yml file that I use is pretty simple and it available here: docker-compose.yml
The interesting part if the URI used: ldap://OpenLDAPServer:389). String "OpenLDAPServer" only appears in environment variable LDAP1_HOST
of service FusionDirectory. And my understanding is that this string refers to service OpenLDAPServer which itself defines a HOSTNAME
. This work fine with 6.7.0
. Now, with 7.0.1
, it looks like the string defined in LDAP1_HOST
is directly used as ldap URI and therefore generates ldap://OpenLDAPServer:389 instead of using the HOSTNAME
Could you please clarify the situation ?
please i can't connect to my ldap server. i have this error Fatal error
FATAL: Error connecting to LDAP server. The server replied 'Could not bind to cn = admin, dc = madia, dc = local (while operating on LDAP server ldap: // openldap-fusiondirectory-app: 389)'.
Please correct the above error and reload the page
this is my docker-compose
version: '3.7'
services:
fusiondirectory-app:
hostname: fusiondirectory.madia.local
container_name: fusiondirectory-app
image: fusiondirectory
labels:
- traefik.enable=true
- traefik.frontend.rule=Host:fusiondirectory.madia.local
- traefik.port=80
- traefik.docker.network=proxy
- traefik.backend=fusiondirectory-app
ports:
- 80:80
volumes:
- fusion_logs:/www/logs
#- ./custom:/assets/fusiondirectory
#- ./plugins-custom:/assets/plugins-custom
environment:
- VIRTUAL_HOST=fusiondirectory.madia.local
- VIRTUAL_NETWORK=proxy
- VIRTUAL_PORT=80
- LETSENCRYPT_HOST=fusiondirectory.madia.local
- LETSENCRYPT_EMAIL=[email protected]
- ZABBIX_HOSTNAME=fusiondirectory-app
- ENABLE_ARGONAUT=FALSE
- PLUGIN_AUDIT=TRUE
- PLUGIN_DSA=TRUE
- PLUGIN_LDAPDUMP=TRUE
- PLUGIN_LDAPMANAGER=TRUE
- PLUGIN_MAIL=TRUE
- PLUGIN_PERSONAL=TRUE
- PLUGIN_PPOLICY=TRUE
- PLUGIN_SSH=TRUE
- PLUGIN_SUDO=TRUE
- PLUGIN_WEBSERVICE=TRUE
- LDAP1_HOST=openldap-fusiondirectory-app #hostname nom du serveur sur lequel tourne le service openldap-fusiondirectory
- LDAP1_BASE_DN=dc=madia,dc=local
- LDAP1_ADMIN_DN=cn=admin,dc=madia,dc=local
- LDAP1_ADMIN_PASS=admin
- LDAP1_PORT=389
- LDAP1_NAME=Production
#- LDAP2_BASE_DN=dc=example,dc=org
#- LDAP2_ADMIN_DN=cn=admin,dc=example,dc=org
#- LDAP2_HOST=openldap-fusiondirectory2
#- LDAP2_ADMIN_PASS=password2
#- LDAP2_NAME=Development
#- LDAP2_TLS=TRUE
networks:
- proxy
- openldap
restart: always
openldap-fusiondirectory-app:
hostname: ldap.madia.local
image: tiredofit/openldap-fusiondirectory
container_name: openldap-fusiondirectory-app
ports:
- 389:389
- 636:636
volumes:
- backup_openldap:/data/backup
- openldap_data:/var/lib/openldap
- openldap_config:/etc/openldap/slapd.d
- certs:/certs
environment:
- HOSTNAME=ldap.madia.local
- LOG_LEVEL=256
- DOMAIN=madia.local
- BASE_DN=dc=madia,dc=local
- ADMIN_PASS=admin
- CONFIG_PASS=config
- FUSIONDIRECTORY_ADMIN_USER=fd-admin
- FUSIONDIRECTORY_ADMIN_PASS=admin
- ORGANIZATION=madia Organization
- ENABLE_READONLY_USER=FALSE
- READONLY_USER_USER=reader
- READONLY_USER_PASS=reader
- ENABLE_TLS=FALSE
#- TLS_CRT_FILENAME=cert.pem
#- TLS_KEY_FILENAME=key.pem
#- TLS_ENFORCE=FALSE
#- TLS_CIPHER_SUITE=ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:-DHE-DSS:-RSA:!aNULL:!MD5:!DSS:!SHA
#- TLS_VERIFY_CLIENT=never
#- SSL_HELPER_PREFIX=ldap
- ENABLE_REPLICATION=FALSE
#- REPLICATION_CONFIG_SYNCPROV=binddn="cn=admin,cn=config" bindmethod=simple credentials="admin" searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1
#- REPLICATION_DB_SYNCPROV=binddn="cn=admin,dc=madia,dc=org" bindmethod=simple credentials="admin" searchbase="dc=madia,dc=local" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1
#- REPLICATION_HOSTS=ldap://ldap1.madia.local ldap://ldap2.madia.local ldap://ldap3.madia.local
#- REMOVE_CONFIG_AFTER_SETUP=FALSE
#- ENABLE_BACKUP=TRUE
#- BACKUP_INTERVAL=0400
#- BACKUP_RETENTION=10080
- ENABLE_ZABBIX=TRUE #activer l'utilisation du serveur zabbix pour la surveillance du service LDAP
- ZABBIX_HOSTNAME=openldap-fusiondirectory-app # surveillance du bon fonctionnement des différents services et systèmes
networks:
- openldap
restart: always
networks:
proxy:
driver: bridge
openldap:
driver: bridge
volumes:
backup_openldap:
openldap_data:
openldap_config:
certs:
fusion_logs:
Originally posted by @paule1997 in #23 (comment)
When running docker-compose up
on the https://github.com/tiredofit/docker-openldap-fusiondirectory/blob/master/examples/docker-compose.yml file, I get the following error:
openldap-fusiondirectory-app | [cont-init.d] 10-openldap: executing...
openldap-fusiondirectory-app | ** [openldap] ERROR: the database directory (/var/lib/openldap) is empty but not the config directory (/etc/openldap/slapd.d)
openldap-fusiondirectory-app | [cont-init.d] 10-openldap: exited 1.
All subsequent operations against the ldap server fails.
I understand that the ports
directive in the docker-compose file exposes them on the host. However, for instances where this image is run on the same host as the corresponding docker-fusiondirectory container, the docker-compose file has to specify that those two ports be exposed.
Shouldn't ports 389
and 636
be exposed by default?
When BASE_DN
is set, as well as DOMAIN
, setup gets completely messed up (BASE_DN
is overwritten in /assets/custom-scripts/001-install-fusiondirectory.sh
).
After first init, user FD is absent, either using defined BASE_DN or DOMAIN base value.
Run setting BASE_DN
& DOMAIN
.
ie:
BASE_DN="dc=localdomain"
DOMAIN="mydomain.com"
BASE_DN
shouldn't be redefined in /assets/custom-scripts/001-install-fusiondirectory.sh
and schemas should work using the provided BASE_DN
Hi,
I just would like to raise that the automatic build system that is used (or the way it is used) is really problematic. The problem is that the tag images are rebuilt... and sometime broken.
Since yesterday, our ldap infra is down using v6.5.0 does not work anymore and fail with this message:
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | [cont-init.d] 10-openldap: exited 1.
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | [cont-init.d] 99-container: executing...
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** ERROR - Some initialization scripts haven't completed - All services are now halted ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** - The following scripts in '/etc/cont-init.d' did not pass their completion check ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr |
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | 10-openldap
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr |
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr |
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** This could have happened for a variety of reasons. Please make sure you have followed the README ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** relating to this image and have proper configuration such as environment variables and volumes set ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** If you feel that you have encountered a bug, please submit an issue on the revision control system ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** and provide full debug logs by setting the environment variable 'DEBUG_MODE=TRUE' ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **** ****
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | **********************************************************************************************************************
openldap-fusiondirectory_openldap-fusiondirectory.1.d07o4rtcxcdb@swarm-node1.gnubila.fr | ****
Would it be possible to fix that please ?
Best,
After setting up this container we were also spinning up a fusiondirectory container pointing to that openldap-fusiondirectory backend.
With the openldap-fusiondirectory container version 1.4-7.1.5 the custom init scripts are not executed.
First spin up the openldap-fusiondirectory setup:
apiVersion: v1
kind: Secret
metadata:
name: openldap-passwords
namespace: fusiondirectory
data:
ADMIN_PASS: <pw>
CONFIG_PASS: <pw>
FUSIONDIRECTORY_ADMIN_PASS: <pw>
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
name: openldap-readonly-password
namespace: fusiondirectory
data:
secretKey: <ro-pw>
type: Opaque
---
apiVersion: v1
kind: Service
metadata:
name: openldap-headless
namespace: fusiondirectory
labels:
app: openldap
ver: v1
spec:
ports:
- port: 389
name: ldap
selector:
app: openldap
ver: v1
---
apiVersion: v1
kind: Service
metadata:
name: openldap-writer
namespace: fusiondirectory
labels:
app: openldap-writer
ver: v1
spec:
ports:
- port: 389
name: ldap
selector:
statefulset.kubernetes.io/pod-name: openldap-0
ver: v1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: openldap
ver: v1
name: openldap
namespace: fusiondirectory
spec:
replicas: 1
serviceName: openldap-headless
selector:
matchLabels:
app: openldap
ver: v1
volumeClaimTemplates:
- metadata:
name: openldap-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "fusiondirectory-data-pv"
resources:
requests:
storage: 1000Mi
- metadata:
name: openldap-config
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "fusiondirectory-config-pv"
resources:
requests:
storage: 500Mi
template:
metadata:
labels:
app: openldap
ver: v1
spec:
containers:
- image: tiredofit/openldap-fusiondirectory:1.4-7.1.5
imagePullPolicy: IfNotPresent
name: openldap
volumeMounts:
- mountPath: /var/lib/openldap
name: openldap-data
- mountPath: /etc/openldap/slapd.d
name: openldap-config
env:
# Container ############################################
- name: ENABLE_CRON
value: "TRUE"
- name: ENABLE_ZABBIX
value: "FALSE"
- name: CONTAINER_LOG_LEVEL
value: "NOTICE"
- name: DEBUG_MODE
value: "FALSE"
# Settings ###############################################
- name: INTERNAL_HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: HOSTNAME
#TODO Setting the fqdn automatically
value: "$(INTERNAL_HOSTNAME).openldap-headless.fusiondirectory.svc.cluster.local"
- name: BACKEND
value: "mdb"
- name: ULIMIT_N
value: "21000"
- name: LOG_LEVEL
value: "256"
- name: DOMAIN
value: "example.com"
- name: ADMIN_PASS
valueFrom:
secretKeyRef:
name: openldap-passwords
key: ADMIN_PASS
- name: CONFIG_PASS
valueFrom:
secretKeyRef:
name: openldap-passwords
key: CONFIG_PASS
- name: KEEP_EXISTING_CONFIG
value: "FALSE"
# FUSIONDIRECTORY ACCESS #################################
- name: FUSIONDIRECTORY_ADMIN_USER
value: "admin"
- name: FUSIONDIRECTORY_ADMIN_PASS
valueFrom:
secretKeyRef:
name: openldap-passwords
key: FUSIONDIRECTORY_ADMIN_PASS
- name: ORGANIZATION
value: "organization"
# LDAP Settings ##########################################
- name: BASE_DN
value: "dc=example,dc=com"
- name: ENABLE_READONLY_USER
value: "TRUE"
- name: READONLY_USER_USER
value: "reader"
- name: READONLY_USER_PASS
valueFrom:
secretKeyRef:
name: openldap-readonly-password
key: secretKey
# TLS ######################################################
- name: ENABLE_TLS
value: "FALSE"
# REPLICATION ##############################################
- name: ENABLE_REPLICATION
value: "FALSE"
# Replication without tls tls_reqcert=never
# - name: REPLICATION_CONFIG_SYNCPROV
# value: "binddn=\"cn=config\" bindmethod=simple credentials=$(CONFIG_PASS) searchbase=\"cn=config\" type=refreshAndPersist retry=\"5 5 60 +\" timeout=1 filter=\"(!(objectclass=olcGlobal))\" tls_reqcert=never"
# # Replication without tls tls_reqcert=never
# - name: REPLICATION_DB_SYNCPROV
# value: "binddn=\"cn=admin,$(BASE_DN)\" bindmethod=simple credentials=$(ADMIN_PASS) searchbase=\"$(BASE_DN)\" type=refreshAndPersist interval=00:00:00:10 retry=\"60 +\" timeout=1 tls_reqcert=never"
#
# #TODO Scaling of the Statefulset won't work -> olcServerID in the config database has to be changed!
# # Please use the correct fqdn
# - name: REPLICATION_HOSTS
# value: "ldap://openldap-0.openldap-headless.fusiondirectory.svc.cluster.local ldap://openldap-1.openldap-headless.fusiondirectory.svc.cluster.local"
- name: REMOVE_CONFIG_AFTER_SETUP
value: "FALSE"
# ZABBIX #################################################
- name: ZABBIX_HOSTNAME
value: "openldap-fusiondirectory-app"
- name: REAPPLY_PLUGIN_SCHEMAS
value: "TRUE"
- name: PLUGIN_ARGONAUT
value: "TRUE"
- name: PLUGIN_MAIL
value: "TRUE"
- name: PLUGIN_ALIAS
value: "TRUE"
- name: PLUGIN_PERSONAL
value: "TRUE"
- name: PLUGIN_POSIX
value: "TRUE"
- name: PLUGIN_DNS
value: "TRUE"
- name: PLUGIN_SUDO
value: "TRUE"
- name: PLUGIN_SYSTEMS
value: "TRUE"
- name: PLUGIN_NEXTCLOUD
value: "TRUE"
- name: PLUGIN_POSTFIX
value: "TRUE"
- name: PLUGIN_DOVECOT
value: "TRUE"
- name: PLUGIN_DHCP
value: "TRUE"
- name: PLUGIN_FUSIONINVENTORY
value: "TRUE"
- name: PLUGIN_GPG
value: "TRUE"
- name: PLUGIN_REPOSITORY
value: "TRUE"
- name: PLUGIN_SPAMASSASSIN
value: "TRUE"
- name: PLUGIN_SSH
value: "TRUE"
- name: PLUGIN_USER_REMINDER
value: "TRUE"
ports:
- containerPort: 389
restartPolicy: Always
Then spin up the fusiondirectory UI:
apiVersion: v1
kind: Service
metadata:
name: fusiondirectory
namespace: fusiondirectory
labels:
app: fusiondirectory
ver: v1
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30067
protocol: TCP
name: http-fusiondirectory
selector:
app: fusiondirectory
ver: v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: fusiondirectory
ver: v1
name: fusiondirectory
namespace: fusiondirectory
spec:
replicas: 1
selector:
matchLabels:
app: fusiondirectory
ver: v1
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: fusiondirectory
ver: v1
spec:
volumes:
- name: apachelogs
emptyDir: {}
containers:
- image: tiredofit/fusiondirectory:1.4-2.7.11
imagePullPolicy: IfNotPresent
name: fusiondirectory
resources:
limits:
memory: 500Mi
cpu: "0.5"
requests:
memory: 100Mi
cpu: "0.1"
volumeMounts:
- mountPath: /www/logs
name: apachelogs
env:
#- name: DEBUG_SMTP
#value: TRUE
#- name: DEBUG_MODE
#value: TRUE
- name: VIRTUAL_HOST
value: "directory.example.com"
- name: VIRTUAL_PORT
value: "80"
- name: ENABLE_ZABBIX
value: "FALSE"
- name: PLUGIN_ARGONAUT
value: "TRUE"
- name: PLUGIN_MAIL
value: "TRUE"
- name: PLUGIN_ALIAS
value: "TRUE"
- name: PLUGIN_PERSONAL
value: "TRUE"
- name: PLUGIN_POSIX
value: "TRUE"
- name: PLUGIN_DNS
value: "TRUE"
- name: PLUGIN_SUDO
value: "TRUE"
- name: PLUGIN_SYSTEMS
value: "TRUE"
- name: PLUGIN_NEXTCLOUD
value: "TRUE"
- name: PLUGIN_POSTFIX
value: "TRUE"
- name: PLUGIN_DOVECOT
value: "TRUE"
- name: PLUGIN_DHCP
value: "TRUE"
- name: PLUGIN_FUSIONINVENTORY
value: "TRUE"
- name: PLUGIN_GPG
value: "TRUE"
- name: PLUGIN_REPOSITORY
value: "TRUE"
- name: PLUGIN_SPAMASSASSIN
value: "TRUE"
- name: PLUGIN_SSH
value: "TRUE"
- name: PLUGIN_USER_REMINDER
value: "TRUE"
- name: PLUGIN_LDAPDUMP
value: "TRUE"
- name: PLUGIN_LDAPMANAGER
value: "TRUE"
- name: PLUGIN_WEBSERVICE
value: "TRUE"
# Connect to only one openldap server
# in case of a openldap replication setup
- name: LDAP1_HOST
value: "openldap-writer"
- name: LDAP1_TLS
value: "FALSE"
- name: LDAP1_SSL
value: "FALSE"
- name: LDAP1_BASE_DN
value: "dc=example,dc=com"
- name: LDAP1_ADMIN_DN
value: "cn=admin,dc=example,dc=com"
# Defined in the openldap-fusiondirectory
# kubernetes exampel installation
# using the same password/secret
- name: LDAP1_ADMIN_PASS
valueFrom:
secretKeyRef:
name: openldap-passwords
key: ADMIN_PASS
- name: LDAP1_PORT
value: "389"
- name: LDAP1_NAME
value: "ldap"
- name: ENABLE_SMTP
value: "FALSE"
# - name: ENABLE_SMTP
# value: "TRUE"
# - name: SMTP_HOST
# value: "smtp.example.net"
# - name: SMTP_PORT
# value: "25"
# - name: SMTP_DOMAIN
# value: "example.net"
# - name: SMTP_MAILDOMAIN
# value: "example.net"
# - name: SMTP_TLS
# value: "off"
ports:
- containerPort: 80
restartPolicy: Always
The login through the fusiondirectory UI is possible.
The scripts being executed, so that the fusiondirectory UI can actually access.
While starting the docker container the first time, the logs show:
2021-10-20-05:30:08 [NOTICE] ** [openldap] Found custom scripts to execute
/assets/functions/10-openldap: line 558: /assets/custom-scripts/001-install-fusiondirectory.sh: Permission denied
/assets/functions/10-openldap: line 558: /assets/custom-scripts/002-update-schemas.sh: Permission denied
After getting a listing of the custom-scripts directory within the container it shows that the scripts are not executable:
total 36K
drwxr-xr-x 2 root root 4.0K Oct 16 17:06 .
drwxr-xr-x 1 root root 4.0K Oct 20 05:30 ..
-rw-r--r-- 1 root root 19K Oct 16 17:06 001-install-fusiondirectory.sh
-rw-r--r-- 1 root root 969 Oct 16 17:06 002-update-schemas.sh
Not only chmod +x /usr/sbin/fusiondirectory-insert-schema but also chmod +x
the other necessary scripts.
Actually, adding the line in the Dockerfile worked for me:
chmod +x /assets/custom-scripts/*.sh && \
I have a subdomain that I am trying to implement this at - trans.hobbithole.blue
, and when these lines are reached, line 28 correctly assigns it, but then it gets reassigned at line 40 incorrectly. It ends up being "dc=trans,dc=blue". This is then the suffix that is used to build the directory structure.
It almost seems like these two loops are doing the same thing with setting the BASE_DN
variable.
Actually, the more I read through this, the more confused I get. SUFFIX
isn't used anywhere else, so it has to just be a way to compute what the BASE_DN
is. ROOT
is used elsewhere, but that should be easy enough to get from the BASE_DN
.
If I were to write this, I would have chosen the implementation at lines 21-28, as it's clearer, cleaner, and works for multiple subdomains. I don't see why BASE_DN
needs to be reset below.
the replication data are not created properly
create a new ldap server, replication parameters like:
- ENABLE_REPLICATION=TRUE
- WAIT_FOR_REPLICAS=false
- REPLICATION_SAFETY_CHECK=TRUE
- REPLICATION_CONFIG_SYNCPROV=binddn="cn=admin,cn=config" bindmethod=simple credentials="pw!" searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1
- REPLICATION_DB_SYNCPROV=binddn="cn=admin,dc=blabla,dc=de" bindmethod=simple credentials="pw!" searchbase="dc=elternserver,dc=de" type=refreshAndPersist interval=00:00:00:10 retry="60 +" timeout=1
- REPLICATION_HOSTS=ldap://ldap1.blabla.de ldap://ldap4.blabla.de ldap://ldap2.blabla.de
...
# Add sync replication on config
dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcSyncRepl
olcSyncRepl: rid=001 provider=ldap://ldap1.blabla.de binddn="cn=config" bindmethod=simple credentials="pw!" searchbase="cn=config" type=refreshAndPersist retry="60 +" timeout=1 filter="(!(objectclass=olcGlobal))"
<REPLICATION_HOSTS_CONFIG_SYNC_REPL>
...
instead the < REPL ... line I'd like to see the other servers
Hello,
I deploy docker image of this openldap and fusiondirectory app to manage my ldap and through the web interface i can add users but none of them Hadès attribute memberof or OU despite i had users as members of groups. It seem that that attributes are not enable...
I have used the docker composer and change the image for various version, but any of them worked with the fusion https://github.com/tiredofit/docker-fusiondirectory I always get that the OU=fusiondirectory doesn't exist, can you check that?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.