Salesforce VM Windows - Backend server installation

Support DQE
Support DQE

1. Architecture

The application and all its dependencies are compiled into Docker images.

As soon as the containers are deployed to a Windows Server instance, the application pairs with a Microsoft Dynamics 365 organization that has the DQE Unify package installed.

This document describes the configuration to deploy DQE Unify Server on a Windows Server 2022 virtual machine using Docker Compose running inside WSL2 (Windows Subsystem for Linux 2).

Flow Diagram

The diagram below describes all the inbound/outbound flows as well as the IPs and Ports requested by the application.

Security Measures

We cannot provide an example of how to implement the security layer that would fit perfectly into your architecture. However, we can provide some recommendations that are relevant to the use of the app itself.

  • Protocols and Ports: All outgoing/incoming flows from the application go through the HTTPS protocol (port 443). There is no need to open another port on your VM. The DQE IPs that must be accessible are described in the preceding diagram.
  • IP Filtering: The application server itself only needs to be accessible from Microsoft Dynamics 365 servers. It is therefore recommended to set up a filtering of incoming IPs. See the full list of Azure IP ranges at: https://www.microsoft.com/en-us/download/details.aspx?id=56519
  • Authentication protocol: When configuring the DQE Unify Connected App in your Dynamics 365 organization, you will be able to select the authentication method and configure your application firewall accordingly.

If the VM is directly exposed to the internet, it must have a DNS entry and an associated SSL certificate that point to it.

If the VM is not directly exposed to the internet, it usually means that traffic is routed through a component such as a gateway or load balancer. In this case, the DNS and the SSL certificate must be installed on that gateway, which will then forward the traffic to the internal VM.

Recommendation

In this section, we describe the list of components required to install the DQE Unify Server instance on a Windows Server VM.

Note: Estimates are based on 1 million records. Depending on the volume of the databases processed, it may be necessary to increase the memory capacity of container instances to optimize processing times.

Deployment with Windows Server VM:

  • Server type: Windows Server 2022 (64-bit).
  • Container runtime: Docker CE running inside WSL2 (Ubuntu) — required because Docker CE on Windows Server cannot run Linux containers natively.
  • Load balancer: Not required, but can be used if already available.

Hardware requirements:

ComponentMinimumRecommended
CPU4 vCores8 vCores
RAM8 GB16 GB
Disk60 GB SSD120 GB SSD
Network100 Mbit/s1 Gbit/s

Composition and services

The stack is composed of Docker images orchestrated via Docker Compose. Each service runs as a container. Services communicate with each other via their service name on the internal Docker network.

Web Application (unify-server)

A backend container that contains a microservices application. This application exposes all the APIs called to launch processes, manage processing queues, and instantiate processing workers. It is dependent on Redis and RabbitMQ to function properly. This service is exposed on the web through the Nginx reverse proxy.

Docker Compose settings

  • image: The name of the image hosted on the DQE Azure Container Registry:

    <registry-url>/unify-server-web-ms-dynamics:v3.0
  • depends_on: rabbitmq (healthy), redis (started)
  • environment: REDIS_URL, CLOUDAMQP_URL, PORT
  • command: python app.pyc — the image contains compiled Python bytecode, not source files.

Worker (queue-worker)

A backend container that processes queued jobs asynchronously. It consumes tasks from the RabbitMQ queue and executes them. Uses the same Docker image as the web application.

Parameters to set in Docker Compose

  • image: Same image as the web application service
  • depends_on: rabbitmq (healthy), redis (started)
  • environment: REDIS_URL, CLOUDAMQP_URL
  • command: python queue_worker.pyc

Nginx

A reverse proxy that forwards incoming HTTP/HTTPS requests to the Unify Server on port 8000. Its configuration file is stored on the Windows filesystem (C:\dqe-unify\nginxconf\default.conf) and mounted into the container via WSL2 path (/mnt/c/dqe-unify/nginxconf).

  • image: nginx:latest
  • ports: 80:80, 443:443
  • volume: /mnt/c/dqe-unify/nginxconf:/etc/nginx/conf.d:ro

Redis

A key/value database used to store internal operating keys such as Dynamics 365 org configurations, sessions, etc.

The official redis:alpine image is used. Data is persisted in a Docker named volume stored in the WSL2 Linux filesystem — bind mounts on the Windows NTFS filesystem are not used because they do not support the file permissions required by Redis.

Parameters

  • image: redis:alpine
  • volumes: redis-data:/data (Docker named volume)

RabbitMQ

A queue manager allowing the reception and scheduling of processing requests. Until a process has been assigned to a worker and completed, it is parked in the queue. This also provides resiliency to failures — if the server is restarted, it resumes the last processing in the queue where it left off.

The official rabbitmq:3.13-management image is used. Data is persisted in a Docker named volume. Credentials are set via environment variables.

Parameters

  • image: rabbitmq:3.13-management
  • volumes: rabbitmq-data:/var/lib/rabbitmq (Docker named volume)
  • environment: RABBITMQ_DEFAULT_USER=user, RABBITMQ_DEFAULT_PASS=bitnami

2. Installation

All installation steps are performed on the Windows Server VM. Steps marked [PowerShell] must be run in PowerShell as Administrator. Steps marked [WSL2] must be run in the Ubuntu WSL2 terminal.

2.1 Prerequisite

Connect to the Windows Server VM using one of the available connection options (RDP, Azure Bastion, etc.) and open PowerShell as Administrator.

Create the application directory structure from PowerShell:

New-Item -ItemType Directory -Path "C:\dqe-unify"
New-Item -ItemType Directory -Path "C:\dqe-unify\nginxconf"

WSL2 installation [PowerShell]

Enable the required Windows features:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
Enable-WindowsOptionalFeature -Online -FeatureName Containers -All -NoRestart

/!\ Reboot required — Restart the VM after enabling these features before continuing.

After reboot, open PowerShell as Administrator and install Ubuntu:

wsl --set-default-version 2
wsl --install -d Ubuntu

A terminal opens asking you to create a Unix username and password. Complete the setup before continuing.

Docker & Docker Compose installation [WSL2]

Open the Ubuntu WSL2 terminal and run:

curl -fsSL https://get.docker.com | sudo sh

Note: The script detects WSL and recommends Docker Desktop — ignore the message and wait 20 seconds for the installation to continue automatically. Docker Compose is included in this installation.

Add your user to the docker group and start the service:

sudo usermod -aG docker $USER
sudo service docker start

Close and reopen the WSL2 terminal, then verify:

docker --version
docker compose version

Note: The Docker service must be started manually each time the WSL2 session opens: sudo service docker start

Azure CLI installation [WSL2]

curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Nginx configuration [PowerShell]

Nginx runs as a container — there is no host-level installation. You only need to create the configuration file. Open it in Notepad from PowerShell:

notepad C:\dqe-unify\nginxconf\default.conf

Paste the following content and save:

server {
    listen 80;

    location / {
        proxy_pass         http://unify-server:8000;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_read_timeout 300s;
    }
}

Note: Unlike the ACI version where Nginx targets localhost:8000, in Docker Compose services communicate via their service name — the proxy target is http://unify-server:8000.

For HTTPS, add a second server block:

server {
    listen 443 ssl;
    server_name <your-domain.com>;

    ssl_certificate     /etc/nginx/ssl/cert.crt;
    ssl_certificate_key /etc/nginx/ssl/cert.key;
    ssl_protocols       TLSv1.2 TLSv1.3;

    location / {
        proxy_pass         http://unify-server:8000;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_read_timeout 300s;
    }
}

2.2 Windows Unify Server — docker-compose.yml

Create the file C:\dqe-unify\docker-compose.yml with the content below using Notepad. Replace <registry-url> with the URL provided by DQE Software.

Note: Unlike the ACI version, Docker Compose services communicate via service names (redis, rabbitmq), not via localhost. The environment variables are set accordingly.

services:

  # ── Redis ──────────────────────────────────────────────
  redis:
    image: redis:alpine
    platform: linux/amd64
    restart: always
    volumes:
      - redis-data:/data
    networks:
      - unify-net

  # ── RabbitMQ ───────────────────────────────────────────
  rabbitmq:
    image: rabbitmq:3.13-management
    platform: linux/amd64
    restart: always
    ports:
      - "5672:5672"
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    environment:
      - RABBITMQ_DEFAULT_USER=user
      - RABBITMQ_DEFAULT_PASS=bitnami
    networks:
      - unify-net
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5

  # ── Nginx reverse proxy ────────────────────────────────
  nginx:
    image: nginx:latest
    platform: linux/amd64
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /mnt/c/dqe-unify/nginxconf:/etc/nginx/conf.d:ro
    depends_on:
      - unify-server
    networks:
      - unify-net

  # ── Unify Server (web) ─────────────────────────────────
  unify-server:
    image: <registry-url>/unify-server-web-ms-dynamics:v3.0
    restart: always
    command: ["python", "app.pyc"]
    ports:
      - "8000:8000"
    environment:
      - REDIS_URL=redis://redis:6379
      - CLOUDAMQP_URL=amqp://user:bitnami@rabbitmq:5672/
      - PORT=8000
    depends_on:
      rabbitmq:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - unify-net
    deploy:
      resources:
        limits:
          memory: 1g
          cpus: '0.5'

  # ── Queue Worker ───────────────────────────────────────
  queue-worker:
    image: <registry-url>/unify-server-web-ms-dynamics:v3.0
    restart: always
    command: ["python", "queue_worker.pyc"]
    environment:
      - REDIS_URL=redis://redis:6379
      - CLOUDAMQP_URL=amqp://user:bitnami@rabbitmq:5672/
    depends_on:
      rabbitmq:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - unify-net
    deploy:
      resources:
        limits:
          memory: 5g
          cpus: '1.0'

volumes:
  redis-data:
  rabbitmq-data:

networks:
  unify-net:
    driver: bridge

Key points:

  • redis-data and rabbitmq-data are Docker named volumes stored in the WSL2 Linux filesystem. Bind mounts to the Windows NTFS filesystem are not used because NTFS does not support the chown operations required by these containers.
  • The Nginx config is mounted from /mnt/c/dqe-unify/nginxconf — the Windows folder accessible via WSL2.
  • platform: linux/amd64 is required on all public images to force Docker (running in WSL2 on a Windows host) to pull the Linux version.
  • The entry points are app.pyc and queue_worker.pyc — the DQE image contains compiled Python bytecode, not source .py files.

3. Launcher

The DQE Docker images are provided through an Azure Container Registry managed by DQE Software. All commands in this section are run from the Ubuntu WSL2 terminal.

3.1 Connecting to the DQE Azure Container Registry

Start the Docker service and authenticate to the DQE registry:

sudo service docker start
docker login <registry-url> --username <Login provided by DQE> --password <Pwd provided by DQE>

A successful login displays: Login Succeeded

3.2 Launch of docker-compose.yml

Navigate to the application directory and pull the images:

cd /mnt/c/dqe-unify
docker compose pull

Start all services in detached mode:

docker compose up -d

Verify that all containers are running:

docker compose ps

Expected output — all services should show status running:

NAME                        IMAGE                                                  STATUS
dqe-unify-nginx-1           nginx:latest                                           running
dqe-unify-rabbitmq-1        rabbitmq:3.13-management                               running (healthy)
dqe-unify-redis-1           redis:alpine                                           running
dqe-unify-unify-server-1    <registry-url>/unify-server-web-ms-dynamics:v3.0      running
dqe-unify-queue-worker-1    <registry-url>/unify-server-web-ms-dynamics:v3.0      running

/!\ Important: If any container shows status exited or restarting, check its logs: docker compose logs <service-name>

Related to

Was this article helpful?

0 out of 0 found this helpful