Lo so…esiste il Cloud, esiste Office365 che funziona, dove non ci sono problemi da gestire eccetera eccetera, tuttavia ci sono diverse aziende che hanno bisogno per, svariati motivi, di avere un’installazione On-Prem di Exchange Server, magari pure in alta disponibilità!
A parte le considerazioni e le più svariate obbiezioni al mondo On-Prem, in questo articolo andremo a vedere passo passo come installare Exchange Server 2019 in alta disponibilità.
Configurazione del Lab
Il lab è costruito in virtuale su ambiente Hyper-V 2019 ed è composto da queste macchine:
- Un Domain Controller (DOM01)
- 2 vCPU
- 8 GB di RAM
- Disco C 200 GB
- Disco D 50 GB
- NIC1: 192.168.10.11/24
- Due
server Exchange (EXC01 e EXC02)
- Due vCPU
- 32 GB di RAM
- Disco C da 200 GB S.O.
- Disco D da 50 GB Binari di Exchange
- Disco E da 50 GB Code
- Disco F da 200 GB Database
- Disco G da 20 GB Log
- Disco H da 200 GB Database
- Disco I da 20 GB Log
- NIC1: 192.168.10.21 e 192.168.10.22 entrambi in /24
- Un file server (FPS01)
- 2 vCPU
- 4 GB di RAM
- Disco C 200 GB
- Disco D 20 GB
- NIC1: 192.168.10.11/24
- Un
client (CLI01)
- 2 vCPU
- 4 GB di RAM
- Disco C 200 GB
- NIC1: 192.168.10.11/24
- Un
firewall (fwl00)
- 2 vCPU
- 4 GB di RAM
- Disco C 100 GB
- NIC1 (LAN): 192.168.10.1/24
- NIC2 (DMZ): 192. 168.20.1/24
- NIC3(WAN): dipende dal vostro lab!
Tutti i server Microsoft usano Windows Server 2019 aggiornato alla data dell’articolo. Il client usa Windows 10 Pro con Office 2019 Professional Plus. Come firewall potete usare quello che più vi viene comodo. Ad esempio, Smootwal (http://www.smoothwall.org/) in versione Open Source o qualsiasi versione trial di prodotti commerciali.
Per adesso possiamo ignorare la parte in DMZ. In seguito vedremo come aggiungere un SMTP Relay ed eventualmente un bilanciatore. Il dominio AD che useremo è pmincloud.com, che coincide con il nome pubblico, mentre il livello di foresta è 2016.

Passi di Installazione
I passi necessari per arrivare ad avere un lab funzionante sono i seguenti:
- Approvvigionamento dei server
- Installazione del sistema operativo
- Aggiornamento e patch
- Installazione e configurazione di AD
- Join dei sistemi (server e client) al dominio
- Configurazione dei server per Exchange (dischi, cartelle e tappi)
- Installazione dei prerequisiti sui server Exchange
- Preparazione di AD
- Installazione del primo nodo di Exchange
- Installazione del secondo nodo
- Configurazione Exchange
- Creazione e configurazione del DAG
Noi partiamo dal punto 6, cioè dalla preparazione dei nostri server Exchange.
Configurazione dei Server
Lavoreremo in PowerShell, in modo da essere sicuri che tutte le installazioni che faremo saranno simili e congruenti. Preventivamente installiamo i tool di amministrazione remota per AD e DNS, per semplificarci la vita nelle operazioni di manutenzione.
Lanciamo PowerShell con privilegi elevati ed eseguiamo il seguente cmdlet: Install-WindowsFeature RSAT-AD-Tools,RSAT-DNS-SERVER
Terminata questa operazione aggiungiamo i dischi al server secondo la descrizione fatta sopra. Procediamo preparando i dischi dei due server. Come accennato sopra, i server Exchange hanno questa configurazione dei dischi:
- Disco C: 200 GB – sistema operativo
- Disco D: 50 GB – eseguibili di Exchange
- Disco E: 20 GB – code
- Disco F: 200 GB – database
- Disco G: 20 GB – log relativi ai database del disco F
- Disco H: 200 GB – database
- Disco I: 20 GB – log relativi ai database del disco H
Come da best practice, i dischi che contengono i binari e le code sono formattati in NTFS, mentre i dischi per i database e i log, sono formattati in ReFS. Per uniformare il nome dei dischi iniziamo a rinominare il disco C.
Sempre in un PowerShell con privilegi elevati ed eseguiamo il seguente cmdlet: Get-Volume -DriveLetter c | Set-Volume -NewFileSystemLabel discoC-boot
Continuiamo a lavorare sugli altri dischi:
Get-Disk 1 | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel discoD-exc-bin
Get-Disk 2 | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel discoE-exc-queue
Get-Disk 3 | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem REFS -NewFileSystemLabel discoF-exc-edb01 -SetIntegrityStreams $false
Get-Disk 4 | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem REFS -NewFileSystemLabel discoG-exc-log01 -SetIntegrityStreams $false
Get-Disk 5 | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem REFS -NewFileSystemLabel discoH-exc-edb02 -SetIntegrityStreams $false
Get-Disk 6 | Initialize-Disk -PartitionStyle GPT -PassThru | New-Partition -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem REFS -NewFileSystemLabel discoI-exc-log01 -SetIntegrityStreams $false
Ora ci creiamo la struttura delle cartelle che ci serve per mantenere l’installazione ordinata e pulita.
mkdir “D:\Program Files\Microsoft\Exchange Server\V15”
mkdir E:\queue
mkdir E:\ipFilter
mkdir E:\temp
mkdir F:\maildb01-db
mkdir G:\maildb01-log
mkdir H:\maildb02-db
mkdir I:\maildb02-log
L’ultimo passo di questa fase consiste nella creazione dei “tappi” che ci servono a far ripartire al volo i database se un disco si dovesse riempire.
fsutil file createnew D:\cancellareInEmergenza5 5368709120
fsutil file createnew E:\cancellareInEmergenza5 5368709120
fsutil file createnew F:\cancellareInEmergenza20 21474836480
fsutil file createnew G:\cancellareInEmergenza2 2147483648
fsutil file createnew H:\cancellareInEmergenza20 21474836480
fsutil file createnew I:\cancellareInEmergenza2 2147483648
La dimensione dei tappi dipende dai vostri spazi, dai dischi che avete e da quanto velocemente i vostri utenti ingigantiscono le mailbox! Procediamo andando a installare i prerequisiti che devono essere presenti sul server per poter procedere.
Possiamo operare in due modi:
- A mano
- Usando Exchange2019-PreReqScript: https://gallery.technet.microsoft.com/office/Exchange-2019-Preview-b696abcc
Se vogliamo procedere manualmente procediamo installando i seguenti componenti:
- .NET Framework 4.7.2 o successivi (in base alla CU che volete installare)
- Visual C++ Redistributable Package for Visual Studio 2012
- Visual C++ Redistributable Package for Visual Studio 2013
- Server Media Foundation
- Unified Communications Managed API 4.0.
Poi andranno installate le funzionalità di Windows necessarie. Sempre in PowerShell elevata, eseguiamo il seguente cmdlet:
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
Oppure, senza impazzire, scarichiamo Exchange2019-PreReqScript, lo lanciamo e scegliamo in ordine la sequanza: 23 – 1 – reboot – 10 – 30 – 31 – 32 – 33 – 34 – 35 – reboot.

Approfittiamo dello script e configuriamo anche il Power Plan (30), il risparmio energetico delle schede di rete (31), la dimensione del file di paging (32), ridimensioniamo gli Event Logs (33) e il TCP Keep Alive (34). Terminata la configurazione un bel giro di Windows Update (35) e un bel riavvio!
Preparazione di Active Directory
Il primo passo prevede l’espansione dello schema, in modo da renderlo compatibile con gli attributi che ci servono per Exchange. Lanciamo un prompt dei comandi con privilegi elevati, ci spostiamo nella cartella di installazione di Exchange e lanciamo il seguente comando: setup.exe /PrepareSchema /IAcceptExchangeServerLicenseTerms
NB: Per poter eseguire lo script è necessario che l’utente faccia parte del gruppo Schema Admins.

Prima e dopo nella nostra sessione PowerShell, lanciamo questo cmdlet: “Exchange Schema Version = ” + ([ADSI](“LDAP://CN=ms-Exch-Schema-Version-Pt,” + ([ADSI]”LDAP://RootDSE”).schemaNamingContext)).rangeUpper
In questo modo possiamo controllare che l’espansione dello schema sia stata completata.

Se non stiamo facendo un aggiornamento, il primo risultato sarà nullo mentre il secondo dipenderà dalla CU che stiamo installando (nel nostro caso 17001 la CU3). A questo link (https://eightwone.com/references/schema-versions/) trovate tutte le versioni delle diverse versioni e delle CU di Exchange Server.
In ambienti di produzione, a questo punto dobbiamo attendere che questa modifica si propaghi a tutta la foresta. Nel nostro caso, avendo una foresta con un solo dominio e un solo domain controller, passiamo oltre!
Torniamo al nostro prompt dei comandi e lanciamo il seguente comando: setup.exe /PrepareAD /OrganizationName:pmincloud /IAcceptExchangeServerLicenseTerms
NB: Ovviamente sostituite pmincloud con il nome della vostra organizzazione.
NB: Per eseguire il comando è necessario che l’utente faccia parte del gruppo Enterprise Admins.

Come potete vedere, l’installazione ci ricorda che da questo momento in poi non sarà più possibile installare Exchange Server 2016 o 2013 nella nostra foresta. Per controllare, verifichiamo che sia stata creato la OU Microsoft Exchange Security Group (che contiene il gruppo Exchange Trusted Subsystem che ci servirà più avanti).

Completiamo le attività relative ad AD con il seguente comando: setup.exe /PrepareDomain /IAcceptExchangeServerLicenseTerms
In una foresta di produzione questo comando va eseguito in tutti i domini che conterranno utenti con mailbox o server Exchange. Se è necessario preparare tutti i domini, si può aggiungere lo switch /PrepareAllDomain.
NB: L’utente che lo esegue deve far parte del gruppo Domain Admins del dominio da preparare.

Ok! Ora siamo pronti per lanciare il setup vero e proprio.
Installazione di Exchange
L’installazione possiamo farla teoricamente con una bellissima interfaccia grafica… ma…mancano delle opzioni. Ad esempio, non possiamo battezzare il database che viene creato di default né specificarne il path!
Quindi sempre nel nostro prompt lanciamo il seguente comando: Setup.exe /mode:Install /role:Mailbox /TargetDir:”D:\Program Files\Microsoft\Exchange Server\V15″ /MdbName:maildb01 /DbFilePath:”F:\maildb01-db\maildb01.edb” /LogFolderPath:”G:\maildb01-log” /IAcceptExchangeServerLicenseTerms
Armiamoci di pazienza (o magari… pausa caffè!) e attendiamo che l’installazione si completi.

Dopo aver riavviato il server facciamo un po’ di controlli. Iniziamo aprendo la pagina web della EAC (Exchange Admin Center). Il warning che ci compare è corretto, visto che il nome che usiamo per accedere non corrisponde al certificato

Dopo aver confermato che vogliamo procedere si dovrebbe aprire la EAC.

Continuiamo i controlli lanciando la EMS (Exchange Management Shell) ed eseguendo il seguente CmdLet: get-ExchangeServer

Al termine dei controlli ci spostiamo sul secondo nodo ed eseguiamo nuovamente il setup, sempre in un prompt con i privilegi elevati: Setup.exe /mode:Install /role:Mailbox /TargetDir:”D:\Program Files\Microsoft\Exchange Server\V15″ /MdbName:maildb02 /DbFilePath:”H:\maildb02-db\maildb02.edb” /LogFolderPath:”I:\maildb02-log” /IAcceptExchangeServerLicenseTerms

Il messaggio che compare durante il setup relativo al Send connector è corretto, e non deve preoccuparci. Terminata l’installazione, e riavviato il server, rieseguiamo i controlli accedendo ad EAC e controllando i tab Servers e Databases della voce Servers.

Proseguiamo in EMS dove rilanciamo il CmdLet: get-ExchangeServer

A questo punto l’installazione è terminata.
Configurazione di Exchange
Una piccola premessa: sono fondamentalmente pigro! Pertanto, cerco sempre di crearmi degli script il più possibili riciclati: fatto una volta… funziona per sempre! Per questo motivo, userò nei cmdlet seguenti una serie di variabili, in modo che se dovessi rieseguire un’installazione cambio solo le variabili, e il resto rimane uguale!
Quindi per prima cosa definisco le variabili che mi servono. Apriamo la EMS e lanciamo i seguenti cmdlet:
$Server = “exc01”
$HTTPS_FQDN_Interna = “mail.pmincloud.com”
$HTTPS_FQDN_Esterna = “mail.pmincloud.com”
Inoltre, sempre per semplificarmi la vita (o il troubleshooting, come volete), configuro sempre un solo server per volta. Iniziamo sistemando “l’errore” dei connettori di invio.
A livello di architettura, visto che stiamo implementando una architettura in HA, dobbiamo simulare che i due server siano in due siti AD diversi. Quindi procediamo a creare il connettore d’uscita sul primo server. In EMS lanciamo questo cmdlet: New-SendConnector -Name “$($Server)–Internet” -AddressSpaces ‘*’ -SourceTransportServers $Server -DNSRoutingEnabled:$false -SmartHosts “172.30.126.1“
Anche in questo caso sostituite l’IP sopra con il nome FQDN o l’IP del vostro relay.

Per poter proseguire, ci serve definire un alias che useremo nella configurazione e che punterà o ai due server Exchange, se vogliamo usare il DNS in Round Robin per bilanciare, o al VIP del nostro bilanciatore. Nel lab ho scelto di usare la prima soluzione.
Ci spostiamo su DNS server, apriamo PowerShell con i soliti privilegi amministrativi e lanciamo questi due cmdlet:
Add-DnsServerResourceRecord -ZoneName “pmincloud.com” -A -Name “mail” -AllowUpdateAny -IPv4Address “192.168.10.21”
Add-DnsServerResourceRecord -ZoneName “pmincloud.com” -A -Name “mail” -AllowUpdateAny -IPv4Address “192.168.10.22”

Controlliamo, o con un nslookup o aprendo la console del DNS.

Ora torniamo sul server Exchange, dove avevamo aperto la EMS, e procediamo configurando nell’ordine Autodiscover, Virtual Folders e Outlook Anywhere lanciando i seguenti cmdlet:
#Autodiscover
Set-ClientAccessService -Identity $Server -AutodiscoverServiceInternalURI “https://$($HTTPS_FQDN_Interna)/Autodiscover/Autodiscover.xml”
#Virtual Folder
Get-OWAVirtualDirectory -Server $Server | Set-OWAVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/owa” -ExternalURL “https://$($HTTPS_FQDN_Esterna)/owa”
Get-ECPVirtualDirectory -Server $Server | Set-ECPVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/ecp” -ExternalURL “https://$($HTTPS_FQDN_Esterna)/ecp”
Get-OABVirtualDirectory -Server $Server | Set-OABVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/oab” -ExternalURL “https://$($HTTPS_FQDN_Esterna)/oab”
Get-ActiveSyncVirtualDirectory -Server $Server | Set-ActiveSyncVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/Microsoft-Server-ActiveSync” -ExternalURL “https://$($HTTPS_FQDN_Esterna)/Microsoft-Server-ActiveSync”
Get-WebServicesVirtualDirectory -Server $Server | Set-WebServicesVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/EWS/Exchange.asmx” -ExternalURL “https://$($HTTPS_FQDN_Esterna)/EWS/Exchange.asmx”
Get-MapiVirtualDirectory -Server $Server | Set-MapiVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/mapi” -ExternalURL https://$($HTTPS_FQDN_Esterna)/mapi
Get-PowerShellVirtualDirectory -Server $Server | Set-PowerShellVirtualDirectory -InternalURL “https://$($HTTPS_FQDN_Interna)/powershell” -ExternalURL “https://$($HTTPS_FQDN_Esterna)/powershell”
#Outlook AnyWhere
Set-OutlookAnywhere -identity “$($Server)\Rpc (Default Web Site)” -ExternalHostname $HTTPS_FQDN_Esterna -ExternalClientAuthenticationMethod ntlm -ExternalClientsRequireSsl:$True
Set-OutlookAnywhere -identity “$($Server)\Rpc (Default Web Site)” -InternalHostname $HTTPS_FQDN_Interna -InternalClientAuthenticationMethod ntlm -InternalClientsRequireSsl:$True

Proseguiamo con la configurazione del certificato. Sempre in EMS lanciamo il seguente cmdlet che ci consente di importare il certificato: Import-ExchangeCertificate -FileData ([Byte[]]$(Get-Content -Path C:\Setup\pmincloud-com.pfx -Encoding byte -ReadCount 0)) -Server $Server -FriendlyName CertificatoPmincloud-2019 -Password:(Get-Credential).password
Quando ci compare il popup di autenticazione, inseriamo la password associata al certificato e come nome utente… quello che volete! Va solo popolato per evitare errori, ma non è usato!
Dopo averlo importato ne recuperiamo il Thumbprint con il cmdlet: Get-ExchangeCertificate -server $Server
Quindi usiamo il Thumbprint per assegnarlo ai servizi SMTP e IIS (cioè OWA, EWS ecce cc): Enable-ExchangeCertificate –Thumbprint 5130DA36790E2D1EA91D21797C63B03DC0B289A7 –Services “IIS, SMTP” –Server $Server

Ora non ci rimane che riavviare il servizio di IIS: Restart-Service “World Wide Web Publishing Service”
Per controllare proviamo banalmente ad accedere ad EAC con il nome FQDN del server e controlliamo di non avere più errori di certificato.

Prima di considerare conclusa la nostra configurazione ci rimane ancora da spostare le code sul disco che avevamo preventivamente preparato. Per farlo, dopo esserci spostati nella cartella che contiene gli script di Exchange, eseguiamo il cmdlet:
cd ‘.\Program Files\Microsoft\Exchange Server\V15\Scripts\’
.\Move-TransportDatabase.ps1 -queueDatabasePath ‘E:\queue’ -queueDatabaseLoggingPath ‘E:\queue’ -iPFilterDatabasePath ‘E:\ipFilter’ -iPFilterDatabaseLoggingPath ‘E:\ipFilter’ -temporaryStoragePath ‘E:\temp’
Finiti tutti questi passi… li ripetiamo per il secondo server modificando le varabili iniziali in:
$Server = “exc02”
$HTTPS_FQDN_Interna = “mail.pmincloud.com”
$HTTPS_FQDN_Esterna = “mail.pmincloud.com”
Configurazione del DAG
Ora mi sposto sul file server, dove devo eseguire fondamentalmente due operazioni per consentirgli di operare come File Server Witness:
- Aggiungere il gruppo di domino Exchange Trusted Subsystem agli amministratori locali
- Creare la cartella che useremo per la configurazione
Quindi apriamo la solita PowerShell con i privilegi amministrativi ed eseguiamo questi due cmdlet:
Add-LocalGroupMember -Group “Administrators” -Member “pmincloud\Exchange Trusted Subsystem”
mkdir C:\dag01

Torniamo sul server Exchange, con la EMS aperta, e proseguiamo con la configurazione con il seguente cmdlet che consente di creare il DAG: New-DatabaseAvailabilityGroup -Name dag01 -WitnessServer “fps01.pmincloud.com” -WitnessDirectory C:\dag01 -FileSystem NTFS

Penultimo passo: l’aggiunta dei due server al DAG. Questa operazione ci potrebbe mettere un po’ di tempo, poiché installa sul nodo che andiamo ad aggiungere il servizio di Cluster su cui si appoggia Exchange per il DAG.
Quindi eseguiamo i due cmdlet:
Add-DatabaseAvailabilityGroupServer -Identity dag01 -MailboxServer exc01
Add-DatabaseAvailabilityGroupServer -Identity dag01 -MailboxServer exc02

Ultimo passo: mettiamo in replica i database con i due cmdlet seguenti:
Add-MailboxDatabaseCopy -Identity maildb01 -MailboxServer exc02
Add-MailboxDatabaseCopy -Identity maildb02 -MailboxServer exc01
Aspettiamo che sia raggiunta la convergenza controllando con il cmdlet: Get-MailboxDatabase | Get-MailboxDatabaseCopyStatus

A questo punto non ci resta che riavviare su entrambi i nodi il servizio di Information Store con il cmdlet: Restart-Service “Microsoft Exchange Information Store”
Quindi possiamo goderci un buon caffè: la configurazione è terminata e il nostro Exchange è in Alta Disponibilità!