Windows Server 2016 Technical Preview 5 has just been released. Check what’s new in TP5 on this TechNet page
Let’s quickly review the top 10 reasons why you’ll love Windows Server 2016:
- PowerShell and DSC
- Active Directory and Identity
- Server management tools
- Remote Desktop Services
- Software defined storage
- Software-defined compute
- Software-defined networking
- Security
- Containers
- Nano Server
There are also some fresh news related to Nano server:
- Nano Server TP5 IaaS Image in the Azure Gallery
- Developing Native Apps on Nano Server
- WSA Updates in WS 2016 TP5
- PackageManagement Support on Nano Server
- NanoServerApiScan.exe updated for TP5
- Bug Bounty for Nano Server
Bonus 1: There’s a free e-book about Windows Server 2016.
Bonus 2:: I’ve updated the demo code I presented last year about How to use WDS to PXE Boot a Nano Server VHD with PowerShell published on PowerShell Magazine
If you use the updated version below, you end up with 2 virtual machines: a Windows Server 2016 TP5 (with Active Directory and WDS) and a Nano VM ready to be provisioned through PXE.
The updated code for TP5 is available as a gist on this page.
Let’s see quickly what’s new:
The Convert-WindowsImage.ps1 script and the NanoServerImageGenerator module are now located on the (ISO):\NanoServer\NanoServerImageGenerator folder.
The New-NanoServerImage function has some new parameters like DeploymentType, Edition,… You can see below a huge comment block that contains a comparison of packages differences between TP4 and TP5 as well as details about syntax differences between TP4 and TP5 version of the New-NanoServerImage function.
A small gotcha. I’ve had to specify the Active Directory module version in the DSC configuration because I had multiple versions installed locally. If you’ve got the most up-to-date version, you’ll have to adjust the version I’ve hardcoded (‘2.8.0.0’ in my case).
One last thing, the code below assumes that you’ve downloaded and stored the TP5 ISO file in a directory named TP5 under your current user’s ‘Downloads’ directory.
if (-not(Get-VMSwitch -SwitchType Internal -ErrorAction SilentlyContinue| Where Name -eq 'Internal-Test' )) { | |
# Create an internal switch on Hyper-V | |
($VMswitch = New-VMSwitch -Name "Internal-Test" -SwitchType Internal) | |
# Set a static IP address on Hyper-V switch | |
Get-NetAdapter | | |
Where Name -eq "vEthernet ($($VMswitch.Name))" | | |
Where InterfaceDescription -match "Hyper-V\sVirtual\sEthernet Adapter" | | |
New-NetIPAddress -IPAddress 10.0.0.1 -PrefixLength 24 | |
} else { | |
Write-Information -Msg "Got an internal VM switch named Internal-Test" -InfA 2 | |
Get-NetAdapter | | |
Where Name -eq "vEthernet (Internal-Test)" | | |
Where InterfaceDescription -match "Hyper-V\sVirtual\sEthernet Adapter" | | |
Get-NetIPAddress -AddressFamily IPv4 | |
} | |
# Set the path to ISO | |
$iso = $ExecutionContext.SessionState.Path. | |
GetUnresolvedProviderPathFromPSPath( | |
'~/downloads/TP5/en_windows_server_2016_technical_preview_5_x64_dvd_8512312.iso' | |
) | |
# Integrity check of ISO file | |
# SHA1: 5D2A2795DCA417ED66DFC6B18D733CE2BD09EC63 | |
if ( | |
(Get-FileHash -Path $ISO -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash -eq | |
'E74E7400CD852137A778317CFE0A30D1CB5978DF2ECEC02795E863E50A1EDA8A' | |
){ | |
Write-Information -Msg "Got the correct Technical Preview 5 iso file" -InfA 2 | |
} else { | |
Write-Warning -Message "Don't have the correct ISO of the Technical Preview 5" | |
break | |
} | |
# Mount ISO | |
Mount-DiskImage -ImagePath $iso -StorageType ISO -Access ReadOnly -PassThru | |
$dl = (Get-DiskImage -ImagePath $iso | Get-Volume).DriveLetter | |
If (Test-Path -Path "$($dl):\NanoServer\NanoServerImageGenerator\NanoServerImageGenerator.psm1") { | |
Import-Module "$($dl):\NanoServer\NanoServerImageGenerator\NanoServerImageGenerator.psm1" -Verbose -Force | |
} | |
# Define VM Name | |
$VM = "DC1-test" | |
# Set parent VHD | |
$ServerVHD = (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$VM.vhd") | |
# New TP5: dot source the Convert-WindowsImage function | |
. "$($dl):\NanoServer\NanoServerImageGenerator\Convert-WindowsImage.ps1" | |
# Create parent VHD | |
# Convert the WIM file to a VHD using the loaded Convert-WindowsImage function | |
if (-not(Test-Path -Path $ServerVHD -PathType Leaf)) { | |
Convert-WindowsImage -Sourcepath "$($dl):\sources\install.wim" ` | |
-DiskLayout BIOS -VHDPath $ServerVHD ` | |
-Edition 2 -Verbose:$true | |
} | |
Write-Information -Msg "Created parent VHD: size = $('{0:N2} GB' -f ((Get-item $ServerVHD).Length/1GB))" -InfA 2 | |
# Create child VHD | |
$cvp = (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$VM-child.vhd") | |
$childVHD = New-VHD -Path $cvp -ParentPath $ServerVHD -Differencing | |
# Create a VM Gen 1 | |
New-VM -Name $VM -MemoryStartupBytes 2048MB -NoVHD -SwitchName Internal-Test -Generation 1 | |
# Attach disk | |
Get-VM $VM | Add-VMHardDiskDrive -Path $childVHD.Path | |
# Increase processor count for DC | |
Get-VM $VM | Set-VMProcessor -Count 2 | |
# Mount the VHD | |
$cm = Mount-VHD -Path $childVHD.Path -Passthru | |
$cml = (Get-Disk $cm.DiskNumber | Get-Partition | Where DriveLetter | Select -First 1).DriveLetter | |
# Prepare a Nano VHD with the new script | |
$bdir = Join-Path (Split-Path $iso -Parent) -ChildPath "Base" | |
if (-not(Test-Path -Path $bdir -PathType Container)) { | |
mkdir $bdir | |
} | |
$admincred = Get-Credential -Message 'Admin password of your Nano image' -UserName 'Administrator' | |
if (Test-Path -Path "$bdir\Target") { | |
Get-Item -Path "$bdir\Target" | Remove-Item -Verbose | |
} | |
$nnHT = @{ | |
DeploymentType = 'Guest' ; #NEW TP5: Guest or Host | |
Edition = 'DataCenter' ; #NEW TP5: Datacenter or Standard | |
ComputerName = 'Nano-PXE' ; | |
MediaPath = "$($dl) |
|
BasePath = $bdir ; # The location for the copy of the source media | |
TargetPath = "$bdir\Target\Target.vhd" ; # The location of the final, modified image # \.vhdx?$" pattern. | |
#New TP5 > removed #Language = 'en-US' ; # The language locale of the packages | |
#New TP5 > removed #GuestDrivers = $true ; # Add the Guest Drivers package (enables integration of Nano Server with Hyper-V when running as a guest). | |
AdministratorPassword = $admincred.Password ; | |
} | |
New-NanoServerImage @nnHT | |
# notepad "$($env:Temp)\NanoServerImageGenerator.log" | |
# notepad "$($env:Temp)\NanoServerImageGenerator (DISM).log" | |
# Comparing packages | |
<# | |
Microsoft-OneCore-ReverseForwarders-Package.cab => in TP4 | |
Microsoft-Windows-Server-SCVMM-Compute-Package.cab => in TP4 | |
Microsoft-Windows-Server-SCVMM-Package.cab => in TP4 | |
Microsoft-NanoServer-BootFromWim-Package.cab <= in TP5 | |
Microsoft-NanoServer-Host-Package.cab <= in TP5 | |
Microsoft-NanoServer-SCVMM-Compute-Package.cab <= in TP5 | |
Microsoft-NanoServer-SCVMM-Package.cab <= in TP5 | |
Microsoft-NanoServer-SecureStartup-Package.cab <= in TP5 | |
Microsoft-NanoServer-ShieldedVM-Package.cab <= in TP5 | |
#> | |
<# | |
# Compare the syntax of the New-NanoServerImage function | |
gcm New-NanoServerImage -Syntax | |
# TP3 | |
New-NanoServerImage [[-MediaPath] <String>] [-BasePath] <String> [-TargetPath] <String> [[-ExistingVHDPath] | |
<String>] [[-Language] <String>] [-Storage] [-Compute] [-Defender] [-Clustering] [-OEMDrivers] [-GuestDrivers] | |
[-ReverseForwarders] [[-ExtraPackages] <String[]>] [-ForAzure] [[-ComputerName] <String>] [-AdministratorPassword] | |
<SecureString> [[-DomainName] <String>] [[-DomainBlobPath] <String>] [-ReuseDomainNode] [[-DriversPath] <String>] | |
[-EnableIPDisplayOnBoot] [[-DebugMethod] <String>] [-EnableEMS] [[-EMSPort] <Int32>] [[-EMSBaudRate] <Int32>] | |
[-EnableRemoteManagementPort] [<CommonParameters>] | |
# TP4 | |
New-NanoServerImage [[-MediaPath] <string>] [[-BasePath] <string>] [-TargetPath] <string> [[-Language] <string>] | |
[[-MaxSize] <uint64>] [[-Packages] <string[]>] [[-ComputerName] <string>] [-AdministratorPassword] <securestring> | |
[[-DomainName] <string>] [[-DomainBlobPath] <string>] [[-DriversPath] <string>] [[-InterfaceNameOrIndex] <string>] | |
[[-Ipv6Address] <string>] [[-Ipv4Address] <string>] [[-Ipv4SubnetMask] <string>] [[-Ipv4Gateway] <string>] | |
[[-DebugMethod] <string>] [[-EMSPort] <byte>] [[-EMSBaudRate] <uint32>] [[-MergePath] <string>] [-Storage] [-Compute] | |
[-Defender] [-Clustering] [-OEMDrivers] [-GuestDrivers] [-ReverseForwarders] [-Containers] [-ForAzure] | |
[-ReuseDomainNode] [-EnableEMS] [-EnableRemoteManagementPort] [<CommonParameters>] | |
# TP5 | |
New-NanoServerImage [-DeploymentType] <string> [-Edition] <string> -TargetPath <string> -AdministratorPassword <securestring> | |
[-MediaPath <string>] [-BasePath <string>] [-MaxSize <uint64>] [-Storage] [-Compute] [-Defender] [-Clustering] [-OEMDrivers] | |
[-Containers] [-Packages <string[]>] [-ServicingPackages <string[]>] [-ComputerName <string>] [-UnattendPath <string>] | |
[-DomainName <string>] [-DomainBlobPath <string>] [-ReuseDomainNode] [-DriversPath <string>] [-InterfaceNameOrIndex <string>] | |
[-Ipv6Address <string>] [-Ipv6Dns <string[]>] [-Ipv4Address <string>] [-Ipv4SubnetMask <string>] [-Ipv4Gateway <string>] | |
[-Ipv4Dns <string[]>] [-DebugMethod <string>] [-EnableEMS] [-EMSPort <byte>] [-EMSBaudRate <uint32>] | |
[-EnableRemoteManagementPort] [-CopyFiles <string[]>] [-SetupCompleteCommands <string[]>] [-RamdiskBoot] [-Development] | |
[<CommonParameters>] | |
#> | |
# TP3 version: | |
# New -Defender | |
# New -ForAzure | |
# TP4 version: | |
# Rem -ExistingVHDPath | |
# Rem -EnableIPDisplayOnBoot | |
# Rem -ExtraPackages | |
# New -MaxSize | |
# New -Packages | |
# New -Containers | |
# New -InterfaceNameOrIndex | |
# New -Ipv6Address | |
# New -Ipv4Address | |
# New -Ipv4SubnetMask | |
# New -Ipv4Gateway | |
# New -MergePath | |
# TP5 version: | |
# New -DeploymentType | |
# New -Edition | |
# New -ServicingPackages | |
# New -UnattendPath | |
# New -Ipv6Dns | |
# New -CopyFiles | |
# New -SetupCompleteCommands | |
# New -RamdiskBoot | |
# New -Development | |
# Rem -Language | |
# Rem -ReverseForwarders | |
# Rem -GuestDrivers | |
# Setupcomplete.cmd file | |
$s = @' | |
@echo off | |
:: Define a static IP for the DC | |
netsh int ip set address name="Ethernet" source=static address=10.0.0.10/24 gateway=10.0.0.1 | |
:: Configure the DNS client | |
netsh dns set dnsservers name="Ethernet" source=static address=10.0.0.10 validate=no | |
'@ | |
mkdir "$($cml):\Windows\Setup\Scripts" | |
$s | Out-File -FilePath "$($cml):\Windows\Setup\Scripts\setupcomplete.cmd" -Encoding ASCII | |
# Unattend.xml | |
$unattendDC1 = @' | |
<?xml version="1.0" encoding="utf-8"?> | |
<unattend xmlns="urn:schemas-microsoft-com:unattend"> | |
<settings pass="oobeSystem"> | |
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<UserAccounts> | |
<AdministratorPassword> | |
<PlainText>false</PlainText> | |
<Value>UABAAHMAcwB3ADAAcgBkAEEAZABtAGkAbgBpAHMAdAByAGEAdABvAHIAUABhAHMAcwB3AG8AcgBkAA==</Value> | |
</AdministratorPassword> | |
</UserAccounts> | |
<RegisteredOwner>Tuva user</RegisteredOwner> | |
<RegisteredOrganization>NanoRocks</RegisteredOrganization> | |
<OOBE> | |
<HideEULAPage>true</HideEULAPage> | |
</OOBE> | |
</component> | |
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<SystemLocale>en-US</SystemLocale> | |
<InputLocale>0409:0000040c</InputLocale> | |
<UILanguage>en-US</UILanguage> | |
<UserLocale>en-US</UserLocale> | |
</component> | |
</settings> | |
<settings pass="specialize"> | |
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<ComputerName>DC1-test</ComputerName> | |
<ProductKey>NB4WH-BBBYV-3MPPC-9RCMV-46XCB</ProductKey> | |
</component> | |
<component name="Microsoft-Windows-DNS-Client" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<DNSSuffixSearchOrder> | |
<DomainName wcm:action="add" wcm:keyValue="1">10.0.0.10</DomainName> | |
</DNSSuffixSearchOrder> | |
</component> | |
<component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | |
<Identification> | |
<JoinWorkgroup>test.local</JoinWorkgroup> | |
</Identification> | |
</component> | |
</settings> | |
<cpi:offlineImage cpi:source="wim:c:/iso/sources/install.wim#Windows Server 2012 R2 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> | |
</unattend> | |
'@ | |
$unattendDC1 | Out-File -FilePath "$($cml):\Unattend.xml" -Encoding UTF8 | |
# Get required DSC resource | |
if (-not (Get-Module -ListAvailable -Name xActiveDirectory)) { | |
Find-Module -Name xActiveDirectory -Repository PSGallery | Install-Module -Verbose | |
} | |
# Define environment | |
$ConfigData = @{ | |
AllNodes = @( | |
@{ | |
NodeName = 'localhost'; | |
PSDscAllowPlainTextPassword = $true; | |
PSDscAllowDomainUser = $true ; | |
RequiredFeatures = @( | |
@{ Name = 'DHCP'} | |
@{ Name = 'DNS'} | |
@{ Name = 'WDS'} | |
@{ Name = 'RSAT-DHCP'} | |
@{ Name = 'RSAT-DNS-Server'} | |
@{ Name = 'WDS-AdminPack'} | |
) | |
DCAdminPassword = New-Object pscredential -ArgumentList 'nanorocks\administrator', | |
(ConvertTo-SecureString -String 'P@ssw0rd' -Force -AsPlainText) | |
SafeAdminPassword = New-Object pscredential -ArgumentList 'Password Only', | |
(ConvertTo-SecureString -String 'Azerty@123' -Force -AsPlainText) | |
} | |
) | |
} | |
# DSC config | |
Configuration DCConfig { | |
Param() | |
# Import-DscResource -ModuleName xActiveDirectory | |
# Specify a version if you've multiple ones installed locally | |
Import-DscResource -ModuleName xActiveDirectory -ModuleVersion '2.8.0.0' | |
Import-DscResource –ModuleName 'PSDesiredStateConfiguration' | |
Node localhost { | |
LocalConfigurationManager { | |
RebootNodeIfNeeded = $true; | |
} | |
WindowsFeature ADDS { | |
Name = 'AD-Domain-Services'; | |
Ensure = 'Present'; | |
} | |
foreach ($f in $Node.RequiredFeatures) | |
{ | |
WindowsFeature $f.Name | |
{ | |
Name = $f.Name ; | |
Ensure = 'Present'; | |
} | |
} | |
xADDomain DSDC1 { | |
DomainName = 'nanorocks.local'; | |
DomainAdministratorCredential = $Node.DCAdminPassword | |
SafemodeAdministratorPassword = $Node.SafeAdminPassword | |
DependsOn = '[WindowsFeature]ADDS'; | |
} | |
} | |
} | |
# Compile config into MOF file | |
if (-not(Test-Path -Path ~/Documents/DSC) ){ mkdir ~/Documents/DSC } | |
DCConfig -outputPath ~/Documents/DSC -ConfigurationData $ConfigData | |
# Copy DSC resource | |
$cHT = @{ | |
Path = 'C:\Program Files\WindowsPowerShell\Modules\xActiveDirectory'; | |
Destination = "$($cml):\Program Files\WindowsPowerShell\Modules\xActiveDirectory" | |
} | |
Copy-Item @cHT -Recurse -Force | |
# Copy DSC config | |
Copy-Item -Path ~/documents/DSC/*.mof -Destination "$($cml):\Users\Public\Documents" | |
# Copy original boot image from ISO | |
Copy-Item -Path "$($dl):\Sources\boot.wim" -Destination "$($cml):\Users\Public\Documents" | |
# Copy prepared Nano.vhd | |
Copy-Item -Path "$bdir\Target\*.VHD" -Destination "$($cml):\Users\Public\Documents" | |
# dir "$($cml):\Users\Public\Documents" | |
# Unmount ISO file | |
Get-DiskImage -ImagePath $iso | Dismount-DiskImage | |
# Unmount VHD | |
Dismount-VHD -Path $childVHD.Path | |
Start-Vm -VMName $vm | |
# DCPromo over PowerShell Direct | |
Invoke-Command -VMName $VM -Credential (Get-Credential 'test.local\administrator') -ScriptBlock { | |
Set-DscLocalConfigurationManager C:\Users\Public\Documents | |
Start-DscConfiguration C:\Users\Public\Documents -Verbose -Wait | |
exit | |
} | |
# Post-install | |
Invoke-Command -VMName $VM -Credential (Get-Credential 'nanorocks\administrator') -ScriptBlock { | |
# DHCP configuration | |
# Authorize | |
if (-not(Get-DhcpServerInDC | Where DnsName -eq "$($env:computername).$($env:USERDNSDOMAIN)")) { | |
Add-DhcpServerInDC | |
} else { | |
Get-DhcpServerInDC | |
} | |
# Scope | |
Add-DhcpServerv4Scope -StartRange 10.0.0.20 -EndRange 10.0.0.100 -Name "Nano scope" -State Active -SubnetMask 255.255.255.0 | |
# Activate: done with add-dhcpserverv4scope -state param | |
# WDS | |
mkdir C:\RemoteInstall | |
wdsutil /verbose /progress /initialize-server /RemInst:c:\RemoteInstall # /Authorize | |
wdsutil /start-server | |
wdsutil /verbose /progress /set-server /AnswerClients:ALL | |
Import-WdsBootImage -Path C:\Users\Public\Documents\boot.wim | |
dir C:\Users\Public\Documents\*.vhd | Import-WdsInstallImage | |
} | |
# Create test VM Generation 1 and add legacy network card for PXE boot | |
$testVM = 'Nano-test-pxe' | |
New-VHD -Path (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$($testVM).vhdx") -Dynamic -SizeBytes 127GB | |
New-VM -VMName $testVM -Generation 1 -MemoryStartupBytes 1024MB -NoVHD -SwitchName Internal-test | | |
Remove-VMNetworkAdapter | |
Get-VM -VMName $testVM | | |
Add-VMNetworkAdapter -IsLegacy:$true -SwitchName 'Internal-test' | |
Get-VM -VMName $testVM | | |
Add-VMHardDiskDrive -Path (Join-Path -Path ((Get-VMHost).VirtualHardDiskPath) -ChildPath "$($testVM).vhdx") | |
Start-VM -VMName $testVM |
TP 5 didn’t work with us. I couldn’t join clients to domains. Just going back to TP4. Hope release candidate is more admin friendly
Hi,
Have a look at this video and article:
https://blogs.technet.microsoft.com/canitpro/2016/04/20/step-by-step-deploying-a-domain-joined-nano-server-via-powershell/
I Hope it will help you.
/Emin