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

# Deploying Microsoft Exchange


{% 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 %}



This tutorial describes how to deploy Microsoft Exchange servers in Yandex Cloud. You will install two Microsoft Exchange mail servers, two Active Directory servers, and two Edge Transport servers in the `ru-central1-a` and `ru-central1-b` availability zones. A network load balancer will distribute load across the servers. To manage the servers, you will use a separate VM with internet access hosted in the `ru-central1-d` availability zone.

1. [Get your cloud ready](#before-you-begin).
1. [Create a cloud network and subnets](#create-network).
1. [Create a script to manage a local administrator account](#admin-script).
1. [Create a VM for Active Directory](#ad-vm).
1. [Create a VM for File Share Witness](#ad-fsw-vm).
1. [Install and configure Active Directory](#install-ad).
1. [Configure the second domain controller](#install-ad-2).
1. [Install Microsoft Exchange](#install-exchange).
1. [Set up Microsoft Exchange servers](#create-ms-exchange-servers).
1. [Create a database availability group](#create-dag).
1. [Configure Client Access](#configure-access).
1. [Configure a network load balancer](#set-up-load-balancer).
1. [Configure accepted domains and the email address policy](#set-up-accepted-domains).
1. [Create and configure a VM for Edge Transport servers](#create-edge-vm).
1. [Configure Edge Transport servers](#set-up-edge-transport).
1. [Add Edge Transport servers to Exchange](#add-edges-to-exchange).

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 running a Microsoft Exchange instance includes:

* Fee for continuously running virtual machines (see [Yandex Compute Cloud pricing](../pricing.md)).
* Fee for load balancing (see [Yandex Network Load Balancer pricing](../../network-load-balancer/pricing.md)).
* Fee for using 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 `exchange-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 `exchange-network` as the network name.
     1. Click **Create network**.

   - CLI {#cli}

     To create a cloud network, run this command:

     ```
     yc vpc network create --name exchange-network
     ```

   {% endlist %}

1. Create three subnets in `exchange-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 `exchange-subnet-a` as the name and select the `ru-central1-a` 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**.

      Repeat these steps for two more subnets, `exchange-subnet-b` and `exchange-subnet-d`, in the `ru-central1-b` and `ru-central1-d` availability zones with `10.2.0.0/16` and `10.3.0.0/16` as the CIDR, respectively.

   - CLI {#cli}

      To create subnets, run these commands:

      ```
      yc vpc subnet create \
        --name exchange-subnet-a \
        --zone ru-central1-a \
        --network-name exchange-network \
        --range 10.1.0.0/16

      yc vpc subnet create \
        --name exchange-subnet-b \
        --zone ru-central1-b \
        --network-name exchange-network \
        --range 10.2.0.0/16

      yc vpc subnet create \
        --name exchange-subnet-d \
        --zone ru-central1-d \
        --network-name exchange-network \
        --range 10.3.0.0/16
      ```

   {% endlist %}


## Create a script to manage a local administrator account {#admin-script}

Create a file named `setpass` with a script that will set a password for the local administrator account when you create VMs via the CLI:

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

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#reference).

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

## Create a VM for Active Directory {#ad-vm}

Create two virtual machines for Active Directory. These VMs will not 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**:

      * Navigate to the **Custom** tab.
      * Click **Select** and select **Create** in the window that opens.
      * In the **Contents** field, select `Image` and then, the **Windows Server 2016 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
      * Optionally, enable **Delete along with the virtual machine** in the **Additional** field if you need this disk automatically deleted when deleting the VM.
      * Click **Add disk**.

  1. Under **Location**, select the `ru-central1-a` [availability zone](../../overview/concepts/geo-scope.md).
  1. Under **Disks and file storages**, set `50 GB` as your boot [disk](../concepts/disk.md) size.
  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**: `exchange-subnet-a`.
      * **Public IP address**: `No address`.

  1. Under **General information**, specify the VM name: `ad-vm-a`.
  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.

  Repeat these steps for `ad-vm-b` in the `ru-central1-b` availability zone and connect it to `exchange-subnet-b`.

- CLI {#cli}

  ```
  yc compute instance create \
    --name ad-vm-a \
    --hostname ad-vm-a \
    --memory 8 \
    --cores 4 \
    --zone ru-central1-a \
    --network-interface subnet-name=exchange-subnet-a,ipv4-address=10.1.0.3 \
    --create-boot-disk image-folder-id=standard-images,image-family=windows-2016-gvlk \
    --metadata-from-file user-data=setpass

  yc compute instance create \
    --name ad-vm-b \
    --hostname ad-vm-b \
    --memory 8 \
    --cores 4 \
    --zone ru-central1-b \
    --network-interface subnet-name=exchange-subnet-b,ipv4-address=10.2.0.3 \
    --create-boot-disk image-folder-id=standard-images,image-family=windows-2016-gvlk \
    --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 %}

{% endlist %}

## Create a VM for File Share Witness {#ad-fsw-vm}

You will use a file server with internet access to configure VMs with Active Directory.

{% 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**:

      * Navigate to the **Custom** tab.
      * Click **Select** and select **Create** in the window that opens.
      * In the **Contents** field, select `Image` and then, the **Windows Server 2016 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
      * Optionally, enable **Delete along with the virtual machine** in the **Additional** field if you need this disk automatically deleted when deleting the VM.
      * Click **Add disk**.

  1. Under **Location**, select the `ru-central1-d` [availability zone](../../overview/concepts/geo-scope.md).
  1. Under **Disks and file storages**, set `50 GB` as your boot disk size.
  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**: `2`.
      * **Guaranteed vCPU performance**: `100%`.
      * **RAM**: `4 GB`.

  1. Under **Network settings**:
  
      * In the **Subnet** field, select `exchange-subnet-d`.
      * In the **Public IP address** field, leave `Auto`.

  1. Under **General information**, specify the VM name: `fsw-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 fsw-vm \
    --hostname fsw-vm \
    --memory 4 \
    --cores 2 \
    --zone ru-central1-d \
    --network-interface subnet-name=exchange-subnet-d,nat-ip-version=ipv4 \
    --create-boot-disk image-folder-id=standard-images,image-family=windows-2016-gvlk \
    --metadata-from-file user-data=setpass
  ```

{% endlist %}

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

Active Directory VMs do not have internet access. To configure them, use `fsw-vm` through RDP.

1. Connect to `fsw-vm` through [RDP](../operations/vm-connect/rdp.md). Use the `Administrator` username and your password.
1. On `fsw-vm`, run RDP and connect to `ad-vm-a`. Use the `Administrator` username and your password.
1. Run PowerShell on `ad-vm-a` and set a static address:

   ```powershell
   netsh interface ip set address "eth0" static 10.1.0.3 255.255.255.0 10.1.0.1
   ```

1. Create a temporary folder:

   ```powershell
   mkdir C:\Windows\temp
   ```

1. Assign Active Directory roles:

   ```powershell
   Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
   ```

   Result:

   ```powershell
   Success Restart Needed Exit Code      Feature Result
   ------- -------------- ---------      --------------
   True    No             Success        {Active Directory Domain Services, Group P...
   ```

1. Create an Active Directory forest:

   ```powershell
   Install-ADDSForest -DomainName 'yantoso.net' -Force:$true
   ```

   Windows will restart automatically. After the reboot, connect to `ad-vm-a` using the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Rename the default site to `ru-central1-a`:

   ```powershell
   Get-ADReplicationSite 'Default-First-Site-Name' | Rename-ADObject -NewName 'ru-central1-a'
   ```

1. Create two more sites for the other availability zones:

   ```powershell
   New-ADReplicationSite 'ru-central1-b'
   New-ADReplicationSite 'ru-central1-d'
   ```

1. Create subnets and link them to the sites:

   ```powershell
   New-ADReplicationSubnet -Name '10.1.0.0/16' -Site 'ru-central1-a'
   New-ADReplicationSubnet -Name '10.2.0.0/16' -Site 'ru-central1-b'
   New-ADReplicationSubnet -Name '10.3.0.0/16' -Site 'ru-central1-d'
   ```

1. Rename the site link and configure replication:

   ```powershell
   Get-ADReplicationSiteLink 'DEFAULTIPSITELINK' | `
       Set-ADReplicationSiteLink -SitesIncluded @{Add='ru-central1-b'} -ReplicationFrequencyInMinutes 15 -PassThru | `
       Set-ADObject -Replace @{options = $($_.options -bor 1)} -PassThru | `
       Rename-ADObject -NewName 'ru-central1'
   ```

1. Set the DNS server forwarder:

   ```powershell
   Set-DnsServerForwarder '10.1.0.2'
   ```

1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | Set-DnsClientServerAddress -ServerAddresses "10.2.0.3,127.0.0.1"
   ```

## Configure the second domain controller {#install-ad-2}

1. Connect to `fsw-vm` through [RDP](../operations/vm-connect/rdp.md). Use the `Administrator` username and your password.
1. On `fsw-vm`, run RDP and connect to `ad-vm-b`. Use the `Administrator` username and your password.
1. Create a temporary folder:

   ```
   mkdir C:\Windows\temp
   ```

1. Assign Active Directory roles:

   ```powershell
   Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
   ```

   Result:

   ```powershell
   Success Restart Needed Exit Code      Feature Result
   ------- -------------- ---------      --------------
   True    No             Success        {Active Directory Domain Services, Group P...
   ```

1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | Set-DnsClientServerAddress -ServerAddresses "10.1.0.3,127.0.0.1"
   ```

1. Configure a static IP address:

   ```powershell
   netsh interface ip set address "eth0" static 10.2.0.3 255.255.255.0 10.2.0.1
   ```

1. Add the controller to the domain:

   ```powershell
   Install-ADDSDomainController `
       -Credential (Get-Credential "yantoso\Administrator") `
       -DomainName 'yantoso.net' `
       -Force:$true
   ```

   Windows will restart automatically. After the reboot, connect to `ad-vm-b` using the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Set the DNS server forwarder:

   ```powershell
   Set-DnsServerForwarder '10.2.0.2'
   ```

## Install Microsoft Exchange {#install-exchange}

1. Connect to `fsw-vm` using RDP and run PowerShell.
1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | Set-DnsClientServerAddress -ServerAddresses "10.1.0.3,10.2.0.3"
   ```

1. Add the server to the domain:

   ```powershell
   $Credentials = Get-Credential # yantoso\Administrator
   Add-Computer -DomainName yantoso.net -DomainCredential $Credentials -Force -Restart
   ```

   Windows will restart automatically. After the reboot, connect to `fsw-vm` using the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Create the `distrib` folder:

   ```powershell
   mkdir c:\distrib
   ```

1. Download the [Exchange Server distribution](https://www.microsoft.com/en-us/download/confirmation.aspx?id=58395) kit and required dependencies:
   1. [.NET Framework 4.7.2](https://go.microsoft.com/fwlink/p/?linkid=863265).
   1. [Visual C++ Redistributable Package for Visual Studio 2012](https://go.microsoft.com/fwlink/?linkid=327788). Rename the downloaded file to `vcredist_x64_2012.exe`.
   1. [Visual C++ Redistributable Package for Visual Studio 2013](https://go.microsoft.com/fwlink/?linkid=2002913). Rename the downloaded file to `vcredist_x64_2013.exe`.
   1. [Microsoft Unified Communications Managed API 4.0, Core Runtime 64-bit](https://go.microsoft.com/fwlink/p/?linkId=258269).

   Place the distribution kits in the `C:\distrib` directory.

1. Grant shared access from the domain to the distribution directory:

   ```powershell
   New-SmbShare -ReadAccess 'yantoso\domain users' -Path 'c:\distrib' -Name 'distrib'
   ```

## Set up Microsoft Exchange servers {#create-ms-exchange-servers}

### Set up the first Exchange server {#create-exchange-vm-a}

1. Create a VM named `vm-exchange-a`:

   {% 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**:

         * Navigate to the **Custom** tab.
         * Click **Select** and select **Create** in the window that opens.
         * In the **Contents** field, select `Image` and then, the **Windows Server 2016 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
         * Optionally, enable **Delete along with the virtual machine** in the **Additional** field if you need this disk automatically deleted when deleting the VM.
         * Click **Add disk**.

     1. Under **Location**, select the `ru-central1-a` [availability zone](../../overview/concepts/geo-scope.md).
     1. Under **Disks and file storages**:

         * Set the boot [disk](../concepts/disk.md) size: `100 GB`.
         * Click **Add** and add another `250 GB` SSD named `db-a`.

     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**: `8`.
         * **Guaranteed vCPU performance**: `100%`.
         * **RAM**: `32 GB`.

     1. Under **Network settings**, specify:

         * **Subnet**: `exchange-subnet-a`.
         * **Public IP address**: `No address`.

     1. Under **General information**, specify the VM name: `vm-exchange-a`.
     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 vm-exchange-a \
       --hostname vm-exchange-a \
       --memory 32 \
       --cores 8 \
       --zone ru-central1-a \
       --network-interface subnet-name=exchange-subnet-a \
       --create-boot-disk size=100,image-folder-id=standard-images,image-family=windows-2016-gvlk \
       --create-disk type=network-ssd,size=250,auto-delete=false \
       --metadata-from-file user-data=setpass
     ```

   {% endlist %}

1. Connect to `fsw-vm` through RDP.
1. Run RDP on `fsw-vm` and connect to `vm-exchange-a`. Use the `Administrator` username and your password. Launch PowerShell.
1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | Set-DnsClientServerAddress -ServerAddresses "10.1.0.3"
   ```

1. Add `vm-exchange-a` to the domain:

   ```powershell
   $Credentials = Get-Credential # yantoso\Administrator
   Add-Computer -DomainName yantoso.net -DomainCredential $Credentials -Force -Restart
   ```

   After the reboot, log in to the VM with the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Install the downloaded dependencies in the following order:
   1. `& \\fsw-vm\distrib\vcredist_x64_2012.exe /install /passive /norestart`
   1. `& \\fsw-vm\distrib\vcredist_x64_2013.exe /install /passive /norestart`
   1. `& \\fsw-vm\distrib\UcmaRuntimeSetup.exe /install /passive /norestart`
   1. `& \\fsw-vm\distrib\NDP472-KB4054530-x86-x64-AllOS-ENU.exe /install /passive /norestart`
1. Restart the VM: `Restart-Computer -Force`.

   After the reboot, log in to the VM with the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Install Exchange Mailbox Server on `vm-exchange-a`. Mount the distribution image from the shared folder containing the distribution kits:

   ```powershell
   Mount-DiskImage \\fsw-vm\distrib\ExchangeServer2016-x64-cu13.iso
   ```

1. Install Exchange Mailbox Server:

   ```powershell
   & D:\Setup.exe /Mode:Install /InstallWindowsComponents /Role:Mailbox /IAcceptExchangeServerLicenseTerms /OrganizationName:MyOrg
   Restart-Computer -Force
   ```

   After the installation is complete, the VM will restart automatically.

### Create the second Exchange server {#create-exchange-vm-b}

1. Create a VM named `vm-exchange-b`:

   {% 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**:

         * Navigate to the **Custom** tab.
         * Click **Select** and select **Create** in the window that opens.
         * In the **Contents** field, select `Image` and then, the **Windows Server 2016 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
         * Optionally, enable **Delete along with the virtual machine** in the **Additional** field if you need this disk automatically deleted when deleting the VM.
         * Click **Add disk**.
     1. Under **Location**, select the `ru-central1-b` [availability zone](../../overview/concepts/geo-scope.md).
     1. Under **Disks and file storages**:

         * Set the boot [disk](../concepts/disk.md) size: `100 GB`.
         * Click **Add** and add another `250 GB` SSD named `db-b`.

     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**: `8`.
         * **Guaranteed vCPU performance**: `100%`.
         * **RAM**: `32 GB`.

     1. Under **Network settings**, specify:

         * **Subnet**: `exchange-subnet-b`.
         * **Public IP address**: `No address`.

     1. Under **General information**, specify the VM name: `vm-exchange-b`.
     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 vm-exchange-b \
       --hostname vm-exchange-b \
       --memory 32 \
       --cores 8 \
       --zone ru-central1-b \
       --network-interface subnet-name=exchange-subnet-b \
       --create-boot-disk size=100,image-folder-id=standard-images,image-family=windows-2016-gvlk \
       --create-disk type=network-ssd,size=250,auto-delete=false \
       --metadata-from-file user-data=setpass
     ```

   {% endlist %}

1. Connect to `fsw-vm` through RDP.
1. Run RDP on `fsw-vm` and connect to `vm-exchange-b`. Use the `Administrator` username and your password. Launch PowerShell.
1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | Set-DnsClientServerAddress -ServerAddresses "10.1.0.3"
   ```

1. Add `vm-exchange-a` to the domain:

   ```powershell
   $Credentials = Get-Credential # yantoso\Administrator
   Add-Computer -DomainName yantoso.net -DomainCredential $Credentials -Force -Restart
   ```

   After the reboot, log in to the VM with the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Install the downloaded dependencies in the following order:
   1. `& \\fsw-vm\distrib\vcredist_x64_2012.exe /install /passive /norestart`
   1. `& \\fsw-vm\distrib\vcredist_x64_2013.exe /install /passive /norestart`
   1. `& \\fsw-vm\distrib\UcmaRuntimeSetup.exe /install /passive /norestart`
   1. `& \\fsw-vm\distrib\NDP472-KB4054530-x86-x64-AllOS-ENU.exe /install /passive /norestart`

1. Restart the VM: `Restart-Computer -Force`.

   After the reboot, log in to the VM with the `yantoso\Administrator` account and your password. Relaunch PowerShell.

1. Install Exchange Mailbox Server on `vm-exchange-b`. Mount the distribution image from the shared folder containing the distribution kits:

   ```powershell
   Mount-DiskImage \\fsw-vm\distrib\ExchangeServer2016-x64-cu13.iso
   ```

1. Install Exchange Mailbox Server:

   ```powershell
   & D:\Setup.exe /Mode:Install /InstallWindowsComponents /Role:Mailbox /IAcceptExchangeServerLicenseTerms /OrganizationName:MyOrg
   Restart-Computer -Force
   ```

   After the installation is complete, the VM will restart automatically.

## Create a database availability group {#create-dag}

A database availability group ensures fault tolerance for mailbox servers via DB replication and automatic DB failover in the event of a crash.

1. Connect to `fsw-vm` through RDP.
1. Grant the `yantoso\Exchange Trusted Subsystem` group administrator permissions for `fsw-vm`:

   ```powershell
   Add-LocalGroupMember -Group 'Administrators' -Member 'yantoso\Exchange Trusted Subsystem'
   ```

### Create disks for VM databases {#create-db-disks}

1. Run RDP on `fsw-vm` and connect to `vm-exchange-a`. Use `yantoso\Administrator` as your username and your password.
1. Create a secondary disk and format it:

   ```powershell
   Get-Disk | `
       Where-Object PartitionStyle -eq raw | `
       Initialize-Disk -PartitionStyle GPT -PassThru | `
       New-Partition -DriveLetter 'Z' -UseMaximumSize | `
       Format-Volume -FileSystem NTFS -NewFileSystemLabel "mdb" -Confirm:$false -AllocationUnitSize 65536
   ```

1. Install the `Failover-Clustering` role:

   ```powershell
   Install-WindowsFeature -Name 'Failover-Clustering' -IncludeManagementTools
   ```

Repeat these commands for `vm-exchange-b`.

### Configure the database availability group {#dag-configuration}

1. Run RDP on `fsw-vm` and connect to `vm-exchange-a` through RDP. Use `yantoso\Administrator` as your username and your password.
1. Run the Exchange Management Shell.
1. Create a database availability group:

   ```powershell
   New-DatabaseAvailabilityGroup `
       -Name ycdag `
       -WitnessServer fsw-vm `
       -DatabaseAvailabilityGroupIpAddresses 255.255.255.255
   ```

1. Add the `vm-exchange-a` and `vm-exchange-b` servers to the DAG:

   ```powershell
   Add-DatabaseAvailabilityGroupServer -Identity ycdag -MailboxServer vm-exchange-a
   Add-DatabaseAvailabilityGroupServer -Identity ycdag -MailboxServer vm-exchange-b
   ```

1. Check the status of your servers; both should be in the `Operational Servers` column:

   ```powershell
   Get-DatabaseAvailabilityGroup -Status
   ```

   Result:

   ```powershell
   Name             Member Servers                                      Operational Servers
   ----             --------------                                      -------------------
   ycdag            {VM-EXCHANGE-A, VM-EXCHANGE-B}                    {VM-EXCHANGE-A, VM-EXCHANGE-B}
   ```

1. Create a mailbox server database:

   ```powershell
   New-MailboxDatabase -Name yamdb -EdbFilePath 'Z:\MDB\yamdb\yamdb.edb' -LogFolderPath 'Z:\MDB\yamdb\log' -Server vm-exchange-a
   ```

1. Mount this database:

   ```powershell
   Mount-Database yamdb
   ```

1. Create a copy of this database on the second server:

   ```powershell
   Add-MailboxDatabaseCopy -Identity yamdb -MailboxServer vm-exchange-b -SeedingPostponed
   Update-MailboxDatabasecopy yamdb\vm-exchange-b –CatalogOnly
   ```

1. Check the DB status:

   ```powershell
   Get-MailboxDatabaseCopyStatus -Server vm-exchange-a
   Get-MailboxDatabaseCopyStatus -Server vm-exchange-b
   ```

## Configure Client Access {#configure-access}

To work with various client applications, you need to create virtual directories.

1. Set the mail domain:

   ```powershell
   $MailDomain = "mail.yantoso.net"
   ```

1. ECP:

   ```powershell
   Get-EcpVirtualDirectory | Set-EcpVirtualDirectory -ExternalUrl "https://$MailDomain/ecp"
   ```

1. EWS:

   ```powershell
   Get-WebServicesVirtualDirectory | Set-WebServicesVirtualDirectory -ExternalUrl "https://$MailDomain/ews/exchange.asmx"
   ```

1. Active Sync:

   ```powershell
   Get-ActiveSyncVirtualDirectory | Set-ActiveSyncVirtualDirectory -ExternalUrl "https://$MailDomain/Microsoft-Server-ActiveSync"
   ```

1. OAB:

   ```powershell
   Get-OabVirtualDirectory | Set-OabVirtualDirectory -ExternalUrl "https://$MailDomain/OAB"
   ```

1. OWA:

   ```powershell
   Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -ExternalUrl "https://$MailDomain/owa"
   ```

1. PowerShell:

   ```powershell
   Get-PowerShellVirtualDirectory | Set-PowerShellVirtualDirectory -ExternalUrl "https://$MailDomain/powershell"
   ```

1. MAPI:

   ```powershell
   Get-MapiVirtualDirectory | Set-MapiVirtualDirectory -ExternalUrl "https://$MailDomain/mapi"
   ```

## Configure a network load balancer {#set-up-load-balancer}

It will distribute the load across the Exchange servers in various availability zones.

{% list tabs group=instructions %}

- Management console {#console}

  To create a [network load balancer](../../network-load-balancer/concepts/index.md):

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create your service account.
  1. Navigate to **Network Load Balancer**.
  1. Click **Create a network load balancer**.
  1. Enter the load balancer name: `exchange-lb`.
  1. In the **Public address** field, select **Auto**.
  1. Under **Listeners**, click **Add listener**.
  1. Enter the listener name: `yassl`.
  1. Set `443` as the listener port and target port and click **Add**.
  1. Under **Target groups**, click **Add target group**.
  1. In the **Target group** field, expand the drop-down list and select **Create a target group**.
  1. Specify the target group name: `exchange-tg`.
  1. Select `vm-exchange-a` and `vm-exchange-b` and click **Create**.
  1. Click **Configure**.
  1. Enter `exchange-hc` as the health check name.
  1. Select the **TCP** check.
  1. Set the port to `443`.
  1. Leave the default values for the other properties and click **Apply**.
  1. Click **Create**.

- CLI {#cli}

  1. Create a network load balancer:

     ```
     yc lb nlb create --name exchange-lb
     ```

  1. Create a target group:

     ```
     yc lb tg create --name exchange-tg
     ```

  1. Get information about the mailbox servers:

     ```
     yc compute instance get vm-exchange-a
     yc compute instance get vm-exchange-b
     ```

     Copy the VM subnet IP addresses and IDs.

  1. Add the servers to the target group:

     ```
     yc lb tg update --name exchange-tg \
       --target address=<vm-exchange-a_IP_address>,subnet-id=<vm-exchange-a_subnet_ID> \
       --target address=<vm-exchange-b_IP_address>,subnet-id=<vm-exchange-b_subnet_ID>
     ```

  1. Add the listener to the network load balancer:

     ```
     yc lb nlb add-listener --name exchange-lb --listener name=yassl,port=443,target-port=443,external-ip-version=ipv4
     ```

  1. Get information about the target groups:

     ```
     yc lb tg list
     ```

     Copy the ID of the target group you created.

  1. Connect the target group to the network load balancer using the target group ID:

     ```
     yc lb nlb attach-target-group \
       --name exchange-lb \
       --target-group target-group-id=<target_group_ID>,healthcheck-name=exchange-hc,healthcheck-tcp-port=443
     ```

{% endlist %}

## Configure accepted domains and the email address policy {#set-up-accepted-domains}

By default, the system creates a domain for you. If you need to change the domain, use this command:

```powershell
New-AcceptedDomain -Name yantoso.net -DomainName yantoso.net
```

Edit the email address policy:

```powershell
Get-EmailAddressPolicy | Set-EmailAddressPolicy -EnabledPrimarySMTPAddressTemplate '@yantoso.net'
```

All new mailboxes will automatically get an alias with the `@yantoso.net` domain.

## Create a VM for Edge Transport servers {#create-edge-vm}

The Edge Transport servers will take on the main user load, such as receiving emails from the internet, filtering out spam, and forwarding messages to internal Exchange mailbox servers.

### Create a VM for the `vm-edge-a` server {#create-edge-a}

Create a VM named `vm-edge-a`:

{% 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**:

      * Navigate to the **Custom** tab.
      * Click **Select** and select **Create** in the window that opens.
      * In the **Contents** field, select `Image` and then, the **Windows Server 2016 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
      * Optionally, enable **Delete along with the virtual machine** in the **Additional** field if you need this disk automatically deleted when deleting the VM.
      * Click **Add disk**.
  1. Under **Location**, select the `ru-central1-a` [availability zone](../../overview/concepts/geo-scope.md).
  1. Under **Disks and file storages**, set `50 GB` as your boot [disk](../concepts/disk.md) size.
  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**:
  
      * In the **Subnet** field, select `exchange-subnet-a`.
      * Leave the **Public IP address** field set to `Auto` or select `List` and the public IP address from the list if you [reserved](../../vpc/operations/get-static-ip.md) one earlier.
  1. Under **General information**, specify the VM name: `vm-edge-a`.
  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 vm-edge-a \
    --hostname vm-edge-a \
    --memory 8 \
    --cores 4 \
    --zone ru-central1-a \
    --network-interface subnet-name=exchange-subnet-a,nat-ip-version=ipv4 \
    --create-boot-disk size=50,image-folder-id=standard-images,image-family=windows-2016-gvlk \
    --metadata-from-file user-data=setpass
  ```

 {% endlist %}

### Create a VM for the `vm-edge-b` server {#create-edge-b}

Create a VM named `vm-edge-b`:

{% 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**:

      * Navigate to the **Custom** tab.
      * Click **Select** and select **Create** in the window that opens.
      * In the **Contents** field, select `Image` and then, the **Windows Server 2016 Datacenter** image from the list below. For more information on how to upload your own image for Microsoft products, see [Importing a custom image](../../microsoft/byol.md#how-to-import).
      * Optionally, enable **Delete along with the virtual machine** in the **Additional** field if you need this disk automatically deleted when deleting the VM.
      * Click **Add disk**.
  1. Under **Location**, select the `ru-central1-b` [availability zone](../../overview/concepts/geo-scope.md).
  1. Under **Disks and file storages**, set `50 GB` as your boot [disk](../concepts/disk.md) size.
  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**:
  
      * In the **Subnet** field, select `exchange-subnet-b`.
      * Leave the **Public IP address** field set to `Auto` or select `List` and the public IP address from the list if you [reserved](../../vpc/operations/get-static-ip.md) one earlier.
  1. Under **General information**, specify the VM name: `vm-edge-b`.
  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 vm-edge-b \
    --hostname vm-edge-b \
    --memory 8 \
    --cores 4 \
    --zone ru-central1-b \
    --network-interface subnet-name=exchange-subnet-b,nat-ip-version=ipv4 \
    --create-boot-disk size=50,image-folder-id=standard-images,image-family=windows-2016-gvlk \
    --metadata-from-file user-data=setpass
  ```

{% endlist %}

## Configure Edge Transport servers {#set-up-edge-transport}

### Configure the Edge Transport server in the `ru-central1-a` zone {#edge-a}

1. Connect to `fsw-vm` through RDP.
1. Connect to `vm-edge-a` through RDP. Use the `Administrator` username and your password. Launch PowerShell.
1. Create a temporary folder:

   ```
   mkdir C:\Windows\temp
   ```

1. Install the ADLDS roles on the server:

   ```powershell
   Install-WindowsFeature ADLDS
   ```

1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | `
       Set-DnsClientServerAddress -ServerAddresses "10.1.0.3,10.2.0.3"
   ```

1. Configure remote access to the distribution folder located on the `fsw-vm` server:

   ```powershell
   $Credential = Get-Credential # Username: yantoso\Administrator

   New-PSDrive -Name 'fsw-vm' -PSProvider:FileSystem -Root '\\fsw-vm.ru-central1.internal\distrib' -Credential $Credential
   ```

   Enter `yantoso\Administrator` as your username and your password.

1. Install the dependencies:

   ```powershell
   & fsw-vm:\vcredist_x64_2012.exe /install /passive /norestart
   & fsw-vm:\NDP472-KB4054530-x86-x64-AllOS-ENU.exe /install /passive /norestart
   ```

1. Copy the Microsoft Exchange distribution kit to the `vm-edge-a` server:

   ```powershell
   copy-item fsw-vm:\ExchangeServer2016-x64-cu13.iso c:\windows\temp\ExchangeServer2016-x64-cu13.iso
   ```

1. Specify the primary DNS suffix:

   ```powershell
   $Suffix = 'ru-central1.internal'

   Set-ItemProperty -path HKLM:\system\CurrentControlSet\Services\tcpip\parameters -Name Domain -Value $Suffix

   Set-ItemProperty -path HKLM:\system\CurrentControlSet\Services\tcpip\parameters -Name 'NV Domain' -Value $Suffix
   ```

1. Restart the VM:

   ```powershell
   Restart-Computer -Force
   ```

   Reconnect to `vm-edge-a` through RDP and run PowerShell.

1. Mount the Exchange Server distribution kit:

   ```powershell
   Mount-DiskImage c:\windows\temp\ExchangeServer2016-x64-cu13.iso
   ```

1. Install Edge Transport Server on the `vm-edge-a` server:

   ```powershell
   & D:\Setup.exe /Mode:Install /InstallWindowsComponents /Role:EdgeTransport /IAcceptExchangeServerLicenseTerms /OrganizationName:MyOrg
   ```

### Configure the Edge Transport server in the `ru-central1-b` zone {#edge-b}

1. Connect to `fsw-vm` through RDP.
1. Connect to `vm-edge-b` through RDP. Use the `Administrator` username and your password. Launch PowerShell.
1. Create a temporary folder:

   ```powershell
   mkdir C:\Windows\temp
   ```

1. Install the ADLDS roles on the server:

   ```powershell
   Install-WindowsFeature ADLDS
   ```

1. Configure the DNS client:

   ```powershell
   Get-NetAdapter | `
       Set-DnsClientServerAddress -ServerAddresses "10.2.0.3,10.1.0.3"
   ```

1. Configure remote access to the distribution folder located on the `fsw-vm` server:

   ```powershell
   $Credential = Get-Credential # Username: yantoso\Administrator

   New-PSDrive -Name 'fsw-vm' -PSProvider:FileSystem -Root '\\fsw-vm.ru-central1.internal\distrib' -Credential $Credential
   ```

   Enter `yantoso\Administrator` as your username and your password.

1. Install the dependencies:

   ```powershell
   & fsw-vm:\vcredist_x64_2012.exe /install /passive /norestart
   & fsw-vm:\NDP472-KB4054530-x86-x64-AllOS-ENU.exe /install /passive /norestart
   ```

1. Copy the Microsoft Exchange distribution kit to the `vm-edge-b` server:

   ```powershell
   copy-item fsw-vm:\ExchangeServer2016-x64-cu13.iso c:\windows\temp\ExchangeServer2016-x64-cu13.iso
   ```

1. Specify the primary DNS suffix:

   ```powershell
   $Suffix = 'ru-central1.internal'

   Set-ItemProperty -path HKLM:\system\CurrentControlSet\Services\tcpip\parameters -Name Domain -Value $Suffix

   Set-ItemProperty -path HKLM:\system\CurrentControlSet\Services\tcpip\parameters -Name 'NV Domain' -Value $Suffix
   ```

1. Restart the VM:

   ```powershell
   Restart-Computer -Force
   ```

   Reconnect to `vm-edge-b` through RDP and run PowerShell.

1. Mount the Exchange Server distribution kit:

   ```powershell
   Mount-DiskImage c:\windows\temp\ExchangeServer2016-x64-cu13.iso
   ```

1. Install Edge Transport Server on the `vm-edge-b` server:

   ```powershell
   & D:\Setup.exe /Mode:Install /InstallWindowsComponents /Role:EdgeTransport /IAcceptExchangeServerLicenseTerms /OrganizationName:MyOrg
   ```

## Add the Edge Transport servers to Exchange {#add-edges-to-exchange}

Each Edge Transport server must subscribe to a site in its own availability zone.

### Set up a subscription on the `vm-edge-a` server {#subscribe-vm-edge-a}

1. Create the `subscribe` folder:

   ```powershell
   mkdir c:\subscribe
   ```

1. Run the Exchange Management Shell. Create a subscription file on the `vm-edge-a` server:

   ```powershell
   New-EdgeSubscription -FileName "C:\subscribe\$(hostname).xml"
   ```

1. Copy the `C:\subscribe\vm-edge-a.xml` file to the `vm-exchange-a` server, to the `C:\root\vm-edge-a.xml` folder.

1. Log in to the `vm-exchange-a` server and run the Exchange Management Shell.

1. Subscribe the `vm-edge-a` Edge Transport servers to the `ru-central1-a` site:

   ```powershell
   New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "C:\root\vm-edge-a.xml" -Encoding Byte -ReadCount 0)) -Site "ru-central1-a"
   ```

1. Use this command to check the subscription:

   ```powershell
   Get-EdgeSubscription
   ```

   Result:

   ```powershell
   Name            Site                 Domain
   ----            ----                 ------
   vm-edge-a       yantoso.net/Confi... ru-central1.internal
   ```

1. Check the sync status:

   ```powershell
   Test-EdgeSynchronization
   ```

   The `SyncStatus` parameter should change to `Normal`.


### Set up a subscription on the `vm-edge-b` server {#subscribe-vm-edge-b}

1. Create the `subscribe` folder:

   ```powershell
   mkdir c:\subscribe
   ```

1. Run the Exchange Management Shell. Create a subscription file on the `vm-edge-b` server:

   ```powershell
   New-EdgeSubscription -FileName "C:\subscribe\$(hostname).xml"
   ```

1. Copy the `C:\subscribe\vm-edge-b.xml` file to the `vm-exchange-b` server, to the `C:\root\vm-edge-b.xml` folder.

1. Log in to the `vm-exchange-b` server and run the Exchange Management Shell.

1. Subscribe the `vm-edge-b` Edge Transport servers to the `ru-central1-b` site:

   ```powershell
   New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "C:\root\vm-edge-b.xml" -Encoding Byte -ReadCount 0)) -Site "ru-central1-b"
   ```

1. Make sure the subscription was created using this command:

   ```powershell
   Get-EdgeSubscription
   ```

   Result:

   ```powershell
   Name            Site                 Domain
   ----            ----                 ------
   vm-edge-a       yantoso.net/Confi... ru-central1.internal
   vm-edge-b       yantoso.net/Confi... ru-central1.internal
   ```

1. Check the sync status:

   ```powershell
   Test-EdgeSynchronization
   ```

   The `SyncStatus` parameter should change to `Normal`.

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

To stop paying for the deployed servers, delete all [VMs](../operations/vm-control/vm-delete.md) and the [load balancer](../../network-load-balancer/operations/load-balancer-delete.md):

* `fsw-vm`
* `ad-vm-a`
* `ad-vm-b`
* `vm-exchange-a`
* `vm-exchange-b`
* `vm-edge-a`
* `vm-edge-b`
* `exchange-lb` load balancer