Skip to content

AzureCosmosDB/mongodbmigrationproxy

Repository files navigation

MongoDB migration proxy deployment guide

This guide explains how to deploy an Nginx TCP proxy for MongoDB migrations on Azure by using Bicep templates. The proxy VM must be deployed into the spoke virtual network so that Azure Database Migration Service (DMS) worker nodes can reach a source MongoDB server that is accessible only through a private network (VPN or ExpressRoute).

For more information about private connectivity for MongoDB migrations to Azure DocumentDB, see Private connectivity.

Architecture overview

The following diagram shows the hub-spoke network topology used by the TCP proxy. The proxy VM is deployed into a spoke virtual network that is peered with both the hub (which has connectivity to the source MongoDB server) and the DMS private virtual network. This placement allows DMS worker nodes to connect to the proxy, which forwards traffic to the source MongoDB server on-premises or in another cloud.

Diagram showing the hub-spoke architecture for the MongoDB migration proxy. The source MongoDB connects through VPN or ExpressRoute to a hub virtual network, which peers with a spoke virtual network containing the TCP proxy VM. The spoke peers with the DMS private virtual network, which peers with the target virtual network containing a private endpoint that connects through Private Link to Azure Cosmos DB.

Prerequisites

  1. Azure CLI - Install from Install the Azure CLI.
  2. PowerShell 7+ - Install from Install PowerShell.
  3. Azure subscription - An active Azure subscription.
  4. SSH client - For connecting to the VM (built-in on Windows 10 and later).
  5. Private network connectivity - VPN or ExpressRoute to the target Azure virtual network. The VM has no public IP address.
  6. Spoke virtual network - An existing spoke virtual network peered with both the hub virtual network and the DMS private virtual network. The proxy VM must be deployed into this spoke virtual network.

Get started

1. Configure Azure settings

Edit azure-config.json with your Azure settings:

{
  "subscriptionId": "YOUR_SUBSCRIPTION_ID",
  "resourceGroup": "YOUR_RESOURCE_GROUP_NAME",
  "location": "YOUR_AZURE_REGION",
  "vmName": "YOUR_VM_NAME",
  "vmSize": "YOUR_VM_SIZE",
  "adminUsername": "YOUR_SSH_USERNAME",
  "vmImage": {
    "publisher": "Canonical",
    "offer": "0001-com-ubuntu-server-jammy",
    "sku": "22_04-lts-gen2",
    "version": "latest"
  },
  "networking": {
    "vnetName": "YOUR_VNET_NAME",
    "subnetName": "YOUR_SUBNET_NAME",
    "nsgName": "YOUR_NSG_NAME"
  },
  "proxyPorts": [YOUR_PROXY_PORT1", "YOUR_PROXY_PORT2", "YOUR_PROXY_PORT3]
}

Note: The vmImage and networking sections are required by the deployment script. Do not omit them.

Field descriptions:

Field Description
subscriptionId Your Azure subscription ID. Find it in the Azure portal under Subscriptions, or run az account show --query id -o tsv.
resourceGroup Name of the existing resource group that contains your virtual network and subnet. The VM and other resources are deployed here.
location Azure region to deploy into (see the list that follows).
vmName Name for the Azure VM. Must be unique within the resource group.
vmSize Azure VM SKU (see sizes that follow).
adminUsername SSH login username for the VM.
vmImage Ubuntu image to use. The defaults work as-is. Change them only if you need a different OS version.
networking.vnetName Name of the existing spoke virtual network to deploy the proxy VM into. This must be the spoke virtual network that is peered with the hub and the DMS private virtual network. Must be in the same resource group as resourceGroup. Find it in the Azure portal under Virtual networks, or run az network vnet list -g YOUR_RG --query "[].name" -o tsv.
networking.subnetName Name of the existing subnet within the spoke virtual network. Must be in the same resource group as resourceGroup. Find it under the virtual network's Subnets blade, or run az network vnet subnet list --vnet-name YOUR_VNET -g YOUR_RG --query "[].name" -o tsv.
networking.nsgName Name for the network security group to create. Choose any descriptive name (for example, nsg-mongoproxy).
proxyPorts Array of TCP ports to open on the VM. Must match the listen_port values in proxy-config.json.

Tip: The spoke virtual network and subnet must already exist in the same resource group specified in resourceGroup. The deployment creates only the NSG, NIC, and VM — it doesn't create networking infrastructure. If your spoke virtual network is in a different resource group, move it or update the Bicep template to use a cross-resource-group reference.

Azure VM sizes:

  • Standard_B2s - 2 vCPU, 4 GB RAM (minimal, ~$30/month)
  • Standard_D8s_v3 - 8 vCPU, 32 GB RAM (recommended, ~$280/month)
  • Standard_D8as_v5 - 8 vCPU, 32 GB RAM (recommended, AMD-based, ~$250/month)

Popular Azure regions:

  • eastus - East US
  • westus2 - West US 2
  • centralus - Central US
  • westeurope - West Europe
  • eastasia - East Asia

2. Configure proxy mappings

Edit proxy-config.json to define your MongoDB proxy mappings:

[
  {
    "name": "YOUR_PROXY_NAME",
    "listen_port": YOUR_LISTEN_PORT,
    "target_host": "YOUR_TARGET_HOST",
    "target_port": YOUR_TARGET_PORT,
    "description": "YOUR_DESCRIPTION"
  }
]

Field descriptions:

Field Description
name A unique identifier for this proxy entry. Used internally as the Nginx upstream name (for example, mongodb-primary). Must be unique across all entries.
listen_port The TCP port the proxy VM listens on for incoming connections (for example, 8080). Must also appear in proxyPorts in azure-config.json.
target_host IP address or hostname of the target MongoDB server to forward traffic to.
target_port The port on the target MongoDB server (typically 27017).
description Free-text description for documentation purposes. Not used by the proxy.

Important: Every listen_port in proxy-config.json must have a corresponding entry in the proxyPorts array in azure-config.json. The proxyPorts array controls which ports are opened in the Azure NSG firewall and exposed by Docker. If a listen_port is missing from proxyPorts, the proxy entry will be unreachable from outside the VM.

3. Deploy to Azure

Run the deployment script from the same directory as this guide (all scripts and config files are self-contained here):

.\deploy-azure.ps1

The script performs the following steps:

  1. Validates your Azure sign-in.
  2. Validates that the resource group exists.
  3. Deploys the VM with Docker by using Bicep.
  4. Installs Docker and Docker Compose.
  5. Copies configuration files.
  6. Starts the Nginx proxy.

Deployment takes approximately 5 to 10 minutes.

Deployment options

Full deployment (infrastructure + configuration)

.\deploy-azure.ps1

Deploy infrastructure only

.\deploy-azure.ps1 -DeployOnly

Configure an existing VM

.\deploy-azure.ps1 -ConfigureOnly

Note: All commands assume you are running from the same directory as this guide.

Deployed resources

Azure resources

  • Network Security Group (SSH and proxy ports)
  • Network interface (attached to your existing spoke virtual network and subnet)
  • Ubuntu 22.04 VM
  • Docker and Docker Compose (installed through a VM extension)

Note: The VM is deployed into your existing resource group, spoke virtual network, and subnet with a private IP address only. No public IP address is created. You must have private connectivity (VPN or ExpressRoute) to the spoke virtual network to run the deployment script and manage the VM.

Networking

  • Port 22 - SSH (accessible through the private network)
  • Proxy ports as defined in proxyPorts in azure-config.json (configurable)

Software stack

  • Ubuntu 22.04 LTS
  • Docker Engine
  • Docker Compose V2
  • Nginx (containerized)

Manage the deployment

Connect to the VM with SSH

ssh <USERNAME>@<PROXY_PRIVATE_IP>

View proxy logs

ssh <USERNAME>@<PROXY_PRIVATE_IP>
cd mongoproxy && docker compose logs -f

Update proxy configuration

  1. Edit proxy-config.json locally
  2. If you added or removed ports: Update proxyPorts in azure-config.json to match, then redeploy the Bicep template (deploy-azure.ps1 -DeployOnly) so the NSG firewall rules are updated.
  3. Regenerate nginx.conf:
    .\generate-config.ps1
  4. Copy to VM:
    scp nginx.conf <USERNAME>@<PROXY_PRIVATE_IP>:~/mongoproxy/
  5. Restart proxy:
    ssh <USERNAME>@<PROXY_PRIVATE_IP> 'cd mongoproxy && docker compose restart'

Note: All files (proxy-config.json, generate-config.ps1, nginx.conf) are in the current directory. Run all commands from here.

Stop the proxy

ssh <USERNAME>@<PROXY_PRIVATE_IP> 'cd mongoproxy && docker compose down'

Start the proxy

ssh <USERNAME>@<PROXY_PRIVATE_IP> 'cd mongoproxy && docker compose up -d'

Testing the Deployment

From your local machine:

# Test connection through the proxy using the VM's private IP
# Use the credentials of the TARGET MongoDB server (not the proxy)
mongosh "mongodb://<MONGO_USER>:<MONGO_PASSWORD>@<PROXY_PRIVATE_IP>:<PROXY_PORT>/admin"

From Azure VM:

ssh <USERNAME>@<PROXY_PRIVATE_IP>

# Check if containers are running
docker compose ps

# Test local proxy
curl -v telnet://localhost:<PROXY_PORT>

Cost estimation

Standard_D8s_v3 VM (recommended):

  • VM: ~$280/month
  • Storage (30 GB Premium SSD): ~$5/month
  • Total: ~$285/month

Standard_B2s VM (minimal):

  • VM: ~$30/month
  • Storage (30 GB Premium SSD): ~$5/month
  • Total: ~$35/month

Cleanup

To delete all Azure resources:

az group delete --name rg-mongoproxy --yes --no-wait

Troubleshooting

Docker not starting

ssh <USERNAME>@<PROXY_PRIVATE_IP>
sudo systemctl status docker
sudo systemctl start docker

Nginx container failing

ssh <USERNAME>@<PROXY_PRIVATE_IP>
cd mongoproxy
docker compose logs nginx

Connection refused

  1. Check NSG rules in Azure Portal
  2. Verify proxy ports in azure-config.json
  3. Ensure target MongoDB is accessible from Azure

VM Extension failed

Check extension logs:

az vm extension show \
  --resource-group rg-mongoproxy \
  --vm-name vm-mongoproxy \
  --name installDocker

Security Best Practices

  1. Restrict SSH access - Update NSG to allow SSH only from your private network range
  2. Regular updates - Keep VM and Docker updated

Monitoring

Azure Monitor

Enable VM insights in Azure Portal for:

  • CPU/Memory metrics
  • Network traffic
  • Disk I/O

Container Logs

View in real-time:

ssh <USERNAME>@<PROXY_PRIVATE_IP> 'cd mongoproxy && docker compose logs -f --tail 100'

Support

For issues:

  1. Check Azure deployment logs in Portal
  2. Review VM extension logs
  3. Check docker compose logs
  4. Verify NSG rules and connectivity

About

A a lightweight routing and proxy solution for enabling MongoDB connectivity across isolated hub-and-spoke or peered networks. It helps bridge non-transitive Azure VNet topologies during migrations by securely forwarding database traffic between environments.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors