Saturday, 12 March 2016

Running .NET Core websites on Nano Server

I've recently been looking into the new Windows Nano Server, which is still in Technical Preview, but is due to launch alongside Windows Server 2016 later this year.

I'm not going to go into too much detail about what Nano Server is and what it's benefits are generally, but for me, as a developer it means I should be able to quickly setup a new virtual web server, running IIS to test websites on. The setup and configuration time should be vastly reduced, as it's a much simpler server. This has a potential to make development and testing of sites easier without relying specific PC setup potentially causing problems.

Since the full .NET Framework isn't available for Nano Server, you can only test websites created for .NET Core.

After investigating how Nano server works and is setup, I've managed to simplify much of the setup process so new virtual servers can be created and ASP.Net Core websites deployed with only a few commands.

To make the process of deploying the Nano Servers and sites simpler, there's a small amount of setup to do on your local machine, but this is just getting files in the right places, there's no installation to do and this only has to be done once to make the creation of the servers much simpler.

Creating the Nano Server image in PowerShell

Setting up the files

To start with, you'll need a copy of the Windows Server 2016 Technical preview ISO image.

Getting the files from the ISO

Double clicking the ISO image in Windows 8.1 or Windows 10 will mount it as a virtual disk drive.
With this mounted, create a new folder on your computer (I'm using c:\nano), and from the NanoServer folder on the disk copy the Convert-WindowsImage.ps1 and NanoServerImageGenerator.psm1 files into your new folder.

Inside your nano folder, create a new folder called ISO, and copy the entire contents of the ISO image into this folder. This step isn't strictly necessary, as you can point the setup process at the mounted ISO directly, but doing this means you can un-mount the ISO disk and you won't need it again.

Creating the Tools directory

In your nano folder, create a new Tools folder. This will hold some additional files we're going to copy to our Nano Server when we create the image.

Get the HTTPPlatformHandler files

Inside the Tools folder, create a new folder named HTTPPlatformHandler. The HTTPPlatformHandler is a module which essentially allows .NET Core sites to run under IIS. You'll need to also install the HTTPPlatformHandler on a non-nano machine first, so you can access a couple of the files to copy to your Nano Server.

After it is installed, locate the following two files and copy them to your new HTTPPlatformHandler folder.
%windir%\System32\inetsrv\HttpPlatformHandler.dll
%windir%\System32\inetsrv\config\schema\httpplatform_schema.xml

Publish the Web Application

You'll need to create a published build of your website to be able to deploy it. To do this, find the folder where your website application source code is stored, and run the following publish command.
dnu publish --runtime dnx-coreclr-win-x64.1.0.0-rc1-update1
This will create a published version of the site using the 64-bit version of the Core CLR. The resulting files will be copied to the bin\output\ folder.

Copy the entire Output folder from it's current location to your Tools folder.


Copy the setup script

There are a few commands which need to be executed on the Nano server the first time it starts up. These commands setup IIS to serve up the ASP.Net Core website, and open the relevant firewall ports. The setup script only needs to be run once.

Copy the script.ps1 script into the Tools folder.

The Tools folder should now contain the HTTPPlatformHandler, and Output folders, and the setup.ps1 script.

The main Nano folder should contain ISO and Tools folders, and the Convert-WindowsImage.ps1 and NanoServerImageGenerator.psm1 files.

If these files are all present, then the initial setup is complete.

Creating a Nano Server VM

With the initial setup complete, the process of creating each new Nano server VM only takes a few commands.

In PowerShell enter the following commands to Import the Image Generator module and generate the VHDX hard drive image. The second command will take a few minutes to run.

This will create a new Nano Server image named Nano1 and install the IIS package, and copy your Tools folder to c:\Tools on the new VM. This command will also set some configuration so that you can connect to the VM remotely via PowerShell.
>Import-Module .\NanoServerImageGenerator.psm1

>New-NanoServerImage -MediaPath .\ISO -BasePath .\Base -TargetPath c:\Nano\Nano1\Nano.vhdx
-ComputerName Nano1 –GuestDrivers -ReverseForwarders
-Packages Microsoft-NanoServer-IIS-Package
-Language en-us -EnableRemoteManagementPort -MergePath .\Tools
Once this is done, the following commands will create a new Hyper-V virtual machine using this VHDX image, and start the VM. The commands set defaults for the memory used by the VM, and the network switch it will use. You can alter the values here, or change them once the machine is created in the Hyper-V manager.
>New-VM -Name Nano1 -Generation 2 -MemoryStartupBytes 256MB -VHDPath c:\Nano\Nano1\Nano.vhdx
-SwitchName "Internal Virtual Switch"

>Set-VMMemory Nano1 -DynamicMemoryEnabled $true -MinimumBytes 256MB -StartupBytes 256MB
-MaximumBytes 2GB -Priority 50 -Buffer 20

>Start-VM Nano1
The first time the VM starts up, it takes a few minutes to get fully up and running. Once it is fully running, all that is left is to find the IP address of the new VM, connect to it, and execute the startup.ps1 script we copied to the VM.

You can do that with the following commands.
>$serverIP = (Get-VMNetworkAdapter Nano1).IPAddresses[0]

>Set-Item WSMan:\localhost\Client\TrustedHosts $serverIP -force -concatenate

>Invoke-Command -Computername $serverIP -ScriptBlock { C:\Tools\Setup.ps1 }
-Credential "~\Administrator"
The last command should prompt you for the Administrator password you first used when you created the VM. Enter this, and the setup.ps1 script should execute on the remote VM.
Once this script has executed, you should be able to view the published ASP.NET Core web application in your browser.

This will be accessible on the same IP address found by running
(Get-VMNetworkAdapter Nano1).IPAddresses[0], using port 8000

You can also view the default IIS startup page by just browsing to the IP address without the port number.

So as you can see, once the initial setup is done, the creation of new Nano servers with your deployed ASP.Net Core web application is very simple, and only takes a few minutes.

To save even more time, and as I'm a fan of automation, I've even condensed these PowerShell commands into a couple of scripts which are available on GitHub.

There are two scripts, Nano-Create.ps1 will create and start the VM, and Nano-Setup.ps1 will run the one-time setup of the VM. Both scripts will prompt for the Nano server name you wish to use.