(Answers required) Advanced Guide: Deploying via .NET Binaries (Multi Instance)
This guide explains how to install and deploy the Nextcloud Exchange Connector application using Binary files (.NET 8).
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 ZIP file containing the Nextcloud Exchange Connector release.
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.
How do I know how many instances I need? - to ask Luc to provide answer
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:
# 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), Tasks(4)# 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=Server=localhost;Port=3306;Database=SendentDB;Uid=root;Pwd=YourStrong!Pass123 # 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 # Admin credentials - use a JSON file (recommended) or inline JSON# File path to admin credentials JSON (e.g., /app/settings/admins.json). See Demo files/admins.json.exampleService__ExchangeConfiguration__ExchangeAdminFile=# Inline JSON fallback (used when ExchangeAdminFile is not set)# Cloud Example: "[{\"AppId\":\"AppId1\", \"ClientSecret\":\"Secret1\"}, {\"AppId\":\"AppId2\", \"ClientSecret\":\"Secret2\"}]"# OnPrem(Kerberos/BasicAuth) Example: "[{\"User\":\"Admin1\", \"Pass\":\"Password1\"}, {\"User\":\"Admin2\", \"Pass\":\"Password2\"}]"# OnPremADFS Example: "[{\"ClientId\":\"ClientId1\", \"ClientSecret\":\"Secret1\"}, {\"ClientId\":\"ClientId2\", \"ClientSecret\":\"Secret2\"}]"Service__ExchangeConfiguration__ExchangeAdminRaw="[{}]" # 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: Information, DebugSerilog__MinimumLevel__Default=Information#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=3Service__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: Avoid Raw Exchange Credentials
Do not configure Exchange credentials directly in the .env file via the Service__ExchangeConfiguration__ExchangeAdminRaw parameter.
Escaping quotes and slashes in this string breaks the parser. Always use the admins.json file.
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" }]
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 (e.g., SendentLogs) 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.