[Yandex Cloud documentation](../../index.md) > [Yandex Compute Cloud](../index.md) > [Tutorials](index.md) > Microsoft products in Yandex Cloud > Deploying Remote Desktop Services

# Deploying Microsoft Remote Desktop Services


{% note warning %}

In Yandex Cloud, you can only use Microsoft products with your own licenses and on dedicated hosts. For more information, see [Using personal licenses for Microsoft products](../../microsoft/byol.md).

{% endnote %}



In this tutorial, we will deploy a Yandex Cloud Microsoft Windows Server Datacenter consisting of a single server with pre-installed Active Directory and Remote Desktop Services. Images are available with preset quotas for 5, 10, 25, 50, and 100 users. Select the version with the necessary quota. All examples are given for a server with a quota for five users.

{% note warning %}

To increase the quota, you will need to re-create the VM.

{% endnote %}

To deploy the Remote Desktop Services infrastructure:

1. [Get your cloud ready](#before-you-begin).
1. [Create a cloud network and subnets](#create-network).
1. [Create an administrator account management script](#admin-script).
1. [Create a Remote Desktop Services VM](#add-vm).
1. [Install and configure Active Directory](#install-ad).
1. [Set up firewall rules](#firewall).
1. [Set up a domain license server](#license-server).
1. [Set up the Remote Desktop Session Host role](#rdsh).
1. [Create users](#create-users).

If you no longer need the resources you created, [delete them](#clear-out).

## Get your cloud ready {#before-you-begin}

Sign up for Yandex Cloud and create a [billing account](../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../billing/quickstart/index.md) and [link](../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../resource-manager/concepts/resources-hierarchy.md).

{% note info %}

Make sure that the billing account contains user details [required to meet the Microsoft licensing policy requirements](../../microsoft/check-user-data.md). You can launch the product only if you have these details.

{% endnote %}

### Required paid resources {#paid-resources}

The cost of Microsoft Windows Server with Remote Desktop Services infrastructure includes:

* Fee for continuously running virtual machines (see [Yandex Compute Cloud pricing](../pricing.md)).
* Fee for dynamic or static public IP addresses (see [Yandex Virtual Private Cloud pricing](../../vpc/pricing.md)).
* Fee for Yandex Cloud outbound internet traffic (see [Yandex Compute Cloud pricing](../pricing.md)).

## Create a cloud network and subnets {#create-network}

Create a cloud network named `my-network` with subnets in all availability zones that will host your VMs.

1. Create a cloud network:

   {% list tabs group=instructions %}

   - Management console {#console}

     To create a [cloud network](../../vpc/concepts/network.md):
     1. In the [management console](https://console.yandex.cloud), select a folder where you want to create your cloud network.
     1. Navigate to **Virtual Private Cloud**.
     1. Click **Create network**.
     1. Specify `my-network` as the network name.
     1. Click **Create network**.

   - CLI {#cli}

     If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).
  
     The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions. 

     To create a cloud network, run this command:

     ```
     yc vpc network create --name my-network
     ```

   - API {#api}

     Use the [create](../../vpc/api-ref/Network/create.md) REST API method for the [Network](../../vpc/api-ref/Network/index.md) resource or the [NetworkService/Create](../../vpc/api-ref/grpc/Network/create.md) gRPC API call.

   {% endlist %}

2. Create a subnet in `my-network`:

   {% list tabs group=instructions %}

     - Management console {#console}

       To create a subnet:
       1. Open the **Virtual Private Cloud** section in the folder where you want to create a subnet.
       1. Click the name of your cloud network.
       1. Click **Add subnet**.
       1. Specify `my-subnet-d` as the name and select the `ru-central1-d` availability zone from the drop-down list.
       1. Enter the subnet CIDR: IP address and subnet mask `10.1.0.0/16`. For more information about IP address ranges, see [Cloud networks and subnets](../../vpc/concepts/network.md).
       1. Click **Create subnet**.

     - CLI {#cli}

       To create a subnet, run this command:

       ```
       yc vpc subnet create \
         --name my-subnet-d \
         --zone ru-central1-d \
         --network-name my-network \
         --range 10.1.0.0/16
       ```
     
     - API {#api}

       Use the [create](../../vpc/api-ref/Subnet/create.md) REST API method for the [Subnet](../../vpc/api-ref/Subnet/index.md) resource or the [SubnetService/Create](../../vpc/api-ref/grpc/Subnet/create.md) gRPC API call.

   {% endlist %}


## Create an administrator account management script {#admin-script}

If you are going to create your VM via the CLI, create the `setpass` file with a script that will set the administrator password:

{% list tabs group=programming_language %}

- PowerShell {#powershell}

    ```
    #ps1
    Get-LocalUser | Where-Object SID -like *-500 | Set-LocalUser -Password (ConvertTo-SecureString "<your_password>" -AsPlainText -Force)
    ```
{% endlist %}

The password must meet the [complexity requirements](https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/password-must-meet-complexity-requirements#справочные-материалы).

To learn about the best practices for securing Active Directory, see [this MS guide](https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory).

## Create a Windows Server Remote Desktop Services VM {#add-vm}

Create a virtual machine for Windows Server with Remote Desktop Services. This VM will have internet access.

{% list tabs group=instructions %}

- Management console {#console}

  1. On the folder dashboard in the [management console](https://console.yandex.cloud), click **Create resource** and select `Virtual machine instance`.
  1. Under **Boot disk image**, type `RDS` in the **Product search** field and select the appropriate [RDS](https://yandex.cloud/en/marketplace?tab=software&search=windows+rds) image: 
  1. Under **Location**, select the `ru-central1-d` [availability zone](../../overview/concepts/geo-scope.md).
  1. Under **Disks and file storages**, specify your boot [disk](../concepts/disk.md) size: `50 GB`.
  1. Under **Computing resources**, switch to the `Custom` tab and specify the [platform](../concepts/vm-platforms.md), number of vCPUs, and amount of RAM:

      * **Platform**: `Intel Ice Lake`.
      * **vCPU**: `4`.
      * **Guaranteed vCPU performance**: `100%`.
      * **RAM**: `8 GB`.
  1. Under **Network settings**, specify:

      * **Subnet**: `my-network` and `my-subnet-d`.
      * **Public IP address**: `Auto`.
  1. Under **General information**, specify the VM name: `my-rds-vm`.
  1. Click **Create VM**.

  Wait for the VM status to change to `Running` and reset the password:
  
  1. Select the VM.
  1. Click **Reset password**.
  1. Specify the **Username** to reset the password for. If there is no user with that name on the VM, this user will be created with administrator access.
  1. Click **Generate password**.
  1. Save the **New password**. It will become unavailable once you close the window.

- CLI {#cli}

  ```
   yc compute instance create \
     --name my-rds-vm \
     --hostname my-rds-vm \
     --memory 8 \
     --cores 4 \
     --zone ru-central1-d \
     --network-interface subnet-name=my-subnet-d,ipv4-address=10.1.0.3,nat-ip-version=ipv4 \
     --create-boot-disk image-folder-id=standard-images,image-family=windows-2022-dc-gvlk-rds-5 \
     --metadata-from-file user-data=setpass
  ```

  {% note info %}
  
  The commands [`yc compute instance create`](../../cli/cli-ref/compute/cli-ref/instance/create.md) | [`create-with-container`](../../cli/cli-ref/compute/cli-ref/instance/create-with-container.md) | [`update`](../../cli/cli-ref/compute/cli-ref/instance/update.md) | [`add-metadata`](../../cli/cli-ref/compute/cli-ref/instance/add-metadata.md) support substitution of environment variable values into VM metadata. When you execute a Yandex Cloud CLI command, these values, specified in the `user-data` key in `$<variable_name>` format, will be substituted into the VM metadata from the environment variables of the environment the command is executed in. 
  
  To change such behavior, i.e. to provide a variable name to the VM metadata in `$<variable_name>` format rather than take the variable value from the CLI command runtime environment, use the two-dollar syntax, e.g., `$$<variable_name>`.
  
  For more information, see [Specifics of providing environment variables in metadata via the CLI](../concepts/metadata/sending-metadata.md#environment-variables).
  
  {% endnote %}

- API {#api}

  Use the [create](../api-ref/Instance/create.md) REST API method for the [Instance](../api-ref/Instance/index.md) resource or the [InstanceService/Create](../api-ref/grpc/Instance/create.md) gRPC API call.

{% endlist %}

## Install and configure Active Directory {#install-ad}

1. Restart `my-rds-vm`:

   {% list tabs group=instructions %}
   
   - Management console {#console}

     1. In the [management console](https://console.yandex.cloud), select the folder where you want to create your preemptible VM.
     1. Navigate to **Compute Cloud**.
     1. Select the `my-rds-vm` VM.
     1. Click ![image](../../_assets/console-icons/ellipsis.svg) and select **Restart**.
   
   - CLI {#cli}
   
     ```
     yc compute instance restart my-rds-vm
     ```
   
   - API {#api}
   
     Use the [restart](../api-ref/Instance/restart.md) REST API method for the [Instance](../api-ref/Instance/index.md) resource or the [InstanceService/Restart](../api-ref/grpc/Instance/restart.md) gRPC API call.
   
   {% endlist %}

1. Connect to `my-rds-vm` via [RDP](../operations/vm-connect/rdp.md). Use the `Administrator` username and your password.
1. Assign Active Directory roles:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
        Restart-Computer -Force
        ```
      
    {% endlist %}

1. Create an Active Directory forest:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        Install-ADDSForest -DomainName 'yantoso.net' -Force:$true
        ```
      
    {% endlist %}

   Windows will restart automatically. Reconnect to `my-rds-vm`. Use the `yantoso\Administrator` username and your password. Restart PowerShell.

## Set up firewall rules {#firewall}

1. Add firewall rules protecting Active Directory from external network requests:
    
    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        Set-NetFirewallRule `
          -DisplayName 'Active Directory Domain Controller - LDAP (UDP-In)' `
          -RemoteAddress:Intranet
        
        Set-NetFirewallRule `
          -DisplayName 'Active Directory Domain Controller - LDAP (TCP-In)' `
          -RemoteAddress:Intranet
        
        Set-NetFirewallRule `
          -DisplayName 'Active Directory Domain Controller - Secure LDAP (TCP-In)' `
          -RemoteAddress:Intranet
        ```
      
    {% endlist %}

## Set up a domain license server {#license-server}

1. Add the `Network Service` user to the `Terminal Server License Servers` Active Directory group:
    
    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        net localgroup "Terminal Server License Servers" /Add 'Network Service'
        ```
      
    {% endlist %}
   
1. Set the licensing type.
    
    {% note info %}
    
    You can only use `User CAL` licenses.
    
    {% endnote %}

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        New-ItemProperty `
        -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' `
        -Name 'LicensingMode' `
        -Value 4 `
        -PropertyType 'DWord'
        ```
      
    {% endlist %}
    
1. Specify the RDS licensing service:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        New-ItemProperty `
        -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' `
        -Name 'LicenseServers' `
        -Value 'localhost' `
        -PropertyType 'String'
        ```
      
    {% endlist %}

1. Optionally, limit the number of concurrent server sessions:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}
        
      ```powershell
      New-ItemProperty `
      -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' `
      -Name 'MaxInstanceCount' `
      -Value 5 `
      -PropertyType 'DWord'
      ```
   
    {% endlist %}

## Set up the Remote Desktop Session Host role {#rdsh}

Install the `Remote Desktop Session Host` role on the server:

{% list tabs group=programming_language %}

- PowerShell {#powershell}

    ```powershell
    Install-WindowsFeature RDS-RD-Server -IncludeManagementTools
    Restart-Computer -Force
    ```

{% endlist %}


## Add your license server to the Active Directory security group and register it as SCP {#ad-sg-scp}

Add your license server to the `Terminal Server License Servers group` Active Directory group and register it as the license service connection point (SCP):

{% list tabs group=operating_system %}

- Windows Server {#windows}

  1. Click **Start**.
  1. In the search field, type `Remote Desktop Licensing Manager` and press `Enter` to open the manager.
  1. Right-click your license server in the list and select **Review Configuration...**.
  1. You will see the warning that your license server is not a member of the `Terminal Server License Servers` group and is not registered as a service connection point (SCP). Click **Add to Group** and then click **Continue**.
  1. Click **Register as SCP**.
  1. Click **OK**.
  1. Restart the VM.

{% endlist %}


## Create users {#create-users}

1. Create test users:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}
    
        ```powershell
        New-ADUser `
          -Name ru1 `
          -PasswordNeverExpires $true `
          -Enabled $true `
          -AccountPassword ("P@ssw0rd!1" | ConvertTo-SecureString -AsPlainText -Force )
        New-ADUser `
          -Name ru2 `
          -PasswordNeverExpires $true `
          -Enabled $true `
          -AccountPassword ("P@ssw0rd!1" | ConvertTo-SecureString -AsPlainText -Force )
        New-ADUser `
          -Name ru3 `
          -PasswordNeverExpires $true `
          -Enabled $true `
          -AccountPassword ("P@ssw0rd!1" | ConvertTo-SecureString -AsPlainText -Force )
        New-ADUser `
          -Name ru4 `
          -PasswordNeverExpires $true `
          -Enabled $true `
          -AccountPassword ("P@ssw0rd!1" | ConvertTo-SecureString -AsPlainText -Force )
        New-ADUser `
          -Name ru5 `
          -PasswordNeverExpires $true `
          -Enabled $true `
          -AccountPassword ("P@ssw0rd!1" | ConvertTo-SecureString -AsPlainText -Force )
        ```
      
    {% endlist %}

1. Grant `Remote Desktop Users` permissions to the new users:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}

        ```powershell
        Add-ADGroupMember -Members 'ru1' -Identity 'Remote Desktop Users'
        Add-ADGroupMember -Members 'ru2' -Identity 'Remote Desktop Users'
        Add-ADGroupMember -Members 'ru3' -Identity 'Remote Desktop Users'
        Add-ADGroupMember -Members 'ru4' -Identity 'Remote Desktop Users'
        Add-ADGroupMember -Members 'ru5' -Identity 'Remote Desktop Users'
        ```

    {% endlist %}

1. Set up RDP access permissions for the `Remote Desktop Users` group:

    {% list tabs group=programming_language %}
    
    - PowerShell {#powershell}
    
        ```powershell
        & secedit /export /cfg sec_conf_export.ini  /areas user_rights
        $secConfig = Get-Content sec_conf_export.ini
        $SID = 'S-1-5-32-555'
        $secConfig = $secConfig -replace '^SeRemoteInteractiveLogonRight .+', "`$0,*$SID"
        $secConfig | Set-Content sec_conf_import.ini
        & secedit /configure /db secedit.sdb /cfg sec_conf_import.ini /areas user_rights
        Remove-Item sec_conf_import.ini
        Remove-Item sec_conf_export.ini
        ```
      
    {% endlist %}

## How to delete the resources you created {#clear-out}

If you no longer need the resources you created, i.e., [VMs](../operations/vm-control/vm-delete.md) and [networks](../../vpc/operations/network-delete.md), delete them.