Migrating from Legacy
This guide is for system administrators upgrading from the legacy Nextcloud Exchange Connector to the new architecture.
The new architecture represents a complete paradigm shift. The synchronization engine is no longer restricted by Nextcloud's internal cron jobs. It is now a powerful, decoupled microservice.
Because of this architectural upgrade, the way you configure the application has completely changed. You will no longer edit docker-compose.yml or appsettings.json. All settings have been unified into a single .env file, while administrator credentials have been moved to a dedicated admins.json file.
Prerequisites
Before starting the migration process:
Back up your database: Always create a full snapshot or dump of your existing database before performing major upgrades.
Keep your old config files handy: Do not delete your old
docker-compose.ymlorappsettings.jsonyet. You will need to copy the values from them during the mapping phase.
Step 1. Disable Legacy Background Tasks
If the legacy background synchronization tasks and the new worker run simultaneously, they will overwrite each other, causing massive duplication of calendar events and contacts.
You must stop the old synchronization engine from executing. Depending on how your legacy application was configured, you need to remove or disable the specific cron jobs (scheduled tasks) on your Nextcloud server that trigger the old synchronization scripts.
Warning: Absolute Prerequisite
Do not proceed with the installation of a new connector version until you are 100% certain the legacy application is disabled and its background cron jobs are no longer executing.
Step 2. Preserve Your Database
The new application is fully compatible with your existing database. Because the user tokens and synchronization watermarks are preserved in the old tables, migrating your database connection ensures a seamless transition:
No massive "Initial Sync": The system will simply pick up exactly where it left off.
No user re-consent required: Your Nextcloud users do not need to click the "Grant Access" button again. Their existing consent tokens will continue to work flawlessly.
Step 3. Prepare the Deployment Files
Download and extract the ready-to-use deployment files from the official Sendent GitHub repository 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).
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 4. The Configuration Mapping
You must manually translate your old configuration values into the new architecture using the .env file and the admins.json file.
Example: Before and After
To understand the change, here is a simplified example comparing the legacy configuration approach to the new .env file structure.
Before (Legacy docker-compose.yml environment block):
environment: - Service__NextcloudBaseUrl=https://nc01.sendent.dev - Service__NextcloudServiceUsername=admin - Service__MicrosoftTenantId=df6e89a5-... - Service__ExchangeType=1 - ConnectionStrings__DatabaseConnectionString=Host=sendent.synchronisation.db;Port=5432;...
After (New .env file):
Service__NextcloudConfiguration__NextcloudBaseUrl=https://nc01.sendent.devService__NextcloudConfiguration__NextcloudServiceUsername=adminService__ExchangeConfiguration__ExchangeTenantId=df6e89a5-...Service__ExchangeConfiguration__ExchangeType=1DatabaseConfiguration__ConnectionString=Host=sendent.synchronisation.db;Port=5432;...
Step 4.1: General Settings (Move to .env)
Open your new .env file and map your old appsettings.json or docker-compose.yml variables exactly as follows:
Old Variable | New Variable |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note: Obsolete Variables
You can safely ignore variables like Service__OsVersion andService__ApplicationVersion. They have been removed or hardcoded into the new application defaults.
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.
Step 4.2: Administrator Credentials (Move to admins.json)
For security and scalability (to bypass Exchange throttling), direct credentials are no longer stored in the main environment file.
Inside your deployment folder, create a directory named
exchangeAdmins.Create a file named
admins.jsoninside it.Move your old credential variables into this JSON array depending on your Exchange connection type:
For Cloud (Microsoft 365) setups
Move
Service__MicrosoftAppIdto AppIdMove
Service__MicrosoftClientSecretto ClientSecret
Example:
[ { "AppId": "your_old_MicrosoftAppId_value", "ClientSecret": "your_old_MicrosoftClientSecret_value" }]
For On-Premise (Kerberos/BasicAuth) setups
Move
Service__ExchangeOnPremUsernameto UsernameMove
Service__ExchangeOnPremPasswordto Password
Example:
[ { "Username": "your_old_ExchangeOnPremUsername_value", "Password": "your_old_ExchangeOnPremPassword_value" }]
Refer to Managing Service Accounts (admins.json) article to know more about managing service accounts.
Step 4.3: New Configuration Variables
The new architecture introduces several settings that were not present in the legacy appsettings.json or docker-compose.yml configurations. These new parameters provide granular control over scaling, data privacy, and logging.
You can configure these in your new .env file.
Deployment & Instance Settings
Parameter | Meaning & Usage | Example |
| Meaning: Dictates if this instance is the primary synchronization coordinator. Usage: Exactly one instance must be set to |
|
| Meaning: Specifies the hosting method. Usage: Set to |
|
| Meaning: The unique identifier for the instance. Usage: Used in logs and database tracking to identify which worker processed a task. |
|
| Meaning: Selects the database provider. Usage: |
|
Advanced Synchronization Control
Parameter | Meaning & Usage | Example |
| Meaning: Level of detail for synchronization. Usage: Set to |
|
| Meaning: The sleep interval between global application runs. Usage: Determines how often the application checks the database for new users to process. |
|
| Meaning: The retry delay for users whose synchronization failed. Usage: Gives the system time to recover before retrying a broken sync. |
|
| Meaning: Database transaction chunk size. Usage: Maximum number of objects saved to the database in a single transaction. |
|
| Meaning: Allows or disallows processing of attachments. Usage: Applicable only when |
|
| Meaning: Custom title applied to events in Exchange. Usage: Hides meeting details when |
|
| Meaning: Custom category tag applied to events. Usage: Categorizes events originating from Nextcloud in the user's Exchange calendar. |
|
| Meaning: Path to your JSON file containing Exchange service accounts. Usage: Points to the |
|
Concurrency & Scaling
Parameter | Meaning & Usage | Example |
| Meaning: The number of secondary containers to deploy automatically. Usage: Scales your synchronization power (Docker only). |
|
| Meaning: Maximum users processed concurrently by a single Exchange service account. Usage: Prevents Microsoft Exchange from throttling your connections. |
|
Logging Configuration
Parameter | Meaning & Usage | Example |
| Meaning: The global log verbosity level. Usage: Acceptable values are |
|
| Meaning: Determines where logs are stored (Bitwise mask). Usage: |
|
| Meaning: Name of the folder where file logs are saved. Usage: Required if using File Output (value |
|
| Meaning: Maximum size of a single log file. Usage: Expressed in Megabytes (MB). |
|
Step 5. Start the New Worker
Once your .env and admins.json files are fully mapped within your extracted deployment folder (from Step 3), and your legacy background processes are disabled, you can safely start the new worker.
The Sendent deployment is modular. You must build your startup command by appending -f flags depending on which database and monitoring tools you want Docker to host for you.
Build your command by starting with the base file, appending your optional components, and ending with up:
1. The Base Command (Required): docker compose -f docker-compose.yml
2. Append a Database Container (Skip if you're using an external database)
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 with a local PostgreSQL container and Grafana:
docker compose -f docker-compose.yml -f docker-compose.postgres.yml -f docker-compose.grafana.yml up
Running with an external database (no local DB container) and no Grafana:
docker compose -f docker-compose.yml up
The application will automatically connect to your existing database, read the old tokens, and seamlessly resume synchronizing user data.
Step 6. Configure Logging
The logging architecture has been completely redesigned. You will no longer define complex Serilog objects in appsettings.json. Instead, you control logging through bitwise values in the .env file.
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].
Clean-up
After verifying that the new worker is running and synchronization is occurring smoothly via the logs, safely archive or delete your old docker-compose.yml and appsettings.json files to prevent future configuration confusion.