Microsoft VM Windows - Backend server installation

Support DQE
Support DQE
  • Updated

1. Installation

This section describes the installation protocol to deploy DQE Unify Server on a Windows Virtual Machine using Docker and Docker Compose. The application stack consists of Redis, RabbitMQ, Nginx, Unify Server, and a Queue Worker, all orchestrated via Docker Compose.

Note: All containers run on a single Docker network on the Windows VM. Inter-container communication uses service names defined in docker-compose.yml (not localhost). Environment variables are set accordingly.

1.1 Prerequisites

1.1.1 Hardware Requirements

Component Minimum Recommended
CPU 4 vCores 8 vCores
RAM 8 GB 16 GB
Disk (OS + Docker) 60 GB SSD 120 GB SSD
Network 100 Mbit/s 1 Gbit/s

1.1.2 Software Requirements

Software Version / Notes
Operating System Windows Server 2019 / 2022 (64-bit)
Docker Engine Latest stable – installed inside WSL2 (Ubuntu)
WSL2 Windows Subsystem for Linux 2 – required to run Linux containers on Windows Server
PowerShell 5.1 or later (included with Windows)
Internet access Required to pull images from DQE Container Registry and Docker Hub

1.2 Install Docker via WSL2

Why WSL2? Docker CE on Windows Server cannot run Linux containers natively (LCOW was removed in Docker 20.10+). WSL2 provides a real Linux kernel on Windows, enabling Docker to run Linux containers seamlessly.

1.2.1 Enable Windows Features

Open PowerShell as Administrator and run each command:

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 proceeding.

1.2.2 Install WSL2 and Ubuntu

After reboot, open PowerShell as Administrator:

  1. Set WSL2 as the default version:

    wsl --set-default-version 2
  2. Install Ubuntu:

    wsl --install -d Ubuntu

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

1.2.3 Install Docker CE inside Ubuntu

Open the Ubuntu WSL2 terminal and run:

  1. Install Docker CE:

    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.

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

    sudo usermod -aG docker $USER
    sudo service docker start
  3. 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

1.2.4 Authenticate to DQE Container Registry

The DQE Unify images are hosted on a private Azure Container Registry. From the Ubuntu WSL2 terminal, use the credentials provided by DQE Software to log in:

docker login <registry-url> --username <Username provided by DQE> --password <Password provided by DQE>

A successful login displays: Login Succeeded

1.3 Prepare the Working Directory

Create a dedicated folder that will hold the Docker Compose file, the Nginx configuration, and the persistent volumes.

# Create the main application directory
New-Item -ItemType Directory -Path "C:\dqe-unify"
New-Item -ItemType Directory -Path "C:\dqe-unify\nginxconf"
New-Item -ItemType Directory -Path "C:\dqe-unify\volumes\redisvol"
New-Item -ItemType Directory -Path "C:\dqe-unify\volumes\rabbitvol"

The directory structure should look as follows:

C:\dqe-unify\
├── docker-compose.yml          ← main orchestration file
├── nginxconf\
│   └── default.conf            ← Nginx reverse-proxy configuration
└── volumes\
    ├── redisvol\               ← Redis persistent data
    └── rabbitvol\              ← RabbitMQ persistent data

Note: Docker Compose mounts these local directories as bind mounts into the containers.

1.4 Configure Nginx

Nginx acts as a reverse proxy, forwarding incoming HTTP/HTTPS requests to the Unify Server container on port 8000.

Run the following command to open the file in Notepad, then paste the configuration below and save:

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

The file C:\dqe-unify\nginxconf\default.conf must contain:

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: In Docker Compose, each service has its own hostname equal to its service name. The proxy target is therefore http://unify-server:8000, not http://localhost:8000.

HTTPS

Add a second server block in default.conf and mount your SSL certificate and private key into the Nginx container. Update docker-compose.yml to expose port 443 and mount the certificate files.

server {
    listen 443 ssl;

    ssl_certificate      /etc/nginx/ssl/cert.crt;
    ssl_certificate_key  /etc/nginx/ssl/cert.key;

    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;
    }
}

1.5 Docker Compose Configuration File

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

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 configuration notes:

  • Services communicate via their service name (e.g. redis, rabbitmq), not via 127.0.0.1.
  • redis-data and rabbitmq-data are Docker named volumes stored in the WSL2 Linux filesystem — this avoids NTFS permission issues.
  • The Nginx config is read from /mnt/c/dqe-unify/nginxconf (the Windows folder accessible via WSL2).
  • Image registry credentials are handled by docker login (see §1.2.4), not embedded in the compose file.

1.6 Deploy the Application

All commands below must be run from the Ubuntu WSL2 terminal.

  1. Step 1 — Start the Docker service and navigate to the application directory:

    sudo service docker start
    cd /mnt/c/dqe-unify
  2. Step 2 — Pull the required images:

    docker compose pull
  3. Step 3 — Start all services in detached mode:

    docker compose up -d
  4. Step 4 — 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 immediately using: docker compose logs <service-name>

1.7 Configure Windows Firewall

Open the required inbound ports on the Windows Firewall so that external clients can reach the application. Run the following commands in PowerShell as Administrator:

New-NetFirewallRule -DisplayName "DQE Unify - HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "DQE Unify - HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow

Note: Port 8000 (Unify Server) and port 5672 (RabbitMQ) do not need to be opened externally — they are only accessed internally via Docker networking.

Dynamics 365 — Authorize inbound IP ranges

The DQE Unify Server receives requests from Microsoft Dynamics 365, which runs on Azure infrastructure. You must authorize the corresponding Azure IP ranges in both the Windows Firewall and the NSG.

The full and up-to-date list of Microsoft Azure IP ranges is available for download at:
https://www.microsoft.com/en-us/download/details.aspx?id=56519

Download the JSON file, identify the Dynamics365 and AzureCloud service tags relevant to your region, and add the corresponding IP ranges as inbound allow rules on port 443.

Azure VM — Network Security Group (NSG)

If the VM is hosted on Azure, you must also add inbound security rules in the associated Network Security Group (NSG):

  1. Go to Azure Portal → Virtual Machines → [Your VM] → Networking.
  2. Click Add inbound port rule.
  3. Set Destination port ranges to 80,443.
  4. Set Protocol to TCP, Action to Allow.
  5. To authorize Dynamics 365 traffic, set Source to Service Tag and select Dynamics365.
  6. Click Add.

1.8 (Optional) Configure IIS as Reverse Proxy

If your organization requires IIS as the entry point (e.g., for certificate management or integration with an existing IIS-based infrastructure), you can configure IIS to forward traffic to Nginx running on port 80. This is an optional step — Nginx alone is sufficient.

1.8.1 Install IIS and ARR

In PowerShell as Administrator:

# Install IIS with management tools
Install-WindowsFeature -Name Web-Server, Web-Mgmt-Tools -IncludeManagementTools

# Install URL Rewrite module (required for reverse proxy)
# Download from: https://www.iis.net/downloads/microsoft/url-rewrite
# Then install Application Request Routing (ARR):
# Download from: https://www.iis.net/downloads/microsoft/application-request-routing

1.8.2 Enable Proxy in ARR

  1. Open IIS Manager.
  2. Click the server node → Application Request Routing Cache.
  3. In the Actions panel, click Server Proxy Settings.
  4. Check Enable proxy and click Apply.

1.8.3 Add a URL Rewrite Rule

Edit C:\inetpub\wwwroot\web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="DQE Unify Proxy" stopProcessing="true">
          <match url="(.*)" />
          <action type="Rewrite"
                  url="http://localhost:80/{R:1}" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

1.9 Setup the DNS

Contact your DNS administrators and ask them to create an A record pointing to the public IP address of the Windows VM.

Record Type Name Value
A unify.yourdomain.com Public IP address of the Windows VM

If the VM is on Azure, you can find its public IP address in Azure Portal → Virtual Machines → [Your VM] → Overview → Public IP address.

1.10 Verify the Deployment

Once DNS propagates, open a browser and navigate to:

http://unify.yourdomain.com

You can also test locally from the VM itself:

# Test Nginx is reachable
curl http://localhost

# Test the Unify Server is reachable
curl http://localhost:8000

If the application responds, the deployment is complete and the server is properly configured.

2. Application Set Up

Once the application is running, the Windows Firewall and any upstream firewall or proxy must be configured to allow the IP ranges listed below.

2.1 IP Addresses to Authorize

DQE Software office server

Contact DQE Software support to obtain the IP address to authorize.

DQE – Deduplication service

Contact DQE Software support to obtain the IP address to authorize.

DQE – Quality service

Contact DQE Software support to obtain the IP address to authorize.

Action required: Have your SI/network team authorize the Windows VM's public IP on DQE Software's side as well. Provide DQE with the outbound public IP of the VM.

Azure IP Ranges (IPv4) — if outbound traffic routes through Azure

4.175.0.0/16, 4.180.0.0/16, 4.210.128.0/17, 4.231.0.0/17, 4.245.0.0/17, 13.69.0.0/17,
13.73.128.0/18, 13.73.224.0/21, 13.80.0.0/15, 13.88.200.0/21, 13.93.0.0/17, 13.94.128.0/17,
13.95.0.0/16, 20.4.0.0/16, 20.8.0.0/16, 20.13.0.0/17, 20.16.0.0/16, 20.23.0.0/16,
20.31.0.0/16, 20.50.0.0/18, 20.50.88.0/21, 20.50.128.0/17, 20.54.128.0/17, 20.56.0.0/16,
20.61.0.0/16, 20.67.0.0/17, 20.71.0.0/16, 20.73.0.0/16, 20.76.0.0/16, 20.82.0.0/17,
20.86.0.0/16, 20.93.128.0/17, 20.101.0.0/16, 20.103.0.0/16, 20.105.128.0/17, 20.107.0.0/17,
20.123.128.0/17, 20.126.0.0/16, 20.160.0.0/16, 20.224.0.0/16, 20.229.0.0/16,
20.234.128.0/17, 20.238.128.0/17, 23.97.128.0/17, 23.98.46.0/24, 23.100.0.0/20,
23.101.64.0/20, 40.67.192.0/19, 40.68.0.0/16, 40.74.0.0/18, 40.91.192.0/18,
40.114.128.0/17, 40.115.0.0/18, 40.118.0.0/17, 51.124.0.0/16, 51.136.0.0/16,
51.137.0.0/17, 51.138.0.0/17, 51.144.0.0/16, 51.145.128.0/17, 52.136.192.0/18,
52.137.0.0/18, 52.142.192.0/18, 52.143.0.0/18, 52.148.192.0/18, 52.149.64.0/18,
52.157.64.0/18, 52.157.128.0/17, 52.166.0.0/16, 52.174.0.0/16, 52.178.0.0/17,
52.232.0.0/17, 52.233.128.0/17, 52.236.128.0/17, 65.52.128.0/19, 98.64.0.0/16,
104.40.128.0/17, 104.45.0.0/18, 104.45.64.0/20, 104.46.32.0/19, 137.116.192.0/19,
137.117.128.0/17, 168.61.56.0/21, 168.63.0.0/19, 172.201.0.0/16, 172.205.128.0/17,
172.211.0.0/16, 191.233.64.0/18, 191.237.232.0/22, 191.239.200.0/22, 213.199.128.0/20

Azure IP Ranges (IPv6) — if outbound traffic routes through Azure

2603:1020:200::/46, 2603:1020:205::/48, 2603:1020:206::/47, 2603:1020:208::/56,
2603:1026:900:7::/64, 2603:1026:900:8::/63, 2603:1026:900:1a::/63, 2603:1026:900:1c::/64,
2603:1026:2405::/48, 2603:1026:2500:24::/64, 2603:1026:3000:140::/59, 2603:1027:1:140::/59,
2a01:111:f403:c201::/64, 2a01:111:f403:ca05::/64, 2a01:111:f403:ca06::/63,
2a01:111:f403:ca08::/63, 2a01:111:f403:d201::/64, 2a01:111:f403:da01::/64,
2a01:111:f403:e201::/64

Related to

Was this article helpful?

0 out of 0 found this helpful