PowerShell – Create a fully automated RDS Farm (2016) with HA and Gateway in 25 minutes

Im a big fan of Citrix XenApp/XenDesktop but for some small customers (20-30 user) the licensing costs are to high and there is definitely demand for application and desktop virtualization. Thats why I came up with the idea to automate the proccess to install a native Microsoft RDS Farm with High Availability and RDS Gateway to access the published resources when you are located outside the companys network. The complete procedure to create a Multi & HA site takes about 25 minutes in my lab environment.


With the PowerShell script you can create two different builds.

#Build 1  – Multi Server Deployment

  • 2x RDS Session Host
  • 1x RDS Broker
  • 1x RDS WebAccess
  • 1x RDS Gateway
  • 1x RDS Licensing

#Build 2 – HA Server Deployment

  • 2x RDS Session Host
  • 2x RDS Broker
  • 2x RDS WebAccess
  • 2x RDS Gateway
  • 1x RDS Licensing

Network Diagram


Firewall Configuration





RDS Gateway

Domain Controller



RDS Gateway

Domain Controller



RDS Gateway

Domain Controller

TCP 135


RDS Gateway

Domain Controller

TCP 88


RDS Gateway

Sesssion Host

TCP/UDP 3389



RDS Gateway

TCP 443



RDS Gateway

UDP 3391


If you need a more detailed port usage please check this technet article.

How is it working?

You just need to download the script package and copy the stuff to “C:\rds”. This is necessary because the path to the configuration file is hardcoded in the script and some additonal files will be downloaded during the deployment.


Here is a config file to create a #Build2 environment.

Important: The config file is based on json. For a “\” you always need to put “\\” for not breaking the syntax!

	MultiDeployment: "Yes",
	HADeployment: "Yes",
	ConnectionBroker01: "RDSBroker001.lab.local",
	ConnectionBroker02: "RDSBroker002.lab.local",
	WebAccessServer01: "RDSWebAccess001.lab.local",
	WebAccessServer02: "RDSWebAccess002.lab.local",
	RDGatewayServer01: "RDSGateway001.lab.local",
	RDGatewayServer02: "RDSGateway002.lab.local",
	RDSHost01: "RDSHost001.lab.local",
	RDSHost02: "RDSHost002.lab.local",
	LICserver: "RDSLic001.lab.local",
	LICmode: "PerUser",
	DomainController: "DC001.lab.local",
	DesktopCollectionName: "RDS Lab",
	DesktopDiscription: "Test Deployment with PowerShell",
	ProfileDiskPath: "\\\\DC001\\RDSFarm1$",
	RDSAccessGroup: "SG_RDP_Internal_Access@lab.local",
	GatewayAccessGroup: "SG_RDP_External_Access@lab.local",
	CertPath: "C:\\rds\\Wildcard_Flashmob.pfx",
	CertPassword: "Password",
	GatewayExternalFqdn: "gateway.flashmob-saulgau.de",
	RDBrokerDNSInternalName: "rdsbroker",
	RDBrokerDNSInternalZone: "flashmob-saulgau.de",
	RDWebAccessDNSInternalName: "remoteaccess",
	RDWebAccessDNSInternalZone: "flashmob-<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;"></span>saulgau.de",
	SQLServer: "DB001.lab.local",
	SQLDatabase: "RDSFarm1",
        DomainNetbios: "LAB"

What do I need to know before running the script?

  1. A Wildcard SSL certificate from a 3rd Party PKI is irreplaceable. You also can implement certificates from your enterprise PKI but this can come to unaesthetic warn messages for the users when accessing the infrastructure outside the LAN because the certification revocation list is not reachable.
  2.  The user which is running the script needs to have the right to create DNS Records and Security Groups in Active Directory. If the RSAT Tools are missing they will be installed by the script.
  3. Determine the FQDNs you want to use: Broker, Gateway, WebAcces (The script will generate Split DNS records. My internal domain is “lab.local” and the wildcard certificate is issued for “*.flashmob-saulgau.de)
  4. Create an UNC-Share for the ProfileDisk. You only need to set “Read” access for “Everyone”. Everything else will be handled by the broker machines.
  5. Fill out the configuration file and rename it to “config.json”.
  6. Run the Script (Install_RDSFarm.ps1) as administrator.

HA Broker and SQL Database

Update (2018-02-17)

The script will create the SQL Login for the RDS Broker Security Group. The user running the script just needs sysadmin rights on the database server. Thanks to Sander van Gelderen for contributing the modifications.

When deploying #Build2 you need to interact during the script execution.  To create the database for the HA Broker  the computer accounts needs to have the permission to create a database on the SQL server.  The problem is that the command “Set-RDConnectionBrokerHighAvailability” will always create a new database. You can’t set the permission on an empty “RDSFarm1” database before running the script. You need to give the SecurityGroup “RDS_Connection_Brokers” temporary  the role “sysadmin” to complete the setup. Afterwards you should change the permission to “db_owner”. The script will instruct you to do this.

Load Balancing

This setup is based on DNS Round Robin. Its always better to use a hardware/software load balancer to check if the service is running properly. If you guys are interested how to load balance the components with Microsoft Network Load Balancing (NLB) and Citrix NetScaler drop me a message and I will write a blogpost about this.

How can I access the RDSFarm?

Method 1 – Native RDP Client
Connect to the RDSBroker FQDN and configure Gateway settings.




Method 2 – WebAccess (Browser)
Browse to the configured RemoteAccess FQDN. After succesfull login you can access your Desktop or Remote Apps.



Method 3 – WebAccess with URL or E-Mail
This will create shortcuts in the Windows Startmenu. Its also possible to set the connection URL via Group Policy. ( User –> Windows Components\Remote Desktop Services\RemoteApp and Desktop Connections –> “Specify default connection URL”)





16 thoughts on “PowerShell – Create a fully automated RDS Farm (2016) with HA and Gateway in 25 minutes

Add yours

  1. great script, made some adjustments. But I have something stange… adding the seconds brokers gives me a error: Add-RDServer : The server BR2.rdsfarm.lab has to be same OS version as the active RD Connection Broker server BR1.rdsfarm.lab: Microsoft Windows Server 2016 Standard.

    And I know the versions are the same! do you know what to do?


      1. Julian, yes patch level is the same, my images are syspreped vhdx files. But I think I know what the error means, I will do some tests somewhere next week and let you know.


      2. Julian,

        Found the solution for the issue about ” Add-RDServer : The server BR2.rdsfarm.lab has to be same OS version as the active RD Connection Broker server BR1.rdsfarm.lab: Microsoft Windows Server 2016 Standard. ” Do you mind if I write about that and refer to your blog?
        I also want to do a pull request on github. I automated you’re manual actions (sorry :-D)

        Liked by 1 person

  2. If I want to remove the 2nd connection Broker and use Build 1 do I need to do any modifications to the powershell script. I tried removing the lines for the 2nd Connection Broker and the script now throws tons of errors.


    1. Build 1 is only using one broker. You don’t need to modify the script. Just put your environment parameters in the configuration file. If it’s still not working send me the errors.


  3. Really great work, however I did made some modifications to the script. 1. SQL database connection & logging on prechecks, 2. HA mode automatic UserProfiles folder creation (in my case to fileserver cluster). I’m still receiving a few errors (I have run script just once). I can’t create RDS:\GatewayServer\GatewayManagedComputerGroups\RDSFarm1 because I don’t have sufficient permissions? Then #Configure RDSBrokerHighAvailability fails, I guess because logging on to SQL Database failed earlier (HA mode is not available). Now I have working SQL database and I’ll re-run script. But that RDSFarm1 error remains mystery still.


      1. Yes. I tried also manually. And I also ran the script second time but no luck. This is the part that fails: New-Item -Path “RDS:\GatewayServer\GatewayManagedComputerGroups” -Name “RDSFarm1” -Description “RDSFarm1” -Computers “$RDBrokerDNSInternalName.$RDBrokerDNSInternalZone” -ItemType “String”. For the first run VM’s were fresh Azure Server 2016 VM’s. For the record I’m trying to put RD Gateway and RD Web Access roles into same VM. Two VM’s of course because I’m trying to create HA RDS setup.


  4. Yes. If you mean ADUC. I changed script quite a lot now, pre-checks mostly. Config file: https://pastebin.com/9b0A9iAE, Script: https://pastebin.com/prG64ptT. Text from Powershell window: https://pastebin.com/CesdDCCv.
    I created 2x CB, 2 GW/WA, 2 SH, 1 DC, 1 SQL. CB works as license server. I can see 1 CB, 2 SH’s and 1 GW/WA from deployment overview. Calculator opened just fine. DNSRR looks good. There is RDS_Connection_Brokers group on SQL DB with sysadmin permissions. Both CB’s are on that group. That group doesn’t have permissions on „Broker“ database, which should be db for CB HA.
    On that text file there is a mention: „Set-RDConnectionBrokerHighAvailability : A deployment is not present.“ I guess that’s why CB HA doesn’t work. There could be some check…
    Don’t know why GW/WA is not installed correctly, IIS and tools related to IIS are not installed on GW2.
    Hopefully I can rollback with these Hyper-V checkpoints… because I wouldn’t want to install all the servers again. 🙂


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: