<# .SYNOPSIS This PowerShell script configures a Windows server as a domain controller. .DESCRIPTION The script performs the following tasks: 1. Checks for pending system reboots and creates a log directory if it doesn't exist. 2. Validates the server's hostname and allows the user to edit it if necessary. 3. Configures a static IP address if not already set. 4. Installs required roles, including AD-Domain-Services, DNS, RSAT-AD-Tools, and gpmc. 5. Configures Active Directory Domain Services (ADDS) Forest, including creating a DNS delegation, setting up the database, and configuring the domain mode and forest mode. .PARAMETER None .EXAMPLE Run this script in PowerShell to configure a Windows server as a domain controller. .NOTES This script requires administrative privileges to run. Author: D.de Kooker - info@dcomputers.nl Version: 1.0 DISCLAIMER: Use scripts at your own risk, if there is anything I can help you with I will try but I do not take responsibility for the way that anyone else uses my scripts. Sharing is caring. Share your knowledge with the world so that everybody can learn from it. .LINK The latest version can Always be found on my GIT page on the link below: https://git.dcomputers.nl/Dcomputers/PowershellScripts #> #region Global script settings and variables $Version = "v1.0" $logfilelocation = "$($MyInvocation.MyCommand.Path | Split-Path -Parent)\Logs" $logfilename = "$(Get-Date -Format yyyyMMddHHmmss)-ADDS_Installation.log" $summaryfilename = "$(Get-Date -Format yyyyMMddHHmmss)-ADDS_Installation_Summary.txt" #endregion #region functions function Initiate-Log { # Get current user and session information $username = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $computerName = $env:COMPUTERNAME $sessionID = $pid $date = Get-Date -Format "yyyy-MM-dd HH:mm:ss" # Write log header $logHeader = "[$date] Log initiated by $username on $computerName (Session ID: $sessionID)" Add-Content -Path $logfilelocation\$logfilename -Value "**********************" Add-Content -Path $logfilelocation\$logfilename -Value "LogFile initiation" Add-Content -Path $logfilelocation\$logfilename -Value "Start time: $date" Add-Content -Path $logfilelocation\$logfilename -Value "Username: $username" Add-Content -Path $logfilelocation\$logfilename -Value "Machine: $computerName" Add-Content -Path $logfilelocation\$logfilename -Value "Process ID: $sessionID" Add-Content -Path $logfilelocation\$logfilename -Value "Script Version: $Version" Add-Content -Path $logfilelocation\$logfilename -Value "Script Source: https://git.dcomputers.nl/Dcomputers/PowershellScripts" Add-Content -Path $logfilelocation\$logfilename -Value "**********************" } function Approve-Reboot { Write-Host "The computer needs to be restarted in order to apply the changes" Write-Host "Please confirm that you have read this message and are ready to reboot" $confirmReboot = Read-Host "Type 'yes' to confirm" if ($confirmReboot -eq "yes") { Restart-Computer -Force } else { Write-Host "Reboot cancelled. Please restart the server manually to apply the changes" exit 1 } } function Write-Log { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [string]$Message, [Parameter(Mandatory=$false)] [ValidateSet("INFO", "WARNING", "ERROR")] [string]$Level = "INFO" ) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logmessage = "[$timestamp] [$Level] $Message" Add-Content -Path $logfilelocation\$logfilename -Value $logmessage } function Write-Summary { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [string]$Message ) Add-Content -Path $logfilelocation\$summaryfilename -Value $Message } #endregion #region prerequisites check #Create log directory if not present if (!(test-path $logfilelocation)) {mkdir $logfilelocation} Initiate-Log #Check pending system reboot if (Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Session Manager" -Name "PendingFileRenameOperations" -ErrorAction Ignore) { Approve-Reboot } #Server hostname validation $hostname = [System.Net.Dns]::GetHostName() Write-Host "Current hostname is: $hostname" Write-Log -Message "Current hostname is: $hostname" -Level "INFO" $editHostname = Read-Host "Do you want to edit the hostname? (y/n)" if ($editHostname -eq "y") { $newHostname = Read-Host "Enter new hostname" Rename-Computer -NewName $newHostname -Force Write-Host "Hostname changed to: $newHostname" Write-Log -Message "Hostname changed to: $newHostname" -Level "INFO" Write-Log -Message "Computer restart required after hostname change" -Level "WARNING" [bool]$rebootneeded = $true } #Static IP configuration $staticIP = Get-NetIPAddress -AddressFamily IPv4 -PrefixOrigin Manual -ErrorAction SilentlyContinue if ($staticIP) { Write-Host "Static IP address is configured: $($staticIP.IPAddress)" Write-Log -Message "Static IP address is configured: $($staticIP.IPAddress)" -Level "INFO" } else { Write-Host "No static IP address is configured, let's configure it" Write-Log -Message "No static IP address is configured, let's configure it" -Level "INFO" $ipAddress = Read-Host "Enter IP address" $subnetMask = Read-Host "Enter subnet mask eg. 24" $gateway = Read-Host "Enter gateway" $dns = Read-Host "Enter DNS server address" New-NetIPAddress -IPAddress $ipAddress -PrefixLength $subnetMask -InterfaceIndex $((Get-NetAdapter).ifIndex) -DefaultGateway $gateway Set-DnsClientServerAddress -InterfaceIndex $((Get-NetAdapter).ifIndex) Write-Host "Static IP address configured: $ipAddress" Write-Log -Message "Static IP address configured: $ipAddress" -Level "INFO" } #Reboot server if needed if ($rebootneeded) { Approve-Reboot } #endregion #region install required roles and features #Check the required roles $requiredRoles = @("AD-Domain-Services", "DNS", "RSAT-AD-Tools", "gpmc") $progress = 0 Write-Progress -Activity "Installing required roles" -Status "Starting installation" -PercentComplete $progress foreach ($role in $requiredRoles) { if (!(Get-WindowsFeature -Name $role).Installed) { Write-Host "Installing required role: $role" Write-Log -Message "Installing required role: $role" -Level "INFO" Write-Progress -Activity "Installing required roles" -Status "Installing $role" -PercentComplete $progress Add-WindowsFeature -Name $role -IncludeAllSubFeature -IncludeManagementTools $progress += (100 / $requiredRoles.Count) [bool]$rebootneeded = $true } } Write-Progress -Activity "Installing required roles" -Status "Completed" -PercentComplete 100 #Reboot server if needed if ($rebootneeded) { Approve-Reboot } #All role requirements are met Write-Host "All role requirements are met continuing Forest configuration" Write-Log -Message "All role requirements are met continuing Forest configuration" -Level "INFO" #endregion #region configure ADDS #Gather the required information $domainName = Read-Host "Enter the domain name" $domainNetBiosName = ($domainName.Split(".")[0] | ForEach-Object { $_.ToUpper() }) #Confirm domain name and netbios name Write-Host "Domain name: $domainName" Write-Log -Message "Domain name: $domainName" -Level "INFO" Write-Host "NetBIOS name: $domainNetBiosName" Write-Log -Message "NetBIOS name: $domainNetBiosName" -Level "INFO" $confirmDomainInfo = Read-Host "Is this information correct? (y/n)" if ($confirmDomainInfo -eq "y") { #Perform the installation Import-Module ADDSDeployment Install-ADDSForest ` -CreateDnsDelegation:$false ` -DatabasePath "C:\Windows\NTDS" ` -DomainMode "WinThreshold" ` -DomainName $domainName ` -DomainNetbiosName $domainNetBiosName ` -ForestMode "WinThreshold" ` -InstallDns:$true ` -LogPath "C:\Windows\NTDS" ` -NoRebootOnCompletion:$true ` -SysvolPath "C:\Windows\SYSVOL" ` -Force:$true } else { Write-Host "Domain configuration cancelled. Please restart the script to continue." Write-Log -Message "Domain configuration cancelled. Please restart the script to continue." -Level "WARNING" exit 1 } Write-Host "ADDS Forest configuration completed successfully" Write-Log -Message "ADDS Forest configuration completed successfully" -Level "INFO" #endregion #region summary Write-Summary "ADDS Forest configuration Summary:" Write-Summary "---------------------------" Write-Summary "Configuration date: $(Get-Date -Format "dd-MM-yyy HH:mm:ss")" Write-Summary "Domain name: $domainName" Write-Summary "NetBIOS name: $domainNetBiosName" Write-Summary "---------------------------" Approve-Reboot #endregion