Quickly deploy RDS 2016 in Azure
In this post I'll show how to deploy a minimal Windows Server 2016 Remote Desktop Services farm in Azure in 20 minutes using Azure Resource Manager template. Such farm will be enough to provide Desktop-as-a-Service (DaaS) for 5 to 100 end-users. It was designed as a single-tenant solution, then can be quickly deployed in Azure with minimal effort for every customer. My ARM template includes:
- One VM with Active Directory Domain Controller and DNS roles
- One VM with RD Connection Broker and RD Licensing Server (per-user licensing through SPLA)
- One VM with RD Gateway and RD Web
- Specified number of RD Session Hosts.
My ARM template is based on RDS 2016 Base template from GitHub. I recommend you to watch this video from Ignite to understand the details. The resulting farm isn't protected from DC, CB or GW failures, but it is much cheaper then Full-HA deployment with a pair of Connection Brokers with Azure SQL Database, a pair of Gateways with a Load Balancer and a highly available AD environment. If you need an RDS farm for 100+ end-users, I recommend you to modify my template and add high availability for the core components, add Azure Backup capabilities and Azure SMT for centralized management. But I assume that such large RDS farms are rare among CSP partners, and those capabilities can be added manually instead of creating a super-complex ARM template.
Login to the Azure Portal and click "More Services" in the left pane. Choose "Template" menu in the list and then click "Add" to create a new Azure Resource Manager Template.
Specify the template name and description:
Then copy the following text and paste it to the template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"gwdnsLabelPrefix": {
"type": "string",
"metadata": {
"description": "Unique gateway public DNS prefix. The fqdn will look something like 'prefix.region.cloudapp.azure.com'. Up to 62 chars, digits or dashes, lowercase, should start with a letter."
}
},
"adDomainName": {
"type": "string",
"metadata": {
"description": "The name of the AD domain."
},
"defaultValue": "contoso.com"
},
"adminUsername": {
"type": "string",
"metadata": {
"description": "The name of the domain admin. Can't be 'administrator' or 'user'."
},
"defaultValue": "rdsadmin"
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "The password for the administrator account of the new VM and the domain"
}
},
"numberOfRdshInstances": {
"type": "int",
"defaultValue": 1,
"metadata": {
"description": "Initial number of RD Session Hosts"
}
},
"rdshVmSize": {
"type": "string",
"allowedValues": [
"Standard_A2m_V2",
"Standard_A4m_V2",
"Standard_A8m_V2",
"Standard_D11_V2",
"Standard_D12_V2",
"Standard_D13_V2",
"Standard_D14_V2",
"Standard_D15_V2"
],
"metadata": {
"description": "The size of the RD Session Host VMs"
},
"defaultValue": "Standard_D11_V2"
}
},
"variables": {
"adAssetLocation": "https://raw.githubusercontent.com/Azure/AzureStack-QuickStart-Templates/master/ad-non-ha",
"gwpublicIPAddressName": "gwpip",
"imageSKU": "2016-Datacenter",
"adVMSize": "Basic_A1",
"adVnetName": "[concat('ADVNET',resourceGroup().name)]",
"adSubnetName": "[concat('ADStaticSubnet',resourceGroup().name)]",
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks', variables('adVnetName'))]",
"staticSubnetID": "[concat(variables('vnetID'),'/subnets/', variables('adSubnetName'))]",
"adTemplateURL": "[concat(variables('adAssetLocation'),'/adVmTemplate.json')]",
"adStorageName": "[tolower(concat('adsa',uniqueString(resourceGroup().id)))]",
"adVmDeployment": "CreateAdVms",
"adVmDeploymentId": "[concat('Microsoft.Resources/deployments/', variables('adVmDeployment'))]",
"deployPrimaryAdTemplateURL": "[concat(variables('adAssetLocation'),'/deployPrimaryAD.json')]",
"deployPrimaryAd": "DeployPrimaryAd",
"deployPrimaryAdID": "[concat('Microsoft.Resources/deployments/', variables('deployPrimaryAd'))]",
"adPDCVMName": "DC1",
"vnetwithDNSTemplateURL": "[concat(variables('adAssetLocation'),'/vnet-with-dns-server.json')]",
"updateVNetDNS1": "updateVNetDNS",
"updateVNetDNS1ID": "[concat('Microsoft.Resources/deployments/', variables('updateVNetDNS1'))]",
"nicTemplateURL": "[concat(variables('adAssetLocation'),'/nic.json')]",
"publicLBName": "[concat('ADPLB',resourceGroup().name)]",
"publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
"lbFE": "ADLBFE",
"rdpNAT": "ADRDPNAT",
"publiclbID": "[resourceId('Microsoft.Network/loadBalancers',variables('publicLBName'))]",
"publiclbFEConfigID": "[concat(variables('publiclbID'),'/frontendIPConfigurations/',variables('lbFE'))]",
"rdpPort": 3389,
"adRDPNATRuleID": "[concat(variables('publiclbID'),'/inboundNatRules/',variables('rdpNAT'))]",
"adNICName": "[concat('ADNic',resourceGroup().name)]",
"lbBE": "ADLBBE",
"publicBEAddressPoolID": "[concat(variables('publiclbID'),'/backendAddressPools/',variables('lbBE'))]",
"gwLBName": "[concat('GWPLB',resourceGroup().name)]",
"publicIPAddressName": "[tolower(concat('adpip',uniqueString(resourceGroup().Id)))]",
"gwIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('gwpublicIPAddressName'))]",
"gwlbFE": "GWLBFE",
"gwlbID": "[resourceId('Microsoft.Network/loadBalancers',variables('gwLBName'))]",
"gwlbFEConfigID": "[concat(variables('gwlbID'),'/frontendIPConfigurations/',variables('gwlbFE'))]",
"gwlbBE": "GWLBBE",
"gwBEAddressPoolID": "[concat(variables('gwlbID'),'/backendAddressPools/',variables('gwlbBE'))]",
"dnsLabelPrefix": "[tolower(concat('adns', resourceGroup().name))]",
"storageAccountName": "[tolower(concat('rdsa',uniqueString(resourceGroup().id)))]",
"storageAccountType": "Standard_LRS",
"uniqueStorageAccountContainerName": "[tolower(concat('sc', uniqueString(resourceGroup().id)))]",
"imagePublisher": "MicrosoftWindowsServer",
"imageOffer": "WindowsServer",
"vnetAddressRange": "10.0.0.0/16",
"subnetAddressRange": "10.0.0.0/24",
"dnsServerPrivateIp": "10.0.0.4",
"subnet-id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('adVnetName')),'/subnets/', variables('adSubnetName'))]",
"assetLocation": "https://raw.githubusercontent.com/Azure/azure-QuickStart-Templates/master/rds-deployment/",
"nsgName": "RDSNsg",
"nsgID": "[resourceId('Microsoft.Network/networkSecurityGroups',variables('nsgName'))]",
"subnets": [
{
"name": "[variables('adSubnetName')]",
"properties": {
"addressPrefix": "[variables('subnetAddressRange')]",
"networkSecurityGroup": {
"id": "[variables('nsgID')]"
}
}
}
]
},
"resources": [
{
"name": "[variables('nsgName')]",
"type": "Microsoft.Network/networkSecurityGroups",
"location": "[resourceGroup().location]",
"apiVersion": "2015-06-15",
"properties": {
"securityRules": [
{
"name": "rule1",
"properties": {
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "*",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 101,
"direction": "Inbound"
}
}
]
}
},
{
"name": "[variables('adVnetName')]",
"type": "Microsoft.Network/virtualNetworks",
"location": "[resourceGroup().location]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[variables('nsgID')]"
],
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('vnetAddressRange')]"
]
},
"subnets": [
{
"name": "[variables('adSubnetName')]",
"properties": {
"addressPrefix": "[variables('subnetAddressRange')]",
"networkSecurityGroup": {
"id": "[variables('nsgID')]"
}
}
}
]
}
},
{
"name": "[variables('publicIPAddressName')]",
"type": "Microsoft.Network/publicIPAddresses",
"location": "[resourceGroup().location]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[variables('vnetID')]"
],
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[variables('dnsLabelPrefix')]"
}
}
},
{
"name": "[variables('gwpublicIPAddressName')]",
"type": "Microsoft.Network/publicIPAddresses",
"location": "[resourceGroup().location]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[variables('deployPrimaryAdID')]"
],
"properties": {
"publicIPAllocationMethod": "Static",
"dnsSettings": {
"domainNameLabel": "[parameters('gwdnsLabelPrefix')]"
}
}
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/availabilitySets",
"name": "gw-availabilityset",
"location": "[resourceGroup().location]"
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/availabilitySets",
"name": "cb-availabilityset",
"location": "[resourceGroup().location]"
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/availabilitySets",
"name": "rdsh-availabilityset",
"location": "[resourceGroup().location]"
},
{
"name": "[variables('publiclbName')]",
"type": "Microsoft.Network/loadBalancers",
"apiVersion": "2015-06-15",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('publicIPAddressID')]"
],
"properties": {
"frontendIPConfigurations": [
{
"name": "[variables('lbFE')]",
"properties": {
"publicIPAddress": {
"id": "[variables('publicIPAddressID')]"
}
}
}
],
"backendAddressPools": [
{
"name": "[variables('lbBE')]"
}
],
"inboundNatRules": [
{
"name": "[variables('rdpNAT')]",
"properties": {
"frontendIPConfiguration": {
"id": "[variables('publiclbFEConfigID')]"
},
"protocol": "tcp",
"frontendPort": "[variables('rdpPort')]",
"backendPort": 3389,
"enableFloatingIP": false
}
}
]
}
},
{
"name": "[variables('gwlbName')]",
"type": "Microsoft.Network/loadBalancers",
"apiVersion": "2015-06-15",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('gwIPAddressID')]"
],
"properties": {
"frontendIPConfigurations": [
{
"name": "[variables('gwlbFE')]",
"properties": {
"publicIPAddress": {
"id": "[variables('gwIPAddressID')]"
}
}
}
],
"backendAddressPools": [
{
"name": "[variables('gwlbBE')]"
}
],
"loadBalancingRules": [
{
"name": "LBRule01",
"properties": {
"frontendIPConfiguration": {
"id": "[variables('gwlbFEConfigID')]"
},
"backendAddressPool": {
"id": "[variables('gwBEAddressPoolID')]"
},
"protocol": "Tcp",
"frontendPort": 443,
"backendPort": 443,
"enableFloatingIP": false,
"idleTimeoutInMinutes": 5,
"loadDistribution": "SourceIPProtocol",
"probe": {
"id": "[concat(variables('gwlbID'),'/probes/tcpProbe')]"
}
}
},
{
"name": "LBRule02",
"properties": {
"frontendIPConfiguration": {
"id": "[variables('gwlbFEConfigID')]"
},
"backendAddressPool": {
"id": "[variables('gwBEAddressPoolID')]"
},
"protocol": "Udp",
"frontendPort": 3391,
"backendPort": 3391,
"enableFloatingIP": false,
"idleTimeoutInMinutes": 5,
"loadDistribution": "SourceIPProtocol",
"probe": {
"id": "[concat(variables('gwlbID'),'/probes/tcpProbe')]"
}
}
}
],
"probes": [
{
"name": "tcpProbe",
"properties": {
"protocol": "Tcp",
"port": 443,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
},
{
"name": "tcpProbe01",
"properties": {
"protocol": "Tcp",
"port": 3391,
"intervalInSeconds": 5,
"numberOfProbes": 2
}
}
],
"inboundNatRules": [
{
"name": "rdp",
"properties": {
"frontendIPConfiguration": {
"id": "[variables('gwlbFEConfigID')]"
},
"protocol": "tcp",
"frontendPort": 3389,
"backendPort": 3389,
"enableFloatingIP": false
}
}
]
}
},
{
"name": "[variables('adVmDeployment')]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-02-01",
"dependsOn": [
"[variables('publiclbID')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[variables('adTemplateURL')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"adminUsername": {
"value": "[parameters('adminUsername')]"
},
"adminPassword": {
"value": "[parameters('adminPassword')]"
},
"adRDPNATRuleID": {
"value": "[variables('adRDPNATRuleID')]"
},
"storageAccount": {
"value": "[variables('adStorageName')]"
},
"subnetResourceId": {
"value": "[variables('staticSubnetID')]"
},
"primaryAdIpAddress": {
"value": "[variables('dnsServerPrivateIp')]"
},
"storageAccountType": {
"value": "[variables('storageAccountType')]"
},
"vmName": {
"value": "[variables('adPDCVMName')]"
},
"vmSize": {
"value": "[variables('adVMSize')]"
},
"adDNicName": {
"value": "[variables('adNICName')]"
}
}
}
},
{
"name": "[variables('deployPrimaryAd')]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-02-01",
"dependsOn": [
"[variables('adVmDeploymentID')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[variables('deployPrimaryAdTemplateURL')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"primaryADName": {
"value": "[variables('adPDCVMName')]"
},
"domainName": {
"value": "[parameters('adDomainName')]"
},
"adminUsername": {
"value": "[parameters('adminUsername')]"
},
"adminPassword": {
"value": "[parameters('adminPassword')]"
},
"assetLocation": {
"value": "[variables('adAssetLocation')]"
}
}
}
},
{
"name": "[variables('updateVNetDNS1')]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2016-02-01",
"dependsOn": [
"[variables('deployPrimaryAdID')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[variables('vnetwithDNSTemplateURL')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"virtualNetworkName": {
"value": "[variables('adVnetName')]"
},
"virtualNetworkAddressRange": {
"value": "[variables('vnetAddressRange')]"
},
"subnets": {
"value": "[variables('subnets')]"
},
"dnsServerAddress": {
"value": [
"[variables('dnsServerPrivateIp')]"
]
}
}
}
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"location": "[resourceGroup().location]",
"properties": {
"accountType": "[variables('storageAccountType')]"
}
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/networkInterfaces",
"name": "gw-nic",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('gwlbID')]",
"[variables('adVmDeploymentID')]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('subnet-id')]"
},
"loadBalancerBackendAddressPools": [
{
"id": "[variables('gwBEAddressPoolID')]"
}
],
"loadBalancerInboundNatRules": [
{
"id": "[concat(variables('gwlbID'),'/inboundNatRules/rdp')]"
}
]
}
}
],
"dnsSettings": {
"dnsServers": [
"[variables('dnsServerPrivateIp')]"
]
}
}
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/networkInterfaces",
"name": "cb-nic",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('publiclbID')]",
"[variables('adVmDeploymentID')]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('subnet-id')]"
}
}
}
],
"dnsSettings": {
"dnsServers": [
"[variables('dnsServerPrivateIp')]"
]
}
}
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/networkInterfaces",
"name": "[concat('rdsh-', copyindex(), '-nic')]",
"location": "[resourceGroup().location]",
"copy": {
"name": "rdsh-nic-loop",
"count": "[parameters('numberOfRdshInstances')]"
},
"dependsOn": [
"[variables('publiclbID')]",
"[variables('adVmDeploymentID')]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[variables('subnet-id')]"
}
}
}
],
"dnsSettings": {
"dnsServers": [
"[variables('dnsServerPrivateIp')]"
]
}
}
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/virtualMachines",
"name": "GW1",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('deployPrimaryAdID')]",
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"Microsoft.Network/networkInterfaces/gw-nic"
],
"properties": {
"hardwareProfile": {
"vmSize": "Standard_A2"
},
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'gw-availabilityset')]"
},
"osProfile": {
"computerName": "GW1",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[variables('imageSKU')]",
"version": "latest"
},
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','gw-vm-os-disk.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces','gw-nic')]"
}
]
}
},
"resources": [
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "GW1/gateway",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', 'GW1')]"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.11",
"autoUpgradeMinorVersion": true,
"settings": {
"modulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
"configurationFunction": "Configuration.ps1\\Gateway",
"Properties": {
"DomainName": "[parameters('adDomainName')]",
"AdminCreds": {
"UserName": "[parameters('adminUsername')]",
"Password": "PrivateSettingsRef:AdminPassword"
}
}
},
"protectedSettings": {
"Items": {
"AdminPassword": "[parameters('adminPassword')]"
}
}
}
}
]
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/virtualMachines",
"name": "[concat('RDSH', copyindex())]",
"location": "[resourceGroup().location]",
"copy": {
"name": "rdsh-vm-loop",
"count": "[parameters('numberOfRdshInstances')]"
},
"dependsOn": [
"[variables('deployPrimaryAdID')]",
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"[concat('Microsoft.Network/networkInterfaces/', 'rdsh-', copyindex(), '-nic')]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('rdshVmSize')]"
},
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'rdsh-availabilityset')]"
},
"osProfile": {
"computerName": "[concat('RDSH', copyIndex())]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[variables('imageSKU')]",
"version": "latest"
},
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','rdsh-',copyindex(),'-os-disk.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces',concat('rdsh-', copyindex(), '-nic'))]"
}
]
}
},
"resources": [
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat('RDSH', copyindex(),'/sessionhost')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', concat('RDSH', copyindex()))]"
],
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.11",
"autoUpgradeMinorVersion": true,
"settings": {
"ModulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
"ConfigurationFunction": "Configuration.ps1\\SessionHost",
"Properties": {
"DomainName": "[parameters('adDomainName')]",
"AdminCreds": {
"UserName": "[parameters('adminUsername')]",
"Password": "PrivateSettingsRef:AdminPassword"
}
}
},
"protectedSettings": {
"Items": {
"AdminPassword": "[parameters('adminPassword')]"
}
}
}
}
]
},
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Compute/virtualMachines",
"name": "CB1",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('deployPrimaryAdID')]",
"[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
"Microsoft.Network/networkInterfaces/cb-nic",
"rdsh-vm-loop"
],
"properties": {
"hardwareProfile": {
"vmSize": "Standard_A2"
},
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', 'cb-availabilityset')]"
},
"osProfile": {
"computerName": "CB1",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[variables('imageSKU')]",
"version": "latest"
},
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')),providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).primaryEndpoints.blob,variables('uniqueStorageAccountContainerName'),'/','cb-vm-os-disk.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces','cb-nic')]"
}
]
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "CB1/rdsdeployment",
"apiVersion": "2015-06-15",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', 'CB1')]",
"Microsoft.Compute/virtualMachines/GW1/extensions/gateway",
"rdsh-vm-loop"
],
"properties": {
"autoUpgradeMinorVersion": true,
"protectedSettings": {
"Items": {
"adminPassword": "[parameters('adminPassword')]"
}
},
"publisher": "Microsoft.Powershell",
"settings": {
"modulesUrl": "[concat(variables('assetLocation'),'/Configuration.zip')]",
"configurationFunction": "Configuration.ps1\\RDSDeployment",
"Properties": {
"adminCreds": {
"UserName": "[parameters('adminUsername')]",
"Password": "PrivateSettingsRef:adminPassword"
},
"connectionBroker": "[concat('CB1.',parameters('adDomainName'))]",
"domainName": "[parameters('adDomainName')]",
"externalfqdn": "[reference(variables('gwpublicIPAddressName')).dnsSettings.fqdn]",
"numberOfRdshInstances": "[parameters('numberOfRdshInstances')]",
"sessionHostNamingPrefix": "RDSH",
"webAccessServer": "[concat('GW1.',parameters('adDomainName'))]"
}
},
"type": "DSC",
"typeHandlerVersion": "2.11"
}
}
]
}
Then save the template, open it and click "Deploy":
Create a new Resource Group, specify the Region and provide some parameters:
- Unique RD Gateway public DNS prefix
- Active Directory Domain Name
- Domain Admin username and password
- Number of RD Session Hosts and their size. Agree with Terms and Conditions and click "Purchase".
In 20-30 minutes you'll have a ready-to-use RDS 2016 farm, accessible via specified Gwdns Label Prefix + Region URL. In my case it is https://kotlyarenkodaas.northeurope.cloudapp.azure.com/RDWeb.
Manual steps after the deployment:
- Configure SSL certificates
- Create Session Host collections
- Install required applications for end-users
- Configure User Profile Disks
- Optional: Implement auto-scaling of RD Session Hosts
- Optional: Configure backup using Azure Backup.
That's all for today. Have fun with RDS 2016 and ARM!
Comments
- Anonymous
January 09, 2017
The comment has been removed- Anonymous
January 10, 2017
The comment has been removed
- Anonymous
- Anonymous
March 14, 2017
How can I edit this to deploy in my existing AD Domain in azure. So to deploy the rest of the VMs, but join my existing domain.- Anonymous
March 15, 2017
Just remove lines that are responsible for DC creation.- Anonymous
May 24, 2017
How do we specifically know which lines are responsible for DC creation? Im trying to edit the RDS-deployment script to remove the DC creation as well as VNET creation. Many lines reference the variables or have "depends on" dependencies set to the AD variables.- Anonymous
July 13, 2017
Krill, thank you for your hard work on this, this is very helpful.Please clarify how we can use the template to join existing domain, I believe it is more complex than simply removing the DC lines.- Anonymous
July 13, 2017
The comment has been removed
- Anonymous
- Anonymous
October 10, 2017
I too would love to know this - Please provide some help with this Kirill - many thanks
- Anonymous
- Anonymous
- Anonymous
- Anonymous
May 15, 2017
The comment has been removed- Anonymous
May 24, 2017
Yes, you can change the list of possible VMs sized in the JSON file.
- Anonymous
- Anonymous
May 17, 2017
Any clue as to the approximate month-to-month cost of something like this on Azure?- Anonymous
May 24, 2017
It depends on the size of the VMs, type of workload and number of users. The price range is very wide.
- Anonymous
- Anonymous
May 23, 2017
Looks like this is working from the link from GitHub https://github.com/Azure/azure-quickstart-templates/tree/master/rds-deployment - Anonymous
May 31, 2017
What does the end infrastructure look like? I'd like to be able to put it into the cost estimator before I hit go. - Anonymous
August 03, 2017
Hi, do you have mor info about licensing ?Greats - Anonymous
March 01, 2018
Hi Kirill,Nice template and have just used it for setting up a lab \ PoC in our Azure environment. Took the steps to create the SSL and created a Session collection for a remote desktop.Created a couple of test users in the AD and can logon to the rdweb and see the published desktop. However, when I launch the desktop and login, it logs the user in as rsadmin (as per the user in your template) and not the test user?Coming from a mainly citrix background, I have not seen this before.Any thoughts?