Installation, Configuration and Migration from Exchange 2013/2016 to Microsoft Exchange 2019 Server

Hardware used during the installation:

  • a VM on XEN Server 8.1
  • CPU: AMD EPYC 7402P 24-Core Processor – 4 core then switch to 8 core when switching to production
  • Memory: 32 Gbytes then switch to 48 Gbytes when moving to production
  • System drive: SSD with 80 Gbytes and 52 Gbytes used by the system
  • Data drive: SSD with 500 Gbytes used by exchange database and log files
  • The size of all databases and transaction logs are around 400GB. (as reference) when planning

Pre-requirement infrastructure

  • Domain forest minimum: Windows Server 2012 R2 Standard or Datacenter
  • Coexistence during the migration: Supported with Exchange 2013 Cumulative Update 21 (CU21) or later on all Exchange 2013 servers in the organization, including Edge Transport servers. Supported with Exchange 2016 CU11 or later on all Exchange 2016 servers in the organization, including Edge Transport servers
  • Operating system: Windows Server 2019 Standard or Datacenter
  • Exchange support only TLS 1.2 natively
  • All operating system since Windows 8.1 support it and you don’t need to enable TLS 1.0 or TLS 1.1 in regedit
  • If you have Windows 7 or Windows 8, then follow the link to enable the support of TLS 1.2
  • Enable TLS 1.1 and TLS 1.2 on Windows 7 and Windows 8

Pre-requirement software

Pre-requirement lync or Skype for Business server components, if needed

  • Install the Server Media Foundation windows feature by executing the following command in Windows PowerShell:
    PowerShell: Install-WindowsFeature Server-Media-Foundation
  • Install Unified Communications Managed API 4.0. This package is available for download and in the \UCMARedist folder on the Exchange Server media.

System pre-requirement: Windows components

  • Desktop Experience
  • Windows 2019 Desktop Experience
  • PowerShell: Install-WindowsFeature Server-Media-Foundation, NET-Framework-45-Features, RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, RSAT-Clustering-Mgmt, RSAT-Clustering-PowerShell, WAS-Process-Model, Web-Asp-Net45, Web-Basic-Auth, Web-Client-Auth, Web-Digest-Auth, Web-Dir-Browsing, Web-Dyn-Compression, Web-Http-Errors, Web-Http-Logging, Web-Http-Redirect, Web-Http-Tracing, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Lgcy-Mgmt-Console, Web-Metabase, Web-Mgmt-Console, Web-Mgmt-Service, Web-Net-Ext45, Web-Request-Monitor, Web-Server, Web-Stat-Compression, Web-Static-Content, Web-Windows-Auth, Web-WMI, Windows-Identity-Foundation, RSAT-ADDS
  • Disable IPv6 because it will not be used and make sure it’s not used on receive connectors after installing Exchange

Installing Microsoft Exchange 2019 server

  • Exchange 2019 installation 01
  • Exchange 2019 installation 02
  • Exchange 2019 installation 03
  • Exchange 2019 installation 04
  • Exchange 2019 installation 05
  • Exchange 2019 installation 06
  • Exchange 2019 installation 07
  • Exchange 2019 installation 08
  • Exchange 2019 installation 09
  • Exchange 2019 installation 10
  • Exchange 2019 installation 12

Enter the product key from exchange powershell

  • Set-ExchangeServer Mailbox01 -ProductKey 12345-12345-12345-12345-12345

Delete the default exchange certificate and add a third part certificate

  • Open mmc.exe and add snap-in certificates
  • Change windows certificate
  • Delete the Friendly Name “Microsoft Exchange”
  • Exchange 2019 Configuration 03
  • Enable third party certificate on exchange smtp service using its Thumbprint
    • Start Exchange powershell on the server
    • Run: Get-ExchangeCertificate
    • Find the correct Thumbprint certificate
    • Run: Enable-ExchangeCertificate 700AD1C6BEC29AB997806652BAC4513315D49285 -Services SMTP

Allow Exchange to send mails outside

  • Open Exchange Admin Center: https://SERVERNAME/ecp/?ExchClientVer=15
  • mail flow -> send connectors
  • Select the connector used to send mails and add your new server to the scoping (source server)

Create additional database on your exchange

  • Depend on the version of your exchange, standard or enterprise. you can create maximum 5 database or unlimited for enterprise
  • Create a folders structure on your additional drive for all your data files and log files
  • On Exchange Admin Center
  • Open: Servers -> Databases
  • Click on “+” symbol
  • Create exchange database
  • Run: iisreset from command prompt to restart IIS
  • Use “…” to mount the database.

Move Arbitration mailbox from default mailbox database

  • Check the name of the default mailboxdatabse by running from exchange powershell:
    Get-MailboxDatabase
  • Check if the server have any system mailbox ( AuditLog, Archive, Arbitration, Monitoring)
  • Get-MailBox -server SRVERNAME -Arbitration
  • Move the default mailbox to the new mailbox database
  • Get-Mailbox -server SERVERNAME -AuditLog | New-MoveRequest -TargetDatabase “System_DB001”
  • Check if the moved mailbox is complete
  • Get-MoveRequest | Get-MoveRequestStatistics
  • Delete completed move request:
  • Get-MoveRequest -movestatus completed | remove-moverequest
  • Delete the default database after moving all system mailbox
  • Remove-MailboxDatabase -Identity “Mailbox Database 1067783753”
  • After deleting the database, restart Microsoft Exchange Mailbox Replication service

Moving mailboxes from previous exchange 2013 or 2016 to the new exchange

  • Tune the slow migration speed of mailboxes
    • Open a file below in notepad.exe
    • C:\Program Files\Microsoft\Exchange Server\V15\Bin\MsExchangeMailboxReplication.exe.config
    • Add: ExportBufferSizeOverrideKB=”7500″ under ExportBufferSizeKB
    • Update: ExportBufferSizeKB=”512” to ExportBufferSizeKB=”10240
    • Update: MaxActiveMovesPerSourceMDB=”20” to MaxActiveMovesPerSourceMDB=”50
    • Update: MaxActiveMovesPerTargetMDB=”20” to MaxActiveMovesPerTargetMDB=”50
  • Example of moving mailbox
    • New-MoveRequest -Identity user01@domain.com -TargetDatabase “System_DB001” -Priority Emergency -BadItemLimit 10
    • New-MoveRequest -Identity user02@domain.com -TargetDatabase “System_DB001” -Priority Emergency -BadItemLimit 10
    • New-MoveRequest -Identity user02@domain.com -TargetDatabase “System_DB001” -Priority Emergency -BadItemLimit 10
  • Check the status: Get-MoveRequest | Get-MoveRequestStatistics
  • Remove the completed: Get-MoveRequest -movestatus completed | remove-moverequest
  • Move Public Folder. if available
  • Get-Mailbox -PublicFolder | New-MoveRequest -TargetDatabase PublicFolder_DB001 -Priority Emergency -BadItemLimit 10
  • Move Arbitration mailboxes from the previous exchange server database before delete them
  • Check if you don’t have any extra mailbox like rooms in the previous database
  • Get-MailboxDatabase OLD_Exchange_DB001 | Get-Mailbox | New-MoveRequest -Priority Emergency -BadItemLimit 10
  • All the databases from the previous exchange need to be empty, otherwise you will not be able to delete it from Exchange Admin Center
  • Delete the databases from the previous exchange server and then delete exchange from the servers, to clean all records about previous exchange from Active directory

Create Database Availability Groups (DAG)

  • Install failover cluster on all member servers (the members of the cluster must (should) have the same operating system)
  • Prestage Cluster Name object (CNO)
    • Open Active Directory Users and Computers
    • Create a new computer in Computers OU:
    • Create Computer Object 01
    • Create Computer Object 02
  • Enable Active Directory Advanced features
  • Enable AD Advanced Features
  • Open the properties of the new computer object and select Security tab
  • Add all servers which you are planning to make members of the DAG (exchange servers)
  • Give a full right to the members of the DAG
  • Switch to “Member Of” tab
  • Make sure it is member of “Exchange Trusted Subsystem” or add it
  • Finally, Disable the computer account.
  • Create the DAG on Exchange Admin Console -> Servers -> database availability groups
  • DAG Configuration
    • The name of DAG in the picture above should be the same like the computer name created early
    • The Witness server, guarantees that a Quorum is preserved in the cluster. Two exchange servers must be available in any time, if you have to reboot one of them (in our labs we use two servers), with witness server (which is a small share will keep exchange accessible while one of them is down.
    • Witness directory is the local shared directory on the network of Witness server
    • DAG IP, is an IP which will be added automatically to the active exchange server while the second one is running as passive server or offline for some reason
  • Add the servers to the new created DAG
  • Click on the database and select
  • On the second server, create the same path structure folders like in the first server
  • Select a database and click on “” to “Add database copy” like in the picture below
  • DAG Configuration 03
  • Exchange will create a copy of the database and transaction logs on the second server automatically (if the path on both servers are the same). in our labs
    • EDB folder: D:\Exchange Database\System_DB001\EDB
    • Transaction log: D:\Exchange Database\System_DB001\T_Logs

Enable circular logging

  • On each database, enable circular logging in order to save space of your DATA volume where the databases are located (if needed)

Enable Exchange Anti-Spam on each exchange server

  • Check transport agent before installation using powershell: Get-TransportAgent
  • Anti-Spam installation 01
  • On powershell run: C:\Program Files\Microsoft\Exchange Server\V15\Scripts>.\install-AntispamAgents.ps1
  • Anti-Spam installation 02
  • Run: Get-TransportAgent, to see the difference
  • Anti-Spam installation 03
  • Set-ContentFilterConfig -Enabled $true
  • Set-SenderFilterConfig -Enabled $true
  • Set-SenderIDConfig -Enabled $true
  • Set-SenderReputationConfig -Enabled $true
  • Restart “Microsoft Exchange Transport” service

Update Virtual Directory URL

  • Make sure the server name, InterlanURL and ExternalURL are changed before running the commands
Get-EcpVirtualDirectory -Server SERVERNAME | Set-EcpVirtualDirectory -InternalUrl https://servername.domain.local/ecp -ExternalUrl https://mail.domain.com/ecp
Get-WebServicesVirtualDirectory -Server SERVERNAME | Set-WebServicesVirtualDirectory -InternalUrl https://servername.domain.local/EWS/Exchange.asmx -ExternalUrl https://mail.domain.com/EWS/Exchange.asmx
Get-MapiVirtualDirectory -Server SERVERNAME | Set-MapiVirtualDirectory -InternalUrl https://servername.domain.local/mapi -ExternalUrl https://mail.domain.com/mapi
Get-ActiveSyncVirtualDirectory -Server SERVERNAME | Set-ActiveSyncVirtualDirectory -InternalUrl https://servername.domain.local/Microsoft-Server-ActiveSync -ExternalUrl https://mail.domain.com/Microsoft-Server-ActiveSync
Get-OabVirtualDirectory -Server SERVERNAME | Set-OabVirtualDirectory -InternalUrl https://servername.domain.local/OAB -ExternalUrl https://mail.domain.com/OAB
Get-OwaVirtualDirectory -Server SERVERNAME | Set-OwaVirtualDirectory -InternalUrl https://servername.domain.local/owa -ExternalUrl https://mail.domain.com/owa
Get-PowerShellVirtualDirectory -Server SERVERNAME | Set-PowerShellVirtualDirectory -InternalUrl http://servername.domain.local/powershell -ExternalUrl http://mail.domain.com/powershell
Get-ClientAccessService -Identity SERVERNAME | Set-ClientAccessService -AutoDiscoverServiceInternalUri https://servername.domain.local/Autodiscover/Autodiscover.xml
Get-AutodiscoverVirtualDirectory -Server SERVERNAME | Set-AutodiscoverVirtualDirectory -InternalUrl https://servername.domain.local/autodiscover/autodiscover.xml -ExternalUrl https://mail.domain.com/autodiscover/autodiscover.xml
Get-OutlookAnywhere -Server SERVERNAME | Set-OutlookAnywhere https://servername.domain.local -ExternalUrl https://mail.domain.com

Set-OutlookProvider EXPR –CertPrincipalName msstd:mail.domain.com
Set-OutlookProvider EXCH –CertPrincipalName msstd:mail.domain.com
Set-OutlookProvider WEB –CertPrincipalName msstd:mail.domain.com

Configure Autodiscover on Internal and External DNS servers

On outside DNS configure an A-record which point to our outside IP addresses of our Exchange servers and then add an SRV-record

  • Add the A-records “mail” on outside DNS domain name. (in our lab it’s domain.com)
  • outside DNS A-record
  • Add an SRV-record pointing to mail.domain.com
  • outside DNS SRV-record

On internal Active Directory server, we will add a zone mail.domain.com and add to it the IP address used while configuring our DAG192.168.0.23” or create A-record “mail” in our local zone “domain.local” which point to our DAG IP address and then add an SRV record.

  • Add an SRV-record
  • autodiscover dns record 01
  • autodiscover dns record 02
  • Depend on the method used (new zone or A-record on your local domain zone) make sure the record on “the host offering this service” is correct. in our lab we create a new zone mail.domain.com
  • autodiscover dns record 03

Update IIS binding

Update the IIS on each exchange server and make sure you add new bind to host name mail.domain.com and map it to a correct SSL certificate

  • Add a new IIS bind

Enable Strict-Transport-Security

  • IIS-configuration 02
  • Name: Strict-Transport-Security
  • Value: max-age=31536000

Protect Exchange OWA from Brute-Force attack

  • Open Regedit on Exchange CAS server.
  • Go to HKLM\SYSTEM\CurrentControlSET\Services\InetInfo\Parameters
  • Create a new DWORD with a name UserTokenTTL and keep the value 30 (this means keeping the Cache only for 30 Sec)

Clean log files from system drive

Move mail.que and IPFilter database from system drive

  • Automatic: (recommended to reuse mail.queue DB and not lost data)
  • [PS] C:\Program Files\Microsoft\Exchange Server\V15\scripts>.\Move-TransportDatabase.ps1 -queueDatabasePath ‘Q:\TransportRoles\data\Queue’ -queueDatabaseLoggingPath ‘Q:\TransportRoles\data\Queue’ -iPFilterDatabasePath ‘Q:\TransportRoles\data\IpFilter’ -iPFilterDatabaseLoggingPath ‘Q:\TransportRoles\data\IpFilter’ -temporaryStoragePath ‘Q:\TransportRoles\data\Temp’
  • Manual
  • to save space on system drive, it’s better to move mail.que database to alternative drive in the same way like we do for exchange mailbox databases
  • edit: C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config

<add key=”QueueDatabasePath” value=”D:\Exchange Database\Exchange Queue\Database” />
<add key=”QueueDatabaseLoggingPath” value=”D:\Exchange Database\Exchange Queue\Logs” />
<add key=”IPFilterDatabasePath” value=”D:\Exchange Database\IPFilter\Database” />
<add key=”IPFilterDatabaseLoggingPath” value=”D:\Exchange Database\IPFilter\Logs” />

Restart “Microsoft Exchange Transport” service

Enable the Password Reset Option

Log in to exchange server with your admin credentials.Open PowerShell with administrative privileges and execute the following three commands.

  • Add-pssnapin microsoft*
  • Install-CannedRbacRoles
  • Install-CannedRbacRoleAssignments
  • Log in to the Exchange Admin Center and click on Permissions.
  • Right-click ‘Organization Management’ and then click Edit.
  • Click the ‘+’ sign on the roles section.
  • Select ‘Reset Password’ and then click Add. Click OK and then click Save.
  • Log out from the Exchange Admin Center.
  • When you log in again to the Exchange Admin Center and open any existing user mailbox properties, you should see the reset password option.

Configure Kerberos authentication with Exchange 2019

Restrict ECP access

Save Sent Items in Shared Mailbox Sent Items folder

Get-Mailbox info@example.net | set-mailbox -MessageCopyForSentAsEnabled $True
or
Get-Mailbox info@example.net | set-mailbox-MessageCopyForSendOnBehalfEnabled $True