From a6e4cda0e324d22972442cb3ebf0746e86f5fbc2 Mon Sep 17 00:00:00 2001
From: Pascal Bleser
Date: Wed, 8 Oct 2025 19:20:31 +0200
Subject: [PATCH] groupware: make everything also work with the built-in LDAP
and IDP
---
.../config/stalwart/config.toml | 4 +-
devtools/deployments/opencloud_full/ldap.yml | 1 +
.../deployments/opencloud_full/opencloud.yml | 3 +
.../deployments/opencloud_full/stalwart.yml | 2 +
services/groupware/DEVELOPER.md | 361 ++++++++++++++----
5 files changed, 302 insertions(+), 69 deletions(-)
diff --git a/devtools/deployments/opencloud_full/config/stalwart/config.toml b/devtools/deployments/opencloud_full/config/stalwart/config.toml
index 4fec2d941c..e7599a6655 100644
--- a/devtools/deployments/opencloud_full/config/stalwart/config.toml
+++ b/devtools/deployments/opencloud_full/config/stalwart/config.toml
@@ -3,7 +3,7 @@ authentication.fallback-admin.user = "mailadmin"
authentication.master.secret = "$6$4qPYDVhaUHkKcY7s$bB6qhcukb9oFNYRIvaDZgbwxrMa2RvF5dumCjkBFdX19lSNqrgKltf3aPrFMuQQKkZpK2YNuQ83hB1B3NiWzj."
authentication.master.user = "master"
directory.idmldap.attributes.class = "objectClass"
-directory.idmldap.attributes.description = "description"
+directory.idmldap.attributes.description = "displayName"
directory.idmldap.attributes.email = "mail"
directory.idmldap.attributes.groups = "memberOf"
directory.idmldap.attributes.name = "uid"
@@ -95,7 +95,7 @@ server.socket.reuse-addr = true
server.socket.reuse-port = true
storage.blob = "rocksdb"
storage.data = "rocksdb"
-storage.directory = "ldap"
+storage.directory = "%{env:STALWART_AUTH_DIRECTORY}%"
storage.fts = "rocksdb"
storage.lookup = "rocksdb"
store.rocksdb.compression = "lz4"
diff --git a/devtools/deployments/opencloud_full/ldap.yml b/devtools/deployments/opencloud_full/ldap.yml
index 52b3f83e06..a874e0df95 100644
--- a/devtools/deployments/opencloud_full/ldap.yml
+++ b/devtools/deployments/opencloud_full/ldap.yml
@@ -24,6 +24,7 @@ services:
OC_LDAP_SERVER_WRITE_ENABLED: "false" # assuming the external ldap is not writable
# OC_RUN_SERVICES specifies to start all services except glauth, idm and accounts. These are replaced by external services
OC_EXCLUDE_RUN_SERVICES: idm
+ STALWART_AUTH_DIRECTORY: "ldap"
ldap-server:
image: bitnamilegacy/openldap:2.6
diff --git a/devtools/deployments/opencloud_full/opencloud.yml b/devtools/deployments/opencloud_full/opencloud.yml
index 1c8790dcf2..56859c2e8a 100644
--- a/devtools/deployments/opencloud_full/opencloud.yml
+++ b/devtools/deployments/opencloud_full/opencloud.yml
@@ -58,6 +58,9 @@ services:
COMPANION_DOMAIN: ${COMPANION_DOMAIN:-companion.opencloud.test}
# enable to allow using the banned passwords list
OC_PASSWORD_POLICY_BANNED_PASSWORDS_LIST: banned-password-list.txt
+ IDM_REVASVC_PASSWORD: "admin"
+ OC_LDAP_BIND_PASSWORD: "admin"
+ IDM_LDAPS_ADDR: 0.0.0.0:9235
volumes:
- ./config/opencloud/app-registry.yaml:/etc/opencloud/app-registry.yaml
- ./config/opencloud/csp.yaml:/etc/opencloud/csp.yaml
diff --git a/devtools/deployments/opencloud_full/stalwart.yml b/devtools/deployments/opencloud_full/stalwart.yml
index 6f6ed50664..e2e5ccd336 100644
--- a/devtools/deployments/opencloud_full/stalwart.yml
+++ b/devtools/deployments/opencloud_full/stalwart.yml
@@ -19,6 +19,8 @@ services:
- /etc/localtime:/etc/localtime:ro
- ./config/stalwart:/opt/stalwart/etc
- stalwart-data:/opt/stalwart/data
+ environment:
+ STALWART_AUTH_DIRECTORY: "${STALWART_AUTH_DIRECTORY:-idmldap}"
labels:
- "traefik.enable=true"
- "traefik.http.routers.stalwart.entrypoints=https"
diff --git a/services/groupware/DEVELOPER.md b/services/groupware/DEVELOPER.md
index d0dee5e1d4..be4b53b23a 100644
--- a/services/groupware/DEVELOPER.md
+++ b/services/groupware/DEVELOPER.md
@@ -1,18 +1,21 @@
-# Introduction
+# Groupware Developer Guide
-The Groupware component of OpenCloud
+
-* is implemented as yet another microservice within the OpenCloud framework (see `./services/groupware/`)
-* is essentially providing a REST API to the OpenCloud UI clients (web, mobile) that is high-level and adapted to the needs of the UIs
-* the implementation of that REST API turns those high-level APIs into lower-level [JMAP](https://jmap.io/) API calls to [Stalwart, the JMAP mail server](https://stalw.art/), using our own JMAP client library in `./pkg/jmap/` with a couple of additional RFCs used by JMAP in `./pkg/jscalendar` and `./pkg/jscontact`
+## Introduction
-# Repository
+The Groupware component of OpenCloud is implemented as a (micro)service within the OpenCloud framework (see `./services/groupware/`).
-The code lives in the same tree as the other OpenCloud backend services, albeit in the `groupware` branch, that gets rebased on `main` on a regular basis (at least once per week.)
+It is essentially providing a REST API to the OpenCloud UI clients (web, mobile) that is high-level and adapted to the needs of the UIs.
+
+The implementation of that REST API turns those high-level APIs into lower-level [JMAP](https://jmap.io/) API calls to [Stalwart, the JMAP mail server](https://stalw.art/), using our own JMAP client library in `./pkg/jmap/` with a couple of additional RFCs used by JMAP in `./pkg/jscalendar` and `./pkg/jscontact`.
+
+## Repository
+
+The code lives in the same tree as the other OpenCloud backend services, albeit currently in the `groupware` branch, that gets rebased on `main` on a regular basis (at least once per week.)
Use [the `groupware` branch](https://github.com/opencloud-eu/opencloud/tree/groupware)
-
```bash
cd ~/src/opencloud/
OCDIR="$PWD"
@@ -21,6 +24,8 @@ git clone --branch groupware git@github.com:opencloud-eu/opencloud.git
Note that setting the variable `OCDIR` is merely going to help us with keeping the instructions below as generic as possible, it is not an environment variable that is used by OpenCloud.
+### Tools Repository
+
Also, you might want to check out these [helper scripts in opencloud-tools](https://github.com/pbleser-oc/opencloud-tools) somewhere and put that directory into your `PATH`, as it contains scripts to test and build the OpenCloud Groupware:
```bash
@@ -29,24 +34,27 @@ git clone git@github.com:pbleser-oc/opencloud-tools.git ./bin
echo "export PATH=\"\$PATH:$OCDIR/bin\"" >> ~/.bashrc
```
+#### Tools Prerequisites
+
Those scripts have the following prerequisites:
+
* the [`jq`](https://github.com/jqlang/jq) JSON query command-line tool to extract access tokens,
* either the [httpie](https://httpie.io/cli) (`pipx install httpie`) or [`xh`](https://github.com/ducaale/xh) (`cargo install xh --locked`) command-line HTTP clients, just out of convenience as their output is much nicer than curl's
* `curl` as well, to retrieve the access tokens from Keycloak (no need for nice output there)
-# Running
-
-Since we require having a Stalwart container running at the very least, the preferred way of running OpenCloud and its adjacent services for developing the Groupware component is by using the `opencloud_full` Docker Compose setup in `$OCDIR/devtools/deployments/opencloud_full`.
-
## Configuration
-The default hostname domain for the containers is `.opencloud.test`
+Since we require having a Stalwart container running at the very least, the preferred way of running OpenCloud and its adjacent services for developing the Groupware component is by using the `opencloud_full` Docker Compose setup in `$OCDIR/opencloud/devtools/deployments/opencloud_full/`.
+
+This section will explain how to configure that Docker Compose setup for the needs of the Groupware backend.
### Hosts
+The default hostname domain for the containers is `.opencloud.test`
+
Make sure to have the following entries in your `/etc/hosts`:
-```text
+```ruby
127.0.0.1 cloud.opencloud.test
127.0.0.1 keycloak.opencloud.test
127.0.0.1 wopiserver.opencloud.test
@@ -71,9 +79,21 @@ done \
### Compose
-It first needs to be tuned a little, and for that, edit `$OCDIR/opencloud/devtools/deployments/opencloud_full/.env`, making the following changes (make sure to check out [the shell command-line that automates all of that, below](#automate-env-setup)):
+There are two options, either
+
+1. running the Groupware backend with OpenLDAP and Keycloak containers, more akin to a production setup;
+2. running the Groupware backend using the built-in LDAP and OIDC services, for a minimalistic setup that uses less resources and is more likely to be found in a home lab setup.
+
+In either case, the Docker Compose configuration in `$OCDIR/opencloud/devtools/deployments/opencloud_full/` needs to be modified.
+
+#### Production Setup
+
+
+
+Edit `$OCDIR/opencloud/devtools/deployments/opencloud_full/.env`, making the following changes (make sure to check out [the shell command-line that automates all of that, below](#automate-env-setup-prod)):
* change the container image to `opencloudeu/opencloud:dev`:
+
```diff
-OC_DOCKER_IMAGE=opencloudeu/opencloud-rolling
+OC_DOCKER_IMAGE=opencloudeu/opencloud
@@ -82,36 +102,42 @@ It first needs to be tuned a little, and for that, edit `$OCDIR/opencloud/devtoo
```
* add the `groupware` service to `START_ADDITIONAL_SERVICES`:
+
```diff
-START_ADDITIONAL_SERVICES="notifications"
+START_ADDITIONAL_SERVICES="notifications,groupware"
```
* enable the OpenLDAP container:
+
```diff
-#LDAP=:ldap.yml
+LDAP=:ldap.yml
```
* enable the Keycloak container:
+
```diff
-#KEYCLOAK=:keycloak.yml
+KEYCLOAK=:keycloak.yml
```
* enable the Stalwart container:
+
```diff
-#STALWART=:stalwart.yml
+STALWART=:stalwart.yml
```
* optionally disable the Collabora container
+
```diff
-COLLABORA=:collabora.yml
+#COLLABORA=:collabora.yml
```
* optionally disable UI containers
+
```diff
-UNZIP=:web_extensions/unzip.yml
-DRAWIO=:web_extensions/drawio.yml
@@ -125,7 +151,7 @@ It first needs to be tuned a little, and for that, edit `$OCDIR/opencloud/devtoo
+#EXTERNALSITES=:web_extensions/externalsites.yml
```
-
+
All those changes above can be automated with the following script:
```bash
@@ -133,14 +159,122 @@ cd "$OCDIR/opencloud/devtools/deployments/opencloud_full/"
perl -pi -e '
s|^(OC_DOCKER_IMAGE)=.*$|$1=opencloudeu/opencloud|;
s|^(OC_DOCKER_TAG)=.*$|$1=dev|;
- s|^(START_ADDITIONAL_SERVICES=".*)"|$1,groupware"|;
- s|^([A-Z]+=:web_extensions/.*yml)$|#$1|;
- s,^(COLLABORA)=(.+)$,#$1=$2,;
+ s|^(START_ADDITIONAL_SERVICES=".*(?
+
+Edit `$OCDIR/opencloud/devtools/deployments/opencloud_full/.env`, making the following changes (make sure to check out [the shell command-line that automates all of that, below](#automate-env-setup-homelab)):
+
+* change the container image to `opencloudeu/opencloud:dev`:
+
+```diff
+-OC_DOCKER_IMAGE=opencloudeu/opencloud-rolling
++OC_DOCKER_IMAGE=opencloudeu/opencloud
+-OC_DOCKER_TAG=
++OC_DOCKER_TAG=dev
+```
+
+* enable the creation of demo users:
+
+```diff
+-DEMO_USERS=
++DEMO_USERS=true
+```
+
+* add the `groupware` service to `START_ADDITIONAL_SERVICES`:
+
+```diff
+-START_ADDITIONAL_SERVICES="notifications"
++START_ADDITIONAL_SERVICES="notifications,groupware"
+```
+
+* enable the Stalwart container:
+
+```diff
+-#STALWART=:stalwart.yml
++STALWART=:stalwart.yml
+```
+
+* while not required, it is recommended to enable basic authentication support which, while less secure, allows for easier tooling when developing and testing HTTP APIs, by adding `PROXY_ENABLE_BASIC_AUTH=true` somewhere before the last line of the `.env` file:
+
+```diff
+ # Domain of Stalwart
+ # Defaults to "stalwart.opencloud.test"
+ STALWART_DOMAIN=
+
++# Enable basic authentication to facilitate HTTP API testing
++# Do not do this in production.
++PROXY_ENABLE_BASIC_AUTH=true
++
+ ## IMPORTANT ##
+```
+
+* optionally disable the Collabora container
+
+```diff
+-COLLABORA=:collabora.yml
++#COLLABORA=:collabora.yml
+```
+
+* optionally disable UI containers
+
+```diff
+-UNZIP=:web_extensions/unzip.yml
+-DRAWIO=:web_extensions/drawio.yml
+-JSONVIEWER=:web_extensions/jsonviewer.yml
+-PROGRESSBARS=:web_extensions/progressbars.yml
+-EXTERNALSITES=:web_extensions/externalsites.yml
++#UNZIP=:web_extensions/unzip.yml
++#DRAWIO=:web_extensions/drawio.yml
++#JSONVIEWER=:web_extensions/jsonviewer.yml
++#PROGRESSBARS=:web_extensions/progressbars.yml
++#EXTERNALSITES=:web_extensions/externalsites.yml
+```
+
+
+All those changes above can be automated with the following script:
+
+```bash
+cd "$OCDIR/opencloud/devtools/deployments/opencloud_full/"
+perl -pi -e '
+ BEGIN{$basic_auth=0}
+ s|^(OC_DOCKER_IMAGE)=.*$|$1=opencloudeu/opencloud|;
+ s|^(OC_DOCKER_TAG)=.*$|$1=dev|;
+ s|^(START_ADDITIONAL_SERVICES=".*(?Bind DN: `cn=admin,dc=opencloud,dc=eu`
+* Bind Password: `admin`
+* Base DN: `ou=users,dc=opencloud,dc=eu`
+* Host: `localhost`
+* LDAP Port: `389`
+* LDAPS Port: `636`
+
Run the following command on your host (requires the `ldap-tools` package with the `ldapsearch` CLI tool), which should output a list of DNs of demo users:
+
```bash
-ldapsearch -h localhost -D 'cn=admin,dc=opencloud,dc=eu' -x -w 'admin' -b 'ou=users,dc=opencloud,dc=eu' -LLL '(objectClass=person)' dn
+ldapsearch -h localhost -D 'cn=admin,dc=opencloud,dc=eu' \
+-x -w 'admin' -b 'ou=users,dc=opencloud,dc=eu' -LLL \
+'(objectClass=person)' dn
```
Sample output:
-```text
+
+```ldif
dn: uid=alan,ou=users,dc=opencloud,dc=eu
dn: uid=lynn,ou=users,dc=opencloud,dc=eu
@@ -198,20 +353,82 @@ dn: uid=margaret,ou=users,dc=opencloud,dc=eu
```
-### Keycloak
+#### Homelab Setup LDAP
+
+Instead, when using the “homelab” setup (as depicted in section [Homelab Setup](#homelab-setup) above), queries cannot be performed directly from the host \
+but, instead, require spinning up another container in the same Docker network and do so from there.
+
+The necessary LDAP parameters are as follows:
+
+* Bind DN: `uid=libregraph,ou=sysusers,o=libregraph-idm`
+* Bind Password: `admin` (or whichever password is set in the `IDM_REVASVC_PASSWORD` environment variable in `opencloud.yml`)
+* Base DN: `o=libregraph-idm` or ``
+* Host: `localhost`
+* LDAP Port: none, only supports LDAPS
+* LDAPS Port: `9235`
+
+To access the LDAP tree, spawn a new container in the same network, e.g. like this for a Debian 12 container:
-To check whether it works correctly:
```bash
-curl -ks -D- -X POST "https://keycloak.opencloud.test/realms/openCloud/protocol/openid-connect/token" -d username=alan -d password=demo -d grant_type=password -d client_id=groupware -d scope=openid
+docker run --network 'opencloud_full_opencloud-net' --rm \
+--name "debian-${RANDOM}" -ti 'debian:12'
```
-should provide you with a JSON response that contains an `access_token`.
+
+In that container, install the necessary packages to have the LDAP command-line tools:
+
+```bash
+apt-get update -y && apt-get install -y ca-certificates ldap-utils
+```
+
+Run the following command in that container, which should output a list of DNs of demo users:
+
+```bash
+LDAPTLS_REQCERT=never ldapsearch -H ldaps://opencloud:9235 \
+-D 'uid=reva,ou=sysusers,o=libregraph-idm' -x -w 'admin' \
+-b 'o=libregraph-idm' -LLL \
+'(objectClass=person)' dn
+```
+
+Sample output:
+
+```ldif
+dn: uid=admin,ou=users,o=libregraph-idm
+
+dn: uid=alan,ou=users,o=libregraph-idm
+
+dn: uid=lynn,ou=users,o=libregraph-idm
+
+dn: uid=mary,ou=users,o=libregraph-idm
+
+dn: uid=margaret,ou=users,o=libregraph-idm
+
+dn: uid=dennis,ou=users,o=libregraph-idm
+
+```
+
+### Testing Keycloak
+
+> [!NOTE]
+> Only available in the [“production” setup](#prod-setup)
+
+To check whether it works correctly, the following `curl` command:
+
+```bash
+curl -ks -D- -X POST \
+"https://keycloak.opencloud.test/realms/openCloud/protocol/openid-connect/token" \
+-d username=alan -d password=demo -d grant_type=password \
+-d client_id=groupware -d scope=openid
+```
+
+should provide you with a JSON response that contains an `access_token` property.
If it is not set up correctly, it should give you this instead:
+
```json
{"error":"invalid_client","error_description":"Invalid client or Invalid client credentials"}
```
-### Stalwart
+### Testing Stalwart
To then test the IMAP authentication with Stalwart, run the following command on your host (requires the `openssl` CLI tool):
@@ -220,17 +437,20 @@ openssl s_client -crlf -connect localhost:993
```
When then greeted with the following prompt:
-```text
+
+```java
* OK [CAPABILITY ...] Stalwart IMAP4rev2 at your service.
```
enter the following command:
-```text
+
+```bash
A LOGIN alan demo
```
to which one should receive the following response:
-```text
+
+```java
A OK [CAPABILITY IMAP4rev2 ...] Authentication successful
```
@@ -241,17 +461,25 @@ Once a [Stalwart](https://stalw.art/) container is running (using the Docker Com
```bash
cd "$OCDIR/"
git clone git@github.com:opencloud-eu/imap-filler.git
-cd ./imap-filler
-go run . --empty=true --username=alan --password=demo \
---url=localhost:993 --folder=Inbox --senders=3 --count=20
+cd ./imap-filler/
+go run . --username=alan --password=demo \
+ --url=localhost:993 \
+ --empty=true \
+ --folder=Inbox \
+ --senders=6 \
+ --count=50
```
+> [!NOTE]
+> Note that this operation does not use the Groupware APIs or any other OpenCloud backend services either,
+> as it directly communicates with Stalwart via IMAPS on port `993` which is mapped on the host.
+
For more details on the usage of that little helper tool, consult its [`README.md`](https://github.com/opencloud-eu/imap-filler/blob/main/README.md), although it is quite self-explanatory.
> [!NOTE]
> This only needs to be done once, since the emails are stored in a volume used by the Stalwart container.
-# Building
+## Building after Changes
If you run the `opencloud` service as a container, use the following script to update the container image and restart it:
@@ -270,7 +498,7 @@ docker compose up -d opencloud
If you run it from your IDE, there is obviously no need to do that.
-# API Docs
+## API Docs
The REST API documentation is extracted from the source code structure and documentation using [`go-swagger`](https://goswagger.io/go-swagger/), which needs to be installed locally as a prerequisite:
@@ -293,7 +521,7 @@ firefox ./api.html
Note that `redocly-cli` does not need to be installed, it will be pulled locally by the `Makefile`, provided that you have [pnpm](https://pnpm.io/) installed as a pre-requisite, which is already necessary for other OpenCloud components.
-# Testing
+## Testing
This section assumes that you are using the [helper scripts in opencloud-tools](https://github.com/pbleser-oc/opencloud-tools) as instructed above.
@@ -304,12 +532,17 @@ export baseurl=https://localhost:9200
```
The scripts default to using the user `alan` (with the password `demo`), which can be changed by setting the following environment variables:
+
* `username`
* `password`
Your main swiss army knife tool will be `oc-gw` (mnemonic for "OpenCloud Groupware"), which
-* always retrieves an access token from Keycloak, using the credentials defined in the environment variables `username` and `password` (defaulting to `adam`/`demo`), using the "Direct Access Grant" OIDC or "Resource Owner Password Credentials Grant" OAuth2 flow
-* and then use that JWT for Bearer authentication against the OpenCloud Groupware REST API
+
+* checks whether a container named `opencloud_full-opencloud-1` is running locally
+ * if so, whether it has basic auth enabled or not
+ * if yes, uses basic auth directly to authenticate against the OpenCloud Proxy service that ingresses for the OpenCloud Groupware backend, using the credentials defined in the environment variables `username` and `password` (defaulting to `alan`/`demo`)
+ * if not, always retrieves a fresh access token from Keycloak, using the credentials defined in the environment variables `username` and `password` (defaulting to `alan`/`demo`), using the "Direct Access Grant" OIDC API of Keycloak and then use that JWT for Bearer authentication against the OpenCloud Groupware REST API
+ * if no such container is running locally, it assumes that the `opencloud` process is running from within an IDE, with its OpenCloud Proxy service listening on `https://localhost:9200`
It will also save you some typing as whenever you use `//` for the URL, it will replace that by the Groupware REST API base URL, e.g.
@@ -333,10 +566,14 @@ Obviously, you may use whichever HTTP client you are most comfortable with.
Here is how to do it without the `oc-gw` script, using [`curl`](https://curl.se/):
-First, make sure to retrieve a JWT for authentication from Keycloak:
+When using the “production” setup, first make sure to retrieve a JWT for authentication from Keycloak:
```bash
-token=$(curl --silent --insecure --fail -X POST "https://keycloak.opencloud.test/realms/openCloud/protocol/openid-connect/token" -d username="alan" -d password="demo" -d grant_type=password -d client_id="groupware" -d scope=openid | jq -r '.access_token')
+token=$(curl --silent --insecure --fail -X POST \
+"https://keycloak.opencloud.test/realms/openCloud/protocol/openid-connect/token" \
+-d username="alan" -d password="demo" \
+-d grant_type=password -d client_id="groupware" -d scope=openid \
+| jq -r '.access_token')
```
Then use that token to authenticate the Groupware API request:
@@ -345,61 +582,51 @@ Then use that token to authenticate the Groupware API request:
curl --insecure -s -H "Authorization: Bearer ${token}" "https://cloud.opencloud.test/groupware/"
```
+When using the “homelab” setup, authenticate directly using basic auth:
+
+```bash
+curl --insecure -s -u "alan:demo" "https://cloud.opencloud.test/groupware/"
+```
+
> [!TIP]
-> Until everything is documented, the complete list of URI routes can be found in `$OCDIR/opencloud/services/groupware/pkg/groupware/groupware_route.go`
+> Until everything is documented, the complete list of URI routes can be found in \
+[`$OCDIR/opencloud/services/groupware/pkg/groupware/groupware_route.go`](./pkg/groupware/groupware_route.go)
-# Services
+## Services
-## Stalwart
+### Stalwart
-### Web UI
+#### Web UI
To access the Stalwart admin UI, open and use the following credentials to log in:
+
* username: `mailadmin`
* password: `admin`
The usual admin username `admin` had to be changed into `mailadmin` because there is already an `admin` user that ships with the default users in OpenCloud, and Stalwart always checks the LDAP directory before its internal usernames.
Those credentials are configured in `devtools/deployments/opencloud_full/config/stalwart/config.toml`:
+
```ruby
authentication.fallback-admin.secret = "$6$4qPYDVhaUHkKcY7s$bB6qhcukb9oFNYRIvaDZgbwxrMa2RvF5dumCjkBFdX19lSNqrgKltf3aPrFMuQQKkZpK2YNuQ83hB1B3NiWzj."
authentication.fallback-admin.user = "mailadmin"
```
-### Restart from Scratch
+#### Restart from Scratch
To start with a Stalwart container from scratch, removing all the data (including emails):
```bash
cd "$OCDIR/opencloud/devtools/deployments/opencloud_full"
-docker compose stop stalwart
-docker compose rm stalwart
+docker compose rm stalwart --stop
docker volume rm opencloud_full_stalwart-data
docker compose up -d stalwart
```
-### Diagnostics
+#### Diagnostics
If anything goes wrong, the first thing to check is Stalwart's logs, that are configured on the most verbose level (trace) and should thus provide a lot of insight:
```bash
docker logs -f opencloud_full-stalwart-1
```
-
-## OpenLDAP
-
-The `opencloud_full-ldap-server-1` container exports the ports 389 (LDAP) and 636 (LDAPS) on the host.
-
-To access the LDAP tree:
-* Host: `localhost`
-* Port: `389`
-* Bind DN: `cn=admin,dc=opencloud,dc=eu`
-* Password: `admin`
-* Base DN: `dc=opencloud,dc=eu`
-
-As an example, to list all the users, using the `ldap-tools` on your host:
-
-```bash
-ldapsearch -h localhost -D 'cn=admin,dc=opencloud,dc=eu' -x -w 'admin' -b 'ou=users,dc=opencloud,dc=eu' -LLL '(objectClass=person)'
-```
-