(Subcategories required) Advanced Guide: Deploying via Binaries (Multi Instance)
This guide explains how to install and deploy the Nextcloud Exchange Connector application using Binary files.
While Docker is the recommended deployment method for most users, binary installations are specifically supported for advanced use cases, such as air-gapped networks, closed environments, or organizations with strict security policies that prohibit the use of containerization.
Pre-requirements
Before deploying the application, ensure the following dependencies are ready and 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)
The latest version of .NET Runtime 8.0 is installed on your machine (Official .NET 8.0 download page)
For Linux deployments connecting to Exchange On-Premise via Kerberos, ensure the
libgssapi-krb5-2package is installed.
How to install libgssapi-krb5-2?
Use the following command:
sudo apt install libgssapi-krb5-2
You have downloaded the deployment files containing the Nextcloud Exchange Connector release from the official GitHub repository.
Step 1. Verify .NET installation
Run the following command in your terminal to check if .NET 8 is installed:
dotnet --version
The output should show a version starting with 8.0.
Note:
If .NET 8 is not installed, download it from the official website.
Step 2. Extract the application files
Unlike Docker deployments that automatically scale via replicas, a binary application cannot auto-scale itself. To achieve a multi-instance setup, you must physically create independent directories for each instance process.
Extract the downloaded ZIP archive into dedicated folders for each instance you plan to run.
For a multi-instance setup:
/usr/sendent-sync/worker-1//usr/sendent-sync/worker-2//usr/sendent-sync/worker-3/
Note: Use a separate folder for each instance. The number of workers depends on your scaling and throughput needs.
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.
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. Prepare the configuration file (.env)
Why this is needed: The application requires credentials, connection strings, and synchronization rules to communicate with Nextcloud, Exchange, and your database.
Place the environment configuration file directly in the root of each worker's directory.
Warning: Strict File Naming
The environment file must be named exactly “.env” (an empty filename with a .env extension).
Naming the file settings.env will cause the application to fail to read the configuration.
Warning: Shared Secret Mismatch
Your Service__NextcloudConfiguration__SharedSecret value must perfectly match the shared secret configured inside the Sendent Sync app within your Nextcloud web interface.
Below is an example of the .env file tailored for a binary deployment:
.env File
# Service ConfigurationService__IsPrimary=true# Deployment Types: Docker(0), Binary(1)Service__DeploymentType=1Service__AspNetCoreUrl="http://localhost:5001"Service__DefaultWorkerName="SendentWorker-1"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=localhost;Port=5432;Database=SendentDB;Username=postgres;Password=YourStrong!Pass123# SqlServer Example: Server=localhost;Database=SendentDB;User Id=sa;Password=YourStrong!Pass123;Encrypt=False;# MariaDB Example: Server=localhost;Port=3306;Database=SendentDB;Uid=root;Pwd=YourStrong!Pass123# MySql Example: Server=localhost;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=your-exchange-on-prem-urlService__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=1000Service__ConcurrencyConfiguration__MaxUsersPerAdmin=100 # Full Synchronization ConfigurationService__FullSyncConfiguration__ProcessAttachments=true # Sensitive Synchronization ConfigurationService__SensitiveSyncConfiguration__SensitiveTitle="Busy"Service__SensitiveSyncConfiguration__SensitiveCategory="Nextcloud Sync" # Logging (Serilog)# 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=5Service__LoggingConfiguration__LogDirectoryPath=# For Limiting log's file size in MBService__LoggingConfiguration__LogFileSizeLimit=50# For Limiting amount of log filesService__LoggingConfiguration__LogFileAmountLimit=20
To understand the meaning of each parameter in .env refer to Configuring the .env File.
Step 4. Configure binary-specific instance values
Why this is needed: To prevent network port conflicts between running instances and to designate exactly one node as the primary synchronization coordinator.
You must edit the bottom three variables in the .env file for each instance directory. All other settings (database, Exchange, Nextcloud) should remain identical across all your worker folders.
Property | Requirement |
| Exactly one instance (e.g., |
| You must assign a different port for each instance (e.g., |
| Must be a unique identifier per instance (e.g., |
Step 5. Set up Exchange Credentials (admins.json)
Why this is needed: Securely passing credentials to the application. In a multi-instance setup, providing multiple service accounts distributes the synchronization load and prevents Microsoft Exchange from throttling your connections.
Inside each worker directory (or in a shared accessible path), create a folder named exchangeAdmins and place your admins.json file inside it. Ensure your .env file points to this location via the Service__ExchangeConfiguration__ExchangeAdminFile parameter.
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.
An example of the correct admins.json :
[ { "AppId": "your-app-id-1", "ClientSecret": "your-client-secret-1" }, { "AppId": "your-app-id-2", "ClientSecret": "your-client-secret-2" }]
Refer to Managing Service Accounts (admins.json) article to know more about managing service accounts.
Step 6. Start the application
Why this is needed: To execute the synchronization processes for each isolated worker.
Warning: Execution Context
You must open your terminal or command prompt specifically inside the target worker's directory before executing the start command. This ensures the application reads the correct local .env file.
Run the following command in each instance directory separately:
cd /usr/sendent-sync/worker-1/dotnet Sendent.Synchronisation.Service.dll
Repeat this process for /worker-2/, /worker-3/, etc.
Step 7. Configure Logging
Use the Service__LoggingConfiguration__LogsOutput setting to control where logs are written. You can combine values by summing them up (e.g., 1 for Console + 4 for File System = 5).
File System Logging (Recommended for Binaries)
If you set your output to include the file system (4 or 5), the application will automatically generate a dedicated logs folder within the root directory of each worker instance.
You can configure automatic log rotation and cleanup using these parameters:
Service__LoggingConfiguration__LogFileSizeLimit=50: The maximum size of a single log file (in MB) before a new file is created.Service__LoggingConfiguration__LogFileAmountLimit=20: The maximum number of log files retained per instance. Older files are automatically deleted to save disk space.
For comprehensive instructions on configuring alternative logging methods, please refer to Logging & Monitoring [TO INSERT THE SUBCATEGORY LINK HERE AFTER FULL DOCUMENTATION APPROVAL].
Next Step
Logging & Monitoring [TO INSERT THE SUBCATEGORY LINK HERE AFTER FULL DOCUMENTATION APPROVAL]