(Subcategories required) Advanced Guide: Deploying via Docker (Multi Instance)
This guide explains how to deploy the Nextcloud Exchange Connector in a Multi-instance architecture using Docker.
When should I choose a multi-instance architecture?
A multi-instance setup is highly recommended for large organizations (~1000 users and more). Exchange enforces throttling limits on the number of concurrent connections per identity. By defining multiple instances and multiple service accounts, you can bypass these bottlenecks and multiply your synchronization throughput.
Adding new instances is necessary if the current operating system restricts the number of data processing threads, resulting in a drop in synchronization speed.
Splitting the application into multiple instances allows for an increase in the total number of threads (especially when deploying via Docker).
The architecture depends on your resources: for small servers, a minimal configuration with default parameters is sufficient.
If a large server infrastructure is available, deploying multiple instances proportionally increases user processing speed.
Pre-requirements
Before deploying the application, make sure the following dependencies already exist and are reachable by the connector:
The Nextcloud service account details are available (Configuring Nextcloud)
The Exchange service account or app registration details are configured (Configuring Exchange - TO ADD LINK TO SUBCATEGORIES)
A supported database is available and reachable from the application
Which databases are supported?
PostgreSQL (PostgreSQL official installation guide)
Microsoft SQL Server (Microsoft SQL Server official installation guide)
MariaDB (MariaDB official installation guide)
Docker is installed on your machine (Docker official installation guide)
Step 1. Prepare the Deployment Files
Extract the Sendent deployment files into your installation directory.
You do not need to alter the docker-compose.yml file.
All necessary configurations are managed entirely through environment variables (.env file).
Inside the provided archive, you will find:
The base
docker-compose.yml(which defines the primary instance).An override file named
docker-compose.multiinstances.yml(which defines the secondary replica instances).
The provided configuration will automatically pull the latest official container image from the public repository: rg.nl-ams.scw.cloud/sendent-public/sendent-sync:latest
Step 2. Configure the Environment Variables (.env)
The application requires credentials, connection strings, and scaling rules to communicate with Nextcloud, Exchange, and your database.
Create the .env file by copy-pasting the following code in the same directory as your Docker compose files:
.env File
# Service ConfigurationService__IsPrimary=true# Deployment Types: Docker(0), Binary(1)Service__DeploymentType=0Service__DefaultWorkerName="SendentWorker"Service__BatchLimit=50Service__WorkerIntervalSeconds=60Service__SyncIntervalInSeconds=60Service__CriticalSyncIntervalInSeconds=100Service__BatchSaveSize=100Service__StartWeekend=6# Synchronization Modes: None(0), Calendars(1), Contacts(2)# You can combine modes, just place sum of necessary numbers in this propertyService__SyncMode=1# Synchronization Types: Full(0), Sensitive(1)Service__SyncType=0 # Database Configuration# Allowed Database types: Postgres(0), SqlServer(1), MariaDB(2), MySql(3)DatabaseConfiguration__DatabaseType=2DatabaseConfiguration__DatabaseEncryptionKey=YourSuperSecretKey123!DatabaseConfiguration__ConnectionString=YourDatabaseConnectionString # Postgres Example: Host=postgres_db;Port=5432;Database=SendentDB;Username=postgres;Password=YourStrong!Pass123# SqlServer Example: Server=mssql_db;Database=SendentDB;User Id=sa;Password=YourStrong!Pass123;Encrypt=False;# MariaDB Example: Server=maria_db;Port=3306;Database=SendentDB;Uid=root;Pwd=YourStrong!Pass123# MySql Example: Server=mysql_db;Port=3306;Database=SendentDB;Uid=root;Pwd=YourStrong!Pass123 # Nextcloud ConfigurationService__NextcloudConfiguration__NextcloudBaseUrl=your-nextcloud-base-urlService__NextcloudConfiguration__NextcloudServiceUsername=your-nextcloud-adminService__NextcloudConfiguration__NextcloudServicePassword=your-nextcloud-passwordService__NextcloudConfiguration__SharedSecret=your-shared-secret # Exchange Configuration# Allowed Exchange Types: Cloud(1), OnPremKerberos(2), OnPremBasicAuth(3), OnPremADFS(4)Service__ExchangeConfiguration__ExchangeType=1Service__ExchangeConfiguration__ExchangeOnPremUrl=https://outlook.office365.com/EWS/Exchange.asmxService__ExchangeConfiguration__ExchangeOnPremDomain=your-domainService__ExchangeConfiguration__ExchangeOnPremAdfsAuthorityUrl=your-adfs-authority-urlService__ExchangeConfiguration__ExchangeTenantId=yor-exchange-tenant-id # Exchange Admins Configuration# Default example: simple file admins.json in exchangeAdmins folder# Service__ExchangeConfiguration__ExchangeAdminFile=# Custom path example:# Service__ExchangeConfiguration__ExchangeAdminFile=administrators/myAdmins/myAdmin.json Service__ExchangeConfiguration__ExchangeAdminFile= # Concurrency ConfigurationService__ConcurrencyConfiguration__MaxParallelProcessingUsers=100Service__ConcurrencyConfiguration__MaxUsersPerAdmin=100Secondary_Replicas_Amount=2 # Full Synchronization ConfigurationService__FullSyncConfiguration__ProcessAttachments=true # Sensitive Synchronization ConfigurationService__SensitiveSyncConfiguration__SensitiveTitle="Busy"Service__SensitiveSyncConfiguration__SensitiveCategory="Nextcloud Sync" # Logging (Serilog & Loki)# Change global Log level: Debug, Information, Warning, ErrorSerilog__MinimumLevel__Default=Error#Change Logs output: None(0), Console(1), Database(2), File(4), Grafana(8)# You can combine outputs, just place sum of necessary numbers in this propertyService__LoggingConfiguration__LogsOutput=9Service__LoggingConfiguration__LogDirectoryPath=# For Limiting log's file size in MBService__LoggingConfiguration__LogFileSizeLimit=50# For Limiting amount of log filesService__LoggingConfiguration__LogFileAmountLimit=20Service__LoggingConfiguration__LokiInternalUrl=http://loki:3100 # Grafana ConfigurationGRAFANA_USER="YourAdminLogin"GRAFANA_PASSWORD="YourAdminPassword"
To understand the meaning of each parameter in .env file, refer to the Configuring the .env File.
Warning: Escaping Special Characters in Docker
When configuring passwords, connection strings, or secrets in your .env file, be aware of Docker's character constraints. Specifically, the dollar sign $) is reserved for variable interpolation. If your actual password contains a literal $, you must escape it by doubling the character (e.g., a password of Pa$word must be written as Pa$$word in the .env file).
Failure to escape this will cause Docker to drop the character, resulting in severe authentication errors.
Warning: Shared Secret Mismatch
Your Service__NextcloudConfiguration__SharedSecret value must exactly match the shared secret configured in the Sendent Sync app within your Nextcloud web interface.
Warning: Strict File Naming
The environment file must be named exactly .env with no prefix. Naming the file like settings.env will cause Docker to fail to read the configuration.
Key Settings for Multi-Instance Configuration:
Scaling Replicas: To set how many secondary instances you want, simply define the
Secondary_Replicas_Amountvariable (e.g.,Secondary_Replicas_Amount=2). Docker will automatically deploy one primary instance and the exact amount of secondary instances you specify. You do not need to manually configureService__IsPrimaryfor different containers; the override files handle this.
How many instances do I need?
The optimal number of instances and threads is determined empirically by monitoring logs and application performance.
If events fail to synchronize within a specific interval, the system has hit the thread limit, and adding instances is required.
Each Exchange server has its own limits for simultaneous concurrent actions under different users.
Distribution limits depend on the number of provided administrators.
If the application returns 429 (Too Many Requests), 400, or service busy errors during operation, the Exchange server is overloaded with threads. In this case, it is necessary to decrease the value of the Service__ConcurrencyConfiguration__MaxUsersPerAdmin parameter. If the error persists in a multi-instance architecture, you must add additional administrators or reduce the number of users per admin.
Step 3. Set Up Exchange Credentials (admins.json)
This is an essential step for a Multi-instance setup because you can map multiple administrators to distribute the load and prevent Exchange throttling.
Inside your deployment folder, create a directory named exchangeAdmins and place your admins.json file inside it. Update your .env file to point to this file (e.g., Service__ExchangeConfiguration__ExchangeAdminFile=globalAdmins/admins.json).
Pro Tip for Environments: You can organize multiple JSON files in subfolders (e.g., testAdmins/admins.json or globalAdmins/admins.json). To switch environments, simply update the file path in your .env variable without needing to rebuild or rewrite files.
Warning: Do Not Mix Exchange Types
Do not mix different Exchange connection types (e.g., Cloud and On-Premise) in a single admins.json file. The "ExchangeType" field inside the JSON file acts merely as a visual comment. The actual active connection type is dictated strictly by the Service__ExchangeConfiguration__ExchangeType parameter in your .env file.
Refer to Managing Service Accounts (admins.json) article to know more about managing service accounts.
Step 4. Start the application
The Sendent deployment is modular. You must build your startup command by chaining -f flags depending on which database and monitoring tools you want Docker to host for you.
1. The Base Command (Required for Multi-Instance): docker compose -f docker-compose.yml -f docker-compose.multiinstances.yml
2. Append your Database Container (Optional if using an external DB):
For PostgreSQL:
-f docker-compose.postgres.ymlFor MariaDB:
-f docker-compose.mariadb.ymlFor SQL Server:
-f docker-compose.sqlserver.yml
3. Append Monitoring (Optional):
For Loki & Grafana:
-f docker-compose.grafana.yml
Examples of complete commands:
Running a Multi-Instance cluster with PostgreSQL and Grafana:
docker compose -f docker-compose.yml -f docker-compose.multiinstances.yml -f docker-compose.postgres.yml -f docker-compose.grafana.yml up
Running a Multi-Instance cluster with an external database (no local DB container) and Grafana:
docker compose -f docker-compose.yml -f docker-compose.multiinstances.yml -f docker-compose.grafana.yml up
Step 5. Verify Container Status
To ensure the primary synchronization service, your defined secondary replicas, and your database containers are running without startup crashes.
Run the following command in your terminal:
docker compose ps
You should see exactly one primary instance and the number of secondary instances you specified in your Secondary_Replicas_Amount variable.
Step 6. Monitor application logs
To view real-time console logs, run:
docker compose logs
Note: The docker compose logs command will only display output if Console logging is enabled in your Service__LoggingConfiguration__LogsOutput variable.
For comprehensive instructions on configuring alternative logging methods (such as Grafana or File System), please refer to Logging & Monitoring [TO INSERT THE SUBCATEGORY LINK HERE AFTER FULL DOCUMENTATION APPROVAL].
For handling self-signed certificates in On-Premise Exchange setups, see Advanced: Handling Self-Signed Certificates (On-Premise Exchange) article.
Next Step
Logging & Monitoring [TO INSERT THE SUBCATEGORY LINK HERE AFTER FULL DOCUMENTATION APPROVAL]