(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:

  1. The Nextcloud service account details are available (Configuring Nextcloud)

  2. The Exchange service account or app registration details are configured (Configuring Exchange - TO ADD LINK TO SUBCATEGORIES)

  3. A supported database is available and reachable from the application

Which databases are supported?
  1. The latest version of .NET Runtime 8.0 is installed on your machine (Official .NET 8.0 download page)

  2. For Linux deployments connecting to Exchange On-Premise via Kerberos, ensure the libgssapi-krb5-2 package is installed.

How to install libgssapi-krb5-2?

Use the following command:

sudo apt install libgssapi-krb5-2
  1. 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:

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 Configuration
Service__IsPrimary=true
# Deployment Types: Docker(0), Binary(1)
Service__DeploymentType=1
Service__AspNetCoreUrl="http://localhost:5001"
Service__DefaultWorkerName="SendentWorker-1"
Service__BatchLimit=50
Service__WorkerIntervalSeconds=60
Service__SyncIntervalInSeconds=60
Service__CriticalSyncIntervalInSeconds=100
Service__BatchSaveSize=100
Service__StartWeekend=6
# Synchronization Modes: None(0), Calendars(1), Contacts(2)
# You can combine modes, just place sum of necessary numbers in this property
Service__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=2
DatabaseConfiguration__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 Configuration
Service__NextcloudConfiguration__NextcloudBaseUrl=your-nextcloud-base-url
Service__NextcloudConfiguration__NextcloudServiceUsername=your-nextcloud-admin
Service__NextcloudConfiguration__NextcloudServicePassword=your-nextcloud-password
Service__NextcloudConfiguration__SharedSecret=your-shared-secret
 
# Exchange Configuration
# Allowed Exchange Types: Cloud(1), OnPremKerberos(2), OnPremBasicAuth(3), OnPremADFS(4)
Service__ExchangeConfiguration__ExchangeType=1
Service__ExchangeConfiguration__ExchangeOnPremUrl=your-exchange-on-prem-url
Service__ExchangeConfiguration__ExchangeOnPremDomain=your-domain
Service__ExchangeConfiguration__ExchangeOnPremAdfsAuthorityUrl=your-adfs-authority-url
Service__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 Configuration
Service__ConcurrencyConfiguration__MaxParallelProcessingUsers=1000
Service__ConcurrencyConfiguration__MaxUsersPerAdmin=100
 
# Full Synchronization Configuration
Service__FullSyncConfiguration__ProcessAttachments=true
 
# Sensitive Synchronization Configuration
Service__SensitiveSyncConfiguration__SensitiveTitle="Busy"
Service__SensitiveSyncConfiguration__SensitiveCategory="Nextcloud Sync"
 
# Logging (Serilog)
# Change global Log level: Debug, Information, Warning, Error
Serilog__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 property
Service__LoggingConfiguration__LogsOutput=5
Service__LoggingConfiguration__LogDirectoryPath=
# For Limiting log's file size in MB
Service__LoggingConfiguration__LogFileSizeLimit=50
# For Limiting amount of log files
Service__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

Service__IsPrimary

Exactly one instance (e.g., worker-1) must be set to true. All other instances must be set to false.

Service__AspNetCoreUrl

You must assign a different port for each instance (e.g., http://localhost:5001, http://localhost:5002).

Service__DefaultWorkerName

Must be a unique identifier per instance (e.g., SendentWorker-1, SendentWorker-2).

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]


Was this article helpful?