From d3cb741e44b9bb8422c2a31c77ddd9fef451bab4 Mon Sep 17 00:00:00 2001 From: Pascal Bleser Date: Tue, 14 Oct 2025 11:35:25 +0200 Subject: [PATCH] groupware: try an alternative way to configure Stalwart dynamically in the devtools Docker Compose setup, by using separate files and ${STALWART_AUTH_DIRECTORY} to name to file to mount --- .../opencloud_full/config/stalwart/README.md | 21 ++++ .../config/stalwart/idmldap.toml | 110 ++++++++++++++++++ .../opencloud_full/config/stalwart/ldap.toml | 110 ++++++++++++++++++ .../deployments/opencloud_full/stalwart.yml | 2 +- 4 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 devtools/deployments/opencloud_full/config/stalwart/README.md create mode 100644 devtools/deployments/opencloud_full/config/stalwart/idmldap.toml create mode 100644 devtools/deployments/opencloud_full/config/stalwart/ldap.toml diff --git a/devtools/deployments/opencloud_full/config/stalwart/README.md b/devtools/deployments/opencloud_full/config/stalwart/README.md new file mode 100644 index 0000000000..df25fb0e05 --- /dev/null +++ b/devtools/deployments/opencloud_full/config/stalwart/README.md @@ -0,0 +1,21 @@ +# Stalwart Configuration + +The mechanics are currently to mount a different configuration file depending on the environment, as we support two scenarios that are described in [`services/groupware/DEVELOPER.md`](../../../../../services/groupware/DEVELOPER.md): + + * «production» setup, with OpenLDAP and Keycloak containers + * «homelab» setup, with the built-in IDM (LDAP) and IDP that run as part of the `opencloud` container + +The Docker Compose setup (in [`stalwart.yml`](../../stalwart.yml)) mounts either [`idmldap.toml`](./idmldap.toml) or [`ldap.toml`](./ldap.toml) depending on how the variable `STALWART_AUTH_DIRECTORY` is set, which is either `idmldap` for the homelab setup, or `ldap` for the production setup. + +This is thus all done automatically, but whenever changes are performed to Stalwart configuration files, they must be reflected across those two files, to keep them in sync, as the only entry that should differ is this one: + +```ruby +storage.directory = "ldap" +``` + +or this: + +```ruby +storage.directory = "idmldap" +``` + diff --git a/devtools/deployments/opencloud_full/config/stalwart/idmldap.toml b/devtools/deployments/opencloud_full/config/stalwart/idmldap.toml new file mode 100644 index 0000000000..eac1294b87 --- /dev/null +++ b/devtools/deployments/opencloud_full/config/stalwart/idmldap.toml @@ -0,0 +1,110 @@ +authentication.fallback-admin.secret = "$6$4qPYDVhaUHkKcY7s$bB6qhcukb9oFNYRIvaDZgbwxrMa2RvF5dumCjkBFdX19lSNqrgKltf3aPrFMuQQKkZpK2YNuQ83hB1B3NiWzj." +authentication.fallback-admin.user = "mailadmin" +authentication.master.secret = "$6$4qPYDVhaUHkKcY7s$bB6qhcukb9oFNYRIvaDZgbwxrMa2RvF5dumCjkBFdX19lSNqrgKltf3aPrFMuQQKkZpK2YNuQ83hB1B3NiWzj." +authentication.master.user = "master" +directory.idmldap.attributes.class = "objectClass" +directory.idmldap.attributes.description = "displayName" +directory.idmldap.attributes.email = "mail" +directory.idmldap.attributes.groups = "memberOf" +directory.idmldap.attributes.name = "uid" +directory.idmldap.attributes.secret = "userPassword" +directory.idmldap.base-dn = "o=libregraph-idm" +directory.idmldap.bind.auth.method = "default" +directory.idmldap.bind.dn = "uid=reva,ou=sysusers,o=libregraph-idm" +directory.idmldap.bind.secret = "admin" +directory.idmldap.cache.size = 1048576 +directory.idmldap.cache.ttl.negative = "10m" +directory.idmldap.cache.ttl.positive = "1h" +directory.idmldap.filter.email = "(&(|(objectClass=person)(objectClass=groupOfNames))(mail=?))" +directory.idmldap.filter.name = "(&(|(objectClass=person)(objectClass=groupOfNames))(uid=?))" +directory.idmldap.timeout = "15s" +directory.idmldap.tls.allow-invalid-certs = true +directory.idmldap.tls.enable = true +directory.idmldap.type = "ldap" +directory.idmldap.url = "ldaps://opencloud:9235" +directory.keycloak.auth.method = "user-token" +directory.keycloak.cache.size = 1048576 +directory.keycloak.cache.ttl.negative = "10m" +directory.keycloak.cache.ttl.positive = "1h" +directory.keycloak.endpoint.method = "introspect" +directory.keycloak.endpoint.url = "http://keycloak:8080/realms/openCloud/protocol/openid-connect/userinfo" +directory.keycloak.fields.email = "email" +directory.keycloak.fields.full-name = "name" +directory.keycloak.fields.username = "preferred_username" +directory.keycloak.timeout = "15s" +directory.keycloak.type = "oidc" +directory.ldap.attributes.class = "objectClass" +directory.ldap.attributes.description = "displayName" +directory.ldap.attributes.email = "mail" +directory.ldap.attributes.email-alias = "mailAlias" +directory.ldap.attributes.groups = "memberOf" +directory.ldap.attributes.name = "uid" +directory.ldap.attributes.secret = "userPassword" +directory.ldap.attributes.secret-changed = "pwdChangedTime" +directory.ldap.base-dn = "dc=opencloud,dc=eu" +directory.ldap.bind.auth.dn = "cn=?,ou=users,dc=opencloud,dc=eu" +directory.ldap.bind.auth.enable = true +directory.ldap.bind.auth.search = true +directory.ldap.bind.dn = "cn=admin,dc=opencloud,dc=eu" +directory.ldap.bind.secret = "admin" +directory.ldap.cache.ttl.negative = "10m" +directory.ldap.cache.ttl.positive = "1h" +directory.ldap.filter.email = "(&(|(objectClass=person)(objectClass=groupOfNames))(|(uid=?)(mail=?)(mailAlias=?)(cn=?)))" +directory.ldap.filter.name = "(&(|(objectClass=person)(objectClass=groupOfNames))(|(uid=?)(cn=?)))" +directory.ldap.timeout = "5s" +directory.ldap.tls.allow-invalid-certs = true +directory.ldap.tls.enable = true +directory.ldap.type = "ldap" +directory.ldap.url = "ldap://ldap-server:1389" +http.allowed-endpoint = 200 +http.hsts = true +http.permissive-cors = false +http.url = "'https://' + config_get('server.hostname')" +http.use-x-forwarded = true +metrics.prometheus.auth.secret = "secret" +metrics.prometheus.auth.username = "metrics" +metrics.prometheus.enable = true +server.listener.http.bind = "0.0.0.0:8080" +server.listener.http.protocol = "http" +server.listener.https.bind = "0.0.0.0:443" +server.listener.https.protocol = "http" +server.listener.https.tls.implicit = true +server.listener.imap.bind = "0.0.0.0:143" +server.listener.imap.protocol = "imap" +server.listener.imaptls.bind = "0.0.0.0:993" +server.listener.imaptls.protocol = "imap" +server.listener.imaptls.tls.implicit = true +server.listener.pop3.bind = "0.0.0.0:110" +server.listener.pop3.protocol = "pop3" +server.listener.pop3s.bind = "0.0.0.0:995" +server.listener.pop3s.protocol = "pop3" +server.listener.pop3s.tls.implicit = true +server.listener.sieve.bind = "0.0.0.0:4190" +server.listener.sieve.protocol = "managesieve" +server.listener.smtp.bind = "0.0.0.0:25" +server.listener.smtp.protocol = "smtp" +server.listener.submission.bind = "0.0.0.0:587" +server.listener.submission.protocol = "smtp" +server.listener.submissions.bind = "0.0.0.0:465" +server.listener.submissions.protocol = "smtp" +server.listener.submissions.tls.implicit = true +server.max-connections = 8192 +server.socket.backlog = 1024 +server.socket.nodelay = true +server.socket.reuse-addr = true +server.socket.reuse-port = true +storage.blob = "rocksdb" +storage.data = "rocksdb" +storage.directory = "idmldap" +storage.fts = "rocksdb" +storage.lookup = "rocksdb" +store.rocksdb.compression = "lz4" +store.rocksdb.path = "/opt/stalwart/data" +store.rocksdb.type = "rocksdb" +tracer.console.ansi = true +tracer.console.buffered = true +tracer.console.enable = true +tracer.console.level = "trace" +tracer.console.lossy = false +tracer.console.multiline = false +tracer.console.type = "stdout" diff --git a/devtools/deployments/opencloud_full/config/stalwart/ldap.toml b/devtools/deployments/opencloud_full/config/stalwart/ldap.toml new file mode 100644 index 0000000000..8b2c465296 --- /dev/null +++ b/devtools/deployments/opencloud_full/config/stalwart/ldap.toml @@ -0,0 +1,110 @@ +authentication.fallback-admin.secret = "$6$4qPYDVhaUHkKcY7s$bB6qhcukb9oFNYRIvaDZgbwxrMa2RvF5dumCjkBFdX19lSNqrgKltf3aPrFMuQQKkZpK2YNuQ83hB1B3NiWzj." +authentication.fallback-admin.user = "mailadmin" +authentication.master.secret = "$6$4qPYDVhaUHkKcY7s$bB6qhcukb9oFNYRIvaDZgbwxrMa2RvF5dumCjkBFdX19lSNqrgKltf3aPrFMuQQKkZpK2YNuQ83hB1B3NiWzj." +authentication.master.user = "master" +directory.idmldap.attributes.class = "objectClass" +directory.idmldap.attributes.description = "displayName" +directory.idmldap.attributes.email = "mail" +directory.idmldap.attributes.groups = "memberOf" +directory.idmldap.attributes.name = "uid" +directory.idmldap.attributes.secret = "userPassword" +directory.idmldap.base-dn = "o=libregraph-idm" +directory.idmldap.bind.auth.method = "default" +directory.idmldap.bind.dn = "uid=reva,ou=sysusers,o=libregraph-idm" +directory.idmldap.bind.secret = "admin" +directory.idmldap.cache.size = 1048576 +directory.idmldap.cache.ttl.negative = "10m" +directory.idmldap.cache.ttl.positive = "1h" +directory.idmldap.filter.email = "(&(|(objectClass=person)(objectClass=groupOfNames))(mail=?))" +directory.idmldap.filter.name = "(&(|(objectClass=person)(objectClass=groupOfNames))(uid=?))" +directory.idmldap.timeout = "15s" +directory.idmldap.tls.allow-invalid-certs = true +directory.idmldap.tls.enable = true +directory.idmldap.type = "ldap" +directory.idmldap.url = "ldaps://opencloud:9235" +directory.keycloak.auth.method = "user-token" +directory.keycloak.cache.size = 1048576 +directory.keycloak.cache.ttl.negative = "10m" +directory.keycloak.cache.ttl.positive = "1h" +directory.keycloak.endpoint.method = "introspect" +directory.keycloak.endpoint.url = "http://keycloak:8080/realms/openCloud/protocol/openid-connect/userinfo" +directory.keycloak.fields.email = "email" +directory.keycloak.fields.full-name = "name" +directory.keycloak.fields.username = "preferred_username" +directory.keycloak.timeout = "15s" +directory.keycloak.type = "oidc" +directory.ldap.attributes.class = "objectClass" +directory.ldap.attributes.description = "displayName" +directory.ldap.attributes.email = "mail" +directory.ldap.attributes.email-alias = "mailAlias" +directory.ldap.attributes.groups = "memberOf" +directory.ldap.attributes.name = "uid" +directory.ldap.attributes.secret = "userPassword" +directory.ldap.attributes.secret-changed = "pwdChangedTime" +directory.ldap.base-dn = "dc=opencloud,dc=eu" +directory.ldap.bind.auth.dn = "cn=?,ou=users,dc=opencloud,dc=eu" +directory.ldap.bind.auth.enable = true +directory.ldap.bind.auth.search = true +directory.ldap.bind.dn = "cn=admin,dc=opencloud,dc=eu" +directory.ldap.bind.secret = "admin" +directory.ldap.cache.ttl.negative = "10m" +directory.ldap.cache.ttl.positive = "1h" +directory.ldap.filter.email = "(&(|(objectClass=person)(objectClass=groupOfNames))(|(uid=?)(mail=?)(mailAlias=?)(cn=?)))" +directory.ldap.filter.name = "(&(|(objectClass=person)(objectClass=groupOfNames))(|(uid=?)(cn=?)))" +directory.ldap.timeout = "5s" +directory.ldap.tls.allow-invalid-certs = true +directory.ldap.tls.enable = true +directory.ldap.type = "ldap" +directory.ldap.url = "ldap://ldap-server:1389" +http.allowed-endpoint = 200 +http.hsts = true +http.permissive-cors = false +http.url = "'https://' + config_get('server.hostname')" +http.use-x-forwarded = true +metrics.prometheus.auth.secret = "secret" +metrics.prometheus.auth.username = "metrics" +metrics.prometheus.enable = true +server.listener.http.bind = "0.0.0.0:8080" +server.listener.http.protocol = "http" +server.listener.https.bind = "0.0.0.0:443" +server.listener.https.protocol = "http" +server.listener.https.tls.implicit = true +server.listener.imap.bind = "0.0.0.0:143" +server.listener.imap.protocol = "imap" +server.listener.imaptls.bind = "0.0.0.0:993" +server.listener.imaptls.protocol = "imap" +server.listener.imaptls.tls.implicit = true +server.listener.pop3.bind = "0.0.0.0:110" +server.listener.pop3.protocol = "pop3" +server.listener.pop3s.bind = "0.0.0.0:995" +server.listener.pop3s.protocol = "pop3" +server.listener.pop3s.tls.implicit = true +server.listener.sieve.bind = "0.0.0.0:4190" +server.listener.sieve.protocol = "managesieve" +server.listener.smtp.bind = "0.0.0.0:25" +server.listener.smtp.protocol = "smtp" +server.listener.submission.bind = "0.0.0.0:587" +server.listener.submission.protocol = "smtp" +server.listener.submissions.bind = "0.0.0.0:465" +server.listener.submissions.protocol = "smtp" +server.listener.submissions.tls.implicit = true +server.max-connections = 8192 +server.socket.backlog = 1024 +server.socket.nodelay = true +server.socket.reuse-addr = true +server.socket.reuse-port = true +storage.blob = "rocksdb" +storage.data = "rocksdb" +storage.directory = "ldap" +storage.fts = "rocksdb" +storage.lookup = "rocksdb" +store.rocksdb.compression = "lz4" +store.rocksdb.path = "/opt/stalwart/data" +store.rocksdb.type = "rocksdb" +tracer.console.ansi = true +tracer.console.buffered = true +tracer.console.enable = true +tracer.console.level = "trace" +tracer.console.lossy = false +tracer.console.multiline = false +tracer.console.type = "stdout" diff --git a/devtools/deployments/opencloud_full/stalwart.yml b/devtools/deployments/opencloud_full/stalwart.yml index e2e5ccd336..d247925491 100644 --- a/devtools/deployments/opencloud_full/stalwart.yml +++ b/devtools/deployments/opencloud_full/stalwart.yml @@ -17,7 +17,7 @@ services: - "127.0.0.1:1465:465" volumes: - /etc/localtime:/etc/localtime:ro - - ./config/stalwart:/opt/stalwart/etc + - "./config/stalwart/${STALWART_AUTH_DIRECTORY:-idmldap}.toml:/opt/stalwart/etc/config.toml" - stalwart-data:/opt/stalwart/data environment: STALWART_AUTH_DIRECTORY: "${STALWART_AUTH_DIRECTORY:-idmldap}"