Configuring Windows Server core with Powershell DSC

When working with Server core in large corporate environments you quickly find that setting up servers manually is both very time consuming and unnecessary when great features like Powershell DSC exist.

Here is a short guide on getting started with Powershell DSC.

Lab requirements:

1 x Windows 10 machine ( Configured with IP and C$ network path of the servers mapped)

2 x Windows Server 2016 core (configured with IPs and internet access)

For this lab everything is running on the same subnet and the firewall has been set to allow all In and Out. 

DHCP Server

To setup on of the servers as a DHCP server create a script on the C drive of the desired core server with the below code:

Configuration installDHCP
{
    Node localhost 
    {
        WindowsFeature DHCPServer {
            Ensure = "Present"
            Name = "DHCP"
        }
    }
}

installDHCP

Start-DscConfiguration -Wait -Force -Path .\installDHCP -Verbose

On the core server execute the script from the save location

Once complete run the follow command to check the status

Get-DscConfigurationStatus

Domain Controller

Repeat the above steps on to create two script on the second server

buildDomainController.ps1

<#Specify the configuration to be applied to the server.  This section
defines which configurations you're interested in managing.
#>
configuration buildDomainController
{
    Import-DscResource -ModuleName xComputerManagement -ModuleVersion 3.2.0.0
    Import-DscResource -ModuleName xNetworking -ModuleVersion 5.4.0.0
    Import-DscResource -ModuleName xDnsServer -ModuleVersion 1.9.0.0
    Import-DscResource -ModuleName xActiveDirectory -ModuleVersion 2.16.0.0

    Node localhost
    {
        LocalConfigurationManager {
            ActionAfterReboot = "ContinueConfiguration"
            ConfigurationMode = "ApplyOnly"
            RebootNodeIfNeeded = $true
        }
  
        xIPAddress NewIPAddress {
            IPAddress = $node.IPAddressCIDR
            InterfaceAlias = $node.InterfaceAlias
            AddressFamily = "IPV4"
        }

        xDefaultGatewayAddress NewIPGateway {
            Address = $node.GatewayAddress
            InterfaceAlias = $node.InterfaceAlias
            AddressFamily = "IPV4"
            DependsOn = "[xIPAddress]NewIPAddress"
        }

        xDnsServerAddress PrimaryDNSClient {
            Address        = $node.DNSAddress
            InterfaceAlias = $node.InterfaceAlias
            AddressFamily = "IPV4"
            DependsOn = "[xDefaultGatewayAddress]NewIPGateway"
        }

        User Administrator {
            Ensure = "Present"
            UserName = "Administrator"
            Password = $Cred
            DependsOn = "[xDnsServerAddress]PrimaryDNSClient"
        }

        xComputer NewComputerName {
            Name = $node.ThisComputerName
            DependsOn = "[User]Administrator"
        }

        WindowsFeature DNSInstall {
            Ensure = "Present"
            Name = "DNS"
            DependsOn = "[xComputer]NewComputerName"
        }

        xDnsServerPrimaryZone addForwardZoneCompanyPri {
            Ensure = "Present"
            Name = "company.pri"
            DynamicUpdate = "NonsecureAndSecure"
            DependsOn = "[WindowsFeature]DNSInstall"
        }

        xDnsServerPrimaryZone addReverseADZone3Net {
            Ensure = "Present"
            Name = "3.168.192.in-addr.arpa"
            DynamicUpdate = "NonsecureAndSecure"
            DependsOn = "[WindowsFeature]DNSInstall"
        }

        xDnsServerPrimaryZone addReverseADZone4Net {
            Ensure = "Present"
            Name = "4.168.192.in-addr.arpa"
            DynamicUpdate = "NonsecureAndSecure"
            DependsOn = "[WindowsFeature]DNSInstall"
        }

        xDnsServerPrimaryZone addReverseADZone5Net {
            Ensure = "Present"
            Name = "5.168.192.in-addr.arpa"
            DynamicUpdate = "NonsecureAndSecure"
            DependsOn = "[WindowsFeature]DNSInstall"
        }

        WindowsFeature ADDSInstall {
            Ensure = "Present"
            Name = "AD-Domain-Services"
            DependsOn = "[xDnsServerPrimaryZone]addForwardZoneCompanyPri"
        }

        xADDomain FirstDC {
            DomainName = $node.DomainName
            DomainAdministratorCredential = $domainCred
            SafemodeAdministratorPassword = $domainCred
            DatabasePath = $node.DCDatabasePath
            LogPath = $node.DCLogPath
            SysvolPath = $node.SysvolPath 
            DependsOn = "[WindowsFeature]ADDSInstall"
        }

        xADUser myaccount {
            DomainName = $node.DomainName
            Path = "CN=Users,$($node.DomainDN)"
            UserName = "myaccount"
            GivenName = "My"
            Surname = "Account"
            DisplayName = "My Account"
            Enabled = $true
            Password = $Cred
            DomainAdministratorCredential = $Cred
            PasswordNeverExpires = $true
            DependsOn = "[xADDomain]FirstDC"
        }

        xADUser philpug {
            DomainName = $node.DomainName
            Path = "CN=Users,$($node.DomainDN)"
            UserName = "philpug"
            GivenName = "Phil"
            Surname = "Pug"
            DisplayName = "Phil Pug"
            Enabled = $true
            Password = $Cred
            DomainAdministratorCredential = $Cred
            PasswordNeverExpires = $true
            DependsOn = "[xADDomain]FirstDC"
        }

        xADUser djones {
            DomainName = $node.DomainName
            Path = "CN=Users,$($node.DomainDN)"
            UserName = "djones"
            GivenName = "Dan"
            Surname = "Jones"
            DisplayName = "Dan Jones"
            Enabled = $true
            Password = $Cred
            DomainAdministratorCredential = $Cred
            PasswordNeverExpires = $true
            DependsOn = "[xADDomain]FirstDC"
        }

        xADUser jhelmick {
            DomainName = $node.DomainName
            Path = "CN=Users,$($node.DomainDN)"
            UserName = "jhelmick"
            GivenName = "Jane"
            Surname = "Helmick"
            DisplayName = "Jane Helmick"
            Enabled = $true
            Password = $Cred
            DomainAdministratorCredential = $Cred
            PasswordNeverExpires = $true
            DependsOn = "[xADDomain]FirstDC"
        }

        xADGroup IT {
            GroupName = "IT"
            Path = "CN=Users,$($node.DomainDN)"
            Category = "Security"
            GroupScope = "Global"
            MembersToInclude = "philpug", "jhelmick", "myaccount"
            DependsOn = "[xADDomain]FirstDC"
        }

        xADGroup DomainAdmins {
            GroupName = "Domain Admins"
            Path = "CN=Users,$($node.DomainDN)"
            Category = "Security"
            GroupScope = "Global"
            MembersToInclude = "philpug", "myaccount"
            DependsOn = "[xADDomain]FirstDC"
        }

        xADGroup EnterpriseAdmins {
            GroupName = "Enterprise Admins"
            Path = "CN=Users,$($node.DomainDN)"
            Category = "Security"
            GroupScope = "Universal"
            MembersToInclude = "philpug", "myaccount"
            DependsOn = "[xADDomain]FirstDC"
        }

        xADGroup SchemaAdmins {
            GroupName = "Schema Admins"
            Path = "CN=Users,$($node.DomainDN)"
            Category = "Security"
            GroupScope = "Universal"
            MembersToInclude = "philpug", "myaccount"
            DependsOn = "[xADDomain]FirstDC"
        }
    }
}

<#
Specify values for the configurations you're interested in managing.
See in the configuration above how variables are used to reference values listed here.
#>
            
$ConfigData = @{
    AllNodes = @(
        @{
            Nodename = "localhost"
            ThisComputerName = "dc01"
            IPAddressCIDR = "192.168.10.100/24"
            GatewayAddress = "192.168.10.1"
            DNSAddress = "192.168.10.100"
            InterfaceAlias = "Ethernet0"
            DomainName = "company.pri"
            DomainDN = "DC=Company,DC=Pri"
            DCDatabasePath = "C:\NTDS"
            DCLogPath = "C:\NTDS"
            SysvolPath = "C:\Sysvol"
            PSDscAllowPlainTextPassword = $true
            PSDscAllowDomainUser = $true
        }
    )
}

<#
Lastly, prompt for the necessary username and password combinations, then
compile the configuration, and then instruct the server to execute that
configuration against the settings on this local server.
#>

$domainCred = Get-Credential -UserName company\Administrator -Message "Please enter a new password for Domain Administrator."
$Cred = Get-Credential -UserName Administrator -Message "Please enter a new password for Local Administrator and other accounts."

BuildDomainController -ConfigurationData $ConfigData

Set-DSCLocalConfigurationManager -Path .\buildDomainController –Verbose
Start-DscConfiguration -Wait -Force -Path .\buildDomainController -Verbose

prepDomainController.ps1

Get-PackageSource -Name PSGallery | Set-PackageSource -Trusted -Force -ForceBootstrap

Install-PackageProvider -Name NuGet -Force

Install-Module xComputerManagement -RequiredVersion 3.2.0.0 -Force
Install-Module xNetworking -RequiredVersion 5.4.0.0 -Force
Install-Module xDnsServer -RequiredVersion 1.9.0.0 -Force
Install-Module xActiveDirectory -RequiredVersion 2.16.0.0 -Force

Write-Host "You may now execute '.\buildDomainController.ps1'"

The server will reboot during the configuration. To check the status of the setup your can to the command

Get-DscLocalConfigurationManager

If the LCMState is busy the process is still in progress. It can take more than 15 minutes to complete.

You May Also Like

About the Author: Phil

Leave a Reply

Your email address will not be published. Required fields are marked *