Featured image of post Installation guide for Exchange 2019

Installation guide for Exchange 2019

Installation guide for Exchange 2019

Foreword

In this guide, we will install an Exchange Server 2019 with the latest CU15 and configure it as securely as possible. We will create our own WAF rules on the Sophos XG and configure functions such as SPF, DMARC, DKIM and more.

Prerequisites

  • Active Directory
  • In possession of your own domain
  • Optional: DMZ domain (recommended, but not mandatory, significantly higher management effort)
  • Separate VLAN/network
  • Optional, but recommended: Separate zone (e.g. “EXCH”) on the Sophos
  • Wildcard certificate for your own domain (Can be mapped with Let’s Encrypt, but it’s better to buy a certificate for 1 year. I bought mine from https://www.ssl2buy.com/ for example. Costs only 42$ for 1 year).

Preparation of the VM

For our small environment, 16GB RAM is sufficient for the Exchange Server. Microsoft officially recommends 128GB RAM for Exchange Server 2019.

After a lot of research, I decided on the following constellation:

  • One hard disk for the operating system (36GB)
  • One hard disk for the Windows swap file (17GB)
  • One hard disk for the Exchange (82GB)

You may be wondering why the second hard disk for the swap file has 17GB. This is for the following reason: The VM gets 16GB RAM. 10MB should be used as an additional buffer. This results in the following calculation: 16 x 1024 + 10 = 16394MB RAM. However, as the formatting also results in a loss of storage space, the disk has to be slightly larger. I then decided on 17GB.

Please install the server in a separate VLAN and select the NIC accordingly during installation.

Installation of the OS

As there have been problems in the past regarding the installed language for updates, I generally recommend installing all servers in English. Otherwise, error messages are often poorly translated and not easy to find on the Internet.

You can then adjust the time and currency format to your country accordingly.

In this guide, I am following Microsoft’s best practice guidelines and best practices. According to Microsoft, a headless Windows server is recommended for Exchange Server 2019 - i.e. a server without a GUI. This is what we will do in this guide. When installing the Windows Server, select the top option “Windows Server 2025 Standard” for this reason.

For the operating system, we select the hard disk with 36GB.

Basic configuration of the Windows server

Configure IP, join domain, etc.

A password must be set after installation. We then log on to the server. After logging in, we are greeted with the following image. We can navigate through the various menus using the numbers.

You now name your server properly, add it to the domain, assign it a static IP address with DNS server, adjust the time/time zone if necessary and restart it. I think the steps are self-explanatory. It should look like that in the end.

Install VMware Tools

In addition, the VMware Tools should now be installed. As always, you mount these via the vCenter. We can then change to the directory in which the ISO was mounted. For me it was D:. Then simply run the setup.exe.

Then simply click through the setup (in my case it is now in German on the screenshots).

The server must be restarted after installation.

Configure Disks

Initialize Disks

In the sconfig menu, we select the number 15 to switch to Powershell. With the command “Get-Disk” we can display all hard disks.

1
Get-Disk

Disk 0 is our OS disk.

With the command “Initialize-Disk -Number 1” we can initialize the hard disk with the ID 1.

1
Initialize-Disk -Number 1

We have to do the same for the hard disk with ID 2.

1
Initialize-Disk -Number 2

Parition Disks

We now partition the hard disks. We can partition the hard disks with the “New-Partition” command. I give the disk with 17GB, i.e. the disk for our swap file, the drive letter F.

1
New-Partition -DiskNumber 1 -DriveLetter F -UseMaximumSize

We now have to do the same for the other hard disk. I give it the drive letter E for Exchange.

1
New-Partition -DiskNumber 2 -DriveLetter E -UseMaximumSize

We can now check everything with the “Get-Partition” command.

1
Get-Partition

Format Disks

Now we have to format the partitions with NTFS. This can be done with the “Format-Volume” command.

1
Format-Volume -DriveLetter F -FileSystem NTFS

Do the same for the other partition.

1
Format-Volume -DriveLetter E -FileSystem NTFS

Configure Swap File

We enter “cmd” to open the command prompt.

We disable the automatic page file.

1
wmic computersystem set AutomaticManagedPagefile=False

We delete the current page file.

1
wmic pagefileset where name="C:\\pagefile.sys" delete

We create a new page file on our dedicated page file drive.

1
wmic pagefileset create name="F:\pagefile.sys"

We adjust the size of the page file.

1
wmic pagefileset where name="F:\\pagefile.sys" set InitialSize=16394,MaximumSize=16394

We check the settings we have made.

1
wmic pagefile list

Preparation for Exchange installation

Install needed Features

Open Powershell on your server and install the following prerequisites.

1
Install-WindowsFeature Server-Media-Foundation, NET-Framework-45-Features, RPC-over-HTTP-proxy, RSAT-Clustering, RSAT-Clustering-CmdInterface, 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-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, RSAT-ADDS

This can take some minutes to complete.

It should display “Success” when it’s done.

Install VCRedist 2012

Enter the following command to download VCRedist C++ 2012 in x64.

1
Set-Variable ProgressPreference SilentlyContinue ; Invoke-WebRequest -Uri https://download.microsoft.com/download/1/6/b/16b06f60-3b20-4ff2-b699-5e9b7962f9ae/VSU_4/vcredist_x64.exe -OutFile vcredist_x64.exe;

Run the setup and just install it.

1
.\vcredist_x64.exe

Install VCRedist 2013

Enter the following command to download VCRedist C++ 2013 in x64.

1
Set-Variable ProgressPreference SilentlyContinue ; Invoke-WebRequest -Uri https://download.microsoft.com/download/2/e/6/2e61cfa4-993b-4dd4-91da-3737cd5cd6e3/vcredist_x64.exe -OutFile vcredist_x64_2013.exe;

Run the setup and just install it.

1
.\vcredist_x64_2013.exe

Install IIS-Rewrite

Enter the following command to download IIS-Rewrite.

1
Set-Variable ProgressPreference SilentlyContinue ; Invoke-WebRequest -Uri https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi -OutFile rewrite_amd64_en-US.msi;

Run the setup and just install it.

1
.\rewrite_amd64_en-US.msi

Download Exchange 2019 ISO

Enter the following command to download Exchange 2019 CU15.

1
Set-Variable ProgressPreference SilentlyContinue ; Invoke-WebRequest -Uri https://download.microsoft.com/download/7/0/a/70a4d908-eacb-426e-ad9f-e7768e27f873/ExchangeServer2019-x64-cu15.iso -OutFile ExchangeServer2019-x64-CU15.ISO;

Mount the ISO

1
Mount-DiskImage -ImagePath C:\Users\administrator.LAN\ExchangeServer2019-x64-CU15.ISO

Install UCMARedist

The UCMARedist setup is located on the Exchange ISO. In my case, the ISO was mounted with the letter G. I change the directory to G: and then to the “UCMARedist” folder. In this folder we simply execute the Setup.exe.

1
.\Setup.exe

Install Exchange

Create Folders

Before the actual Exchange installation, we now create three folders on the hard disk intended for the Exchange, in my case drive E. This can be done with the mkdir command.

We create a folder with the name “Exchange”.

1
mkdir Exchange

We create a folder with the name “Database”.

1
mkdir Database

We create a folder with the name “Logs”.

1
mkdir Logs

It should look like this.

Run the setup

Now we switch back to the drive with the mounted Exchange ISO. Here we now start the Exchange installation.

Change the “Organization Name” accordingly. Keep quotation marks.

1
.\Setup.exe /IAcceptExchangeServerLicenseTerms_DiagnosticDataOFF /InstallWindowsComponents /mode:Install /OrganizationName:"CHANGE ME" /r:Mailbox /TargetDir:"E:\Exchange"

The setup will start.

This will take around 15-20 minutes on SSD/NVMe.

It should look like this when the setup is finished. We need to reboot the server now.

Test OWA and ECP

OWA and ECP should now be accessible after the reboot.

OWA

OWA can be accessed at https://fqdn.of.your.server/owa.

ECP

ECP can be accessed at https://fqdn.of.your.server/ecp.

DNS Records

A-Record, MX-Record, SRV-Record

We will now configure DNS records. In my case, my domain is with Cloudflare. But it should actually be similar for other providers.

Login to cloudflare and click on your domain.

You should be here now. Click on “DNS” in the left-hand menu.

And then on “Records”.

Click on “Add record” and select “A” as the record type. Now enter a name for the A-Record under which your mail server should be accessible. A common name is “mail”. This is also the name I choose in my case. The IPv4 address field is self-explanatory.

Create another A-Record with the name “autodiscover”.

Create another record but select “MX” as the type. Enter “@” for the name and enter the previously created A-record for your mail server in the “Mail server” field. Select one hour for the TTL and 10 for the priority.

Create another record but select “SRV” as the type. You must enter the following in the “Name” field:

1
_autodiscover._tcp.your.domain

The target is again your previously created A-Record for your mail server. You can copy the other settings from the screenshot.

RDNS Configuration

You must now configure the reverse DNS entry with your server host. Please check whether your server provider has this option. My servers are at Hetzner, where this is configurable.

In my case, I change the reverse DNS entry for the IP address 144.76.105.35 to “mail.nobrac.ch”.

Renaming and moving the mailbox database and the log directory

Open Powershell on your Exchange Server and enter “LaunchEMS” to start the Exchange Management Console.

1
LaunchEMS

I call my mailbox database “MBXDB01”. You can call it whatever you like. Hostname of the server must of course be adapted to yours.

1
Get-MailboxDatabase -Server FSN-EXCH-01 | Set-MailboxDatabase -Name MBXDB01

We then move the database and the log directory to the dedicated folders we created previously.

1
Move-DatabasePath MBXDB01 -EdbFilePath E:\Database\MBXDB01.edb -LogFolderPath E:\Logs

Confirm the prompts with “Y”.

Exchange Configuration

Open your ECP and login.

Log in with the domain administrator. When you log in for the first time, you must configure the language and time zone.

You should see the following page after the login.

Configure “Accepted Domains”

Select “mail flow” in the menu on the left and then click on “accepted domains” at the top of the bar.

Then click on the plus symbol. The following window opens. We then assign any name here. It is best to enter the name of your domain here. We then also enter our domain in the “Accepted domains” field. We select “Authoritative” in the lower selection and click on “Save”.

It should look like this.

Configure “E-Mail Address Policy”

In the top menu bar, click on “email address policies”. You should be here.

Click again on the plus symbol. Enter a name for your policy.

Then click again on the plus next to “Email address format”. Select the accepted domain that you created in the previous step. In my case, I select “alias@contoso.com” for the e-mail address format. This is name.surname@domain.com. Make sure that “Make this format the reply email address” is checked.

It should look like this. Click on save.

You will receive a warning that the policy is not yet active. Simply confirm.

The overview should now look like this.

On the right side we see the status “Not Applied”. Here we now click on “Apply”. We receive another warning, which we simply confirm.

Click on close when it’s done.

Configure “Send Connectors”

In the top menu bar, click on “send connectors”. You should be here. Click on the plus symbol.

Enter a name of your choice. In my case, I use “Route-To-Internet”. We select “Internet” as the type.

In this guide we will guide the mailflow through our Sophos XG Firewall. For this reason, we select the option “Route mail through smart hosts” in the “Network settings”.

Then click on the plus symbol again and enter the IP of the gateway of the Exchange Server VLAN as the smart host.

It should look like this.

We don’t need authentication, so just click on next.

Click on the plus symbol for the “Address space” option.

Simply copy all the options from the screenshot.

It should look like this.

For the “Source server” option, click on the plus symbol again.

Select your Exchange Server and click on “Add”.

It should look like this. Click on finish.

The newly created send connector should now be displayed in the overview.

We select the entry and click on the pencil icon to edit the entry. The following window opens.

Click on “scoping” in the left bar and scroll all the way down. Enter the address of your mail server in the “FQDN” field.

Configuration “Virtual Directories”

Open notepad.exe on your Exchange server.

Paste the following into the document. The following variables must be adjusted:

  • $servername
  • $internalhostname
  • $externalhostname
  • $autodiscoverhostname

It is recommended by Microsoft that the internal and external hostnames are identical.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$servername = "FSN-EXCH-01"
$internalhostname = "mail.nobrac.ch"
$externalhostname = "mail.nobrac.ch"
$autodiscoverhostname = "autodiscover.nobrac.ch"
$owainturl = "https://" + "$internalhostname" + "/owa"
$owaexturl = "https://" + "$externalhostname" + "/owa"
$ecpinturl = "https://" + "$internalhostname" + "/ecp"
$ecpexturl = "https://" + "$externalhostname" + "/ecp"
$ewsinturl = "https://" + "$internalhostname" + "/EWS/Exchange.asmx"
$ewsexturl = "https://" + "$externalhostname" + "/EWS/Exchange.asmx"
$easinturl = "https://" + "$internalhostname" + "/Microsoft-Server-ActiveSync"
$easexturl = "https://" + "$externalhostname" + "/Microsoft-Server-ActiveSync"
$oabinturl = "https://" + "$internalhostname" + "/OAB"
$oabexturl = "https://" + "$externalhostname" + "/OAB"
$mapiinturl = "https://" + "$internalhostname" + "/mapi"
$mapiexturl = "https://" + "$externalhostname" + "/mapi"
$aduri = "https://" + "$autodiscoverhostname" + "/Autodiscover/Autodiscover.xml"
Get-OwaVirtualDirectory -Server $servername | Set-OwaVirtualDirectory -internalurl $owainturl -externalurl $owaexturl -Confirm:$false
Get-EcpVirtualDirectory -server $servername | Set-EcpVirtualDirectory -internalurl $ecpinturl -externalurl $ecpexturl -Confirm:$false
Get-WebServicesVirtualDirectory -server $servername | Set-WebServicesVirtualDirectory -internalurl $ewsinturl -externalurl $ewsexturl -Confirm:$false
Get-ActiveSyncVirtualDirectory -Server $servername | Set-ActiveSyncVirtualDirectory -internalurl $easinturl -externalurl $easexturl -Confirm:$false
Get-OabVirtualDirectory -Server $servername | Set-OabVirtualDirectory -internalurl $oabinturl -externalurl $oabexturl -Confirm:$false
Get-MapiVirtualDirectory -Server $servername | Set-MapiVirtualDirectory -externalurl $mapiexturl -internalurl $mapiinturl -Confirm:$false
Get-OutlookAnywhere -Server $servername | Set-OutlookAnywhere -externalhostname $externalhostname -internalhostname $internalhostname -ExternalClientsRequireSsl:$true -InternalClientsRequireSsl:$true -ExternalClientAuthenticationMethod 'Negotiate'  -Confirm:$false
Get-ClientAccessService $servername | Set-ClientAccessService -AutoDiscoverServiceInternalUri $aduri -Confirm:$false
Get-OwaVirtualDirectory -Server $servername | fl server,externalurl,internalurl
Get-EcpVirtualDirectory -server $servername | fl server,externalurl,internalurl
Get-WebServicesVirtualDirectory -server $servername | fl server,externalurl,internalurl
Get-ActiveSyncVirtualDirectory -Server $servername | fl server,externalurl,internalurl
Get-OabVirtualDirectory -Server $servername | fl server,externalurl,internalurl
Get-MapiVirtualDirectory -Server $servername | fl server,externalurl,internalurl
Get-OutlookAnywhere -Server $servername | fl servername,ExternalHostname,InternalHostname
Get-ClientAccessService $servername | fl name,AutoDiscoverServiceInternalUri

It should look like this.

Then save the text document e.g. under drive E with a name of your choice. Make sure you save it as a .ps1 file as we want to run it with Powershell.

Open an Exchange Management Console with “LaunchEMS” if you don’t have one open.

Then change to the path where you saved the script and execute it.

1
.\virtual_directories.ps1

It should then run through without any problems.

Configure Certificates

Back in ECP, we click on “servers” in the left-hand navigation bar and then on “certificates” in the top menu bar. The following overview page should be visible.

Now click on the symbol with the three dots and select “Import Exchange Certificate”.

The following window opens. Click on “Choose File” to select your certificate.

Select your certificate.

Also enter the password for the certificate.

Now click on the plus.

Select the Exchange server on which you want to install the certificate. Mark your Exchange and click on “Add”.

It should look like this.

We should then see our imported certificate on the overview page.

Bind Services

Select your imported certificate and click on the pencil icon to edit it.

The following window opens.

Click on “services” in the menu bar on the left.

Check the “SMTP” and “IIS” boxes.

Click on save and confirm the warning.

In the overview we can now see that the services “IIS” and “SMTP” are assigned to the certificate.

Open the Exchange Management Console on your Exchange server and enter the following commands for certificate POP and IMAP settings.

For POP:

1
Set-POPSettings -X509CertificateName mail.nobrac.ch

For IMAP:

1
Set-IMAPSettings -X509CertificateName mail.nobrac.ch

Back at the ECP, click again on the pencil icon to edit the certificate again.

Click on “services” again in the left menu.

Check the “IMAP” and “POP” boxes.

An error message appears stating that the certificate cannot be used and that we should configure the settings using the commands in Powershell. We have done this and the message can be ignored. This is a very old bug that has not yet been fixed. The POP and IMAP services are then also not displayed in the overview page for the certificate that the services are bound with the certificate. This is also normal (unfortunately).

Configure Receive Connectors

Select “mail flow” in the left menu bar and “receive connectors” in the top navigation bar. Select “Client Frontend” and then click on the pencil icon to edit it.

Click on “scoping” in the left menu bar and scroll all the way down. Change the FQDN accordingly. That’s it.

Configure Sophos XG

Enable SMTP-Relay for Zones

In your Sophos XG, navigate to “Administration” -> “Device Access” and activate the option “SMTP Relay” for your WAN zone and for the zone that you have created for your Exchange.

Create IP-Host

In your Sophos XG, navigate to “Hosts and Services” -> “IP host” and create a new host for your Exchange server.

Upload Certificate

In your Sophos XG, navigate to “Certificates” and upload your wildcard certificate.

Create Web Server

In your Sophos XG, navigate to “Web server” and click on “Add” to create a new object.

Assign a name, select your previously created Exchange host under “Host”. Select HTTPS for the “Type” and 443 as the “Port”. Set the “Time-out” option to 1850.

Create Protection Policies

Create Protection Policy for Autodiscover

In your Sophos XG, navigate to “Web server” -> “Protection policies”. There are ready-made protection policies for Exchange from Sophos, but these are extremely outdated. They are unusable.

Create a new protection policy and apply the settings from the screenshot.

“Entry URLs” to copy:

  • /autodiscover
  • /Autodiscover

“Skip filter rules” to copy:

  • 960015
  • 960911

Create Protection Policy for Webservices

Create another protection policy and apply the settings from the screenshot.

“Entry URLs” to copy:

  • /ecp
  • /ECP
  • /ews
  • /EWS
  • /Microsoft-Server-ActiveSync
  • /oab
  • /OAB
  • /owa
  • /OWA
  • /
  • /mapi
  • /MAPI

“Skip filter rules” to copy:

  • 920420
  • 920440
  • 960010
  • 960015
  • 960018
  • 960032
  • 981176

We should then see our new two protection policies in the overview.

Create Firewall Rules

Firewall Rule for Webservices

In your Sophos XG, navigate to “Rules and policies” -> “Firewall rules”. Create a new firewall rule.

Under “Action”, select the option “Protect with web server protection”. The other settings can be taken from the screenshot. Make sure that you select your port with the public IP address for “Hosted address”. For the domain, enter your domain for your mail server. I have also created a dedicated group for WAF-Rules to make administration simpler.

Path-specific Routing

Under “Protected servers” -> “Path-specific routing”, click on the pencil icon to edit the entry. You can copy the settings from the screenshot. I have also entered a few countries directly under “Blocked countries”. This at least blocks all the bots.

It should look like that.

Exceptions

Click on “Add new exception” under “Exceptions”. Enter the following paths.

“Paths” to copy:

  • /ews/*
  • /EWS/*
  • /Microsoft-Server-ActiveSync*
  • /oab/*
  • /OAB/*
  • /owa/*
  • /OWA/*
  • /Microsoft-Server-ActiveSync
  • /Microsoft-Server-ActiveSync?*
  • /ecp/*
  • /ECP/*

Check the options “Static URL hardening” and “Never change HTML during static URL hardening or form hardening”.

The overview should now look something like this.

Click again on “Add new exception”.

“Paths” to copy:

  • /owa/ev.owa*
  • /OWA/ev.owa*

Check the option “Antivirus”.

The overview should now look something like this.

Click once again on “Add new exception”.

“Paths” to copy:

  • /rpc/*
  • /RPC/*
  • /mapi/*
  • /MAPI/*
  • /Rpc/*

Check all options except “Never change HTML during static URL hardening or form hardening” and “Accept unhardened form data”.

The overview should now look something like this.

Now select your previously created protection policy under “Advanced” in the “Protection” option. In addition, check the “Pass host header” option.

Firewall Rule for Autodiscover

In your Sophos XG, navigate to “Rules and policies” -> “Firewall rules”. Create another firewall rule.

Under “Action”, select the option “Protect with web server protection”. The other settings can be taken from the screenshot. Make sure that you select your port with the public IP address for “Hosted address”. For the domain, enter your “autodiscover” domain.

Path-specific Routing

Under “Protected servers” -> “Path-specific routing”, click on the pencil icon to edit the entry. You can copy the settings from the screenshot. I have also entered a few countries directly under “Blocked countries”. This at least blocks all the bots.

It should look like that.

Exceptions

Click on “Add new exception” under “Exceptions”. Enter the following paths.

“Paths” to copy:

  • /autodiscover/*
  • /Autodiscover/*

Check the options “Static URL hardening” and “Never change HTML during static URL hardening or form hardening”

It should look like this.

Now select your previously created protection policy under “Advanced” in the “Protection” option. In addition, check the “Pass host header” option.

Licensed under CC BY-NC-SA 4.0
Last updated on Jun 26, 2025 00:00 UTC
Servus.
Built with Hugo
Theme Stack designed by Jimmy