How Do I Set Up A .Net Core WebListener With SSL?

I've been doing a lot of research on Service Fabric and Windows Docker Containers lately. These are natural platforms for .Net Core, which added another learning item to my list: .Net Core.
As a result, I set out to get a .Net Core WebListener web server up and running on Windows Server Core 2016. I chose Server Core because it emulates the kind of environment you'll be faced with when running on Docker or Service Fabric, which is essentially a bare bones, no UI environment.

I'm not attempting to teach you Hyper-V, Docker, or how to get around in Server Core as they are big subjects by themselves. If you are afraid of the command line, you should not be here until you do some prerequisite learning.

Objective: Set up a .Net Core WebListener Server with SSL on Windows Server Core 2016

Create Your Server Core Host

Start by installing Server Core 2016 in a VM. You could use a Docker container too if you're so inclined.

Create Your SSL Certificate

Log onto the new Server Core machine. At the administrative command prompt, type
start powershell

Issue a PowerShell command to to create a self-signed cert (use your server's DNS name)
New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName server0.contoso.com
You'll need the cert thumbprint a little later. Mine was: C74235968895ECA9C9D50703D30CE17A7D3AEEFF

Register Your App With HTTP.SYS

Issue a PowerShell command to create a GUID
New-guid
You'll need this Guid to use as an AppId later. Mine was: 921328e8-5cdf-4b7f-a3cc-4e50147d1521

Switch back to your original administrative command prompt and issue these commands to create the Url ACLs (80 and 443)
netsh http add urlacl url=https://+:443/ user=Users netsh http add urlacl url=https://+:80/ user=Users

While still in the same command prompt, issue a command to associate the cert thumb print and App Id (created above) with port 443
netsh http add sslcert ipport=0.0.0.0:443 certhash=C74235968895ECA9C9D50703D30CE17A7D3AEEFF appid={921328e8-5cdf-4b7f-a3cc-4e50147d1521}
Note: If you run the above from PowerShell rather than cmd, you may need to escape some characters to get it to work

Open the Firewall Web Ports

Switch to your PowerShell prompt
Issue a PowerShell command to open 80 and 443 in the Windows Firewall. This will allow HTTP(S) traffic to WebListener.
New-NetFirewallRule -DisplayName 'HTTP(S) Inbound' -Profile @('Domain', 'Private') -Direction Inbound -Action Allow -Protocol TCP -LocalPort @('80', '443')
I opened both ports because I wanted to test both clear HTTP and HTTPS. I also chose to restrict the ports from being open on the Public firewall profile by specifying Domain and Private.

Install .Net Core

Issue a PowerShell command to download .Net Core to the machine
Invoke-WebRequest "https://go.microsoft.com/fwlink/?LinkID=827524" -OutFile .\DotNetCoreSetup.exe -UseBasicParsing

In the same PowerShell prompt, install .Net Core using the following
.\DotNetCoreSetup.exe /install /quiet /log .\log.txt

.Net Core will silently (and very quickly) install. I chose silent because this is not a full GUI machine. When the install finishes, you should see several text log files in the directory you issued the above command from. Even though you're on Server Core, Notepad still works and you can use it to inspect the logs and satisfy yourself that you had a successful install.
Once satisfied, I really recommend you restart the machine with this PowerShell command
Restart-Computer
You don't need to restart, but it is a pain if you don't let the machine pick up the environment changes.

Create a Web Application to Serve

Now we need an app. The easiest thing to do is to adapt the template web app.
Step 1 - From your Server Core console, enter the following to create the template web app:
mkdir aspnetcoreapp cd aspnetcoreapp dotnet new web

Step 2 - Modify aspnetcoreapp.csproj file to include the WebListener package reference right under the Microsoft.AspNetCore package reference. Notepad is available on Server Core by typing 'notepad' at your command prompt. Your csproj should look like this:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp1.0</TargetFramework> </PropertyGroup> <ItemGroup> <Folder Include="wwwroot\" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore" Version="1.0.3" /> <PackageReference Include="Microsoft.AspNetCore.Server.WebListener" Version="*" /> </ItemGroup> </Project>

Step 3 - Modify Program.cs by replacing the WebHostBuilder initialization statement with this:
var host = new WebHostBuilder() .UseWebListener() .UseUrls("https://+:80", "https://+:443") .UseStartup<Startup>() .Build();
NOTE: Make sure the above URL strings "https://+:80" and "https://+:443" match the URL strings used in the ACLs you created with netsh earlier in 'Register Your App with HTTP.SYS'.
If you don't, you may receive a 503 Service Unavailable from the web server.

Step 4 - From your Server Core console, enter the following to restore the packages and run the server:
dotnet restore dotnet run

Step 5 - Browse to your Server Core machine name from another machine on the network, using either HTTP or HTTPS. In my case, the URLs to browse to were the same as the DnsName for my cert and machine:
https://server0.contoso.com/ https://server0.contoso.com/

You should have a working SSL enabled WebListener server running on Windows Server Core 2016.
Now go and brag about your .Net Core, bare metal, headless, command line skills.

References ASP.Net Core Docs Windows Server 2016 WebListener repository WebListener ASP.Net Core Docs URL routing/registration/pattern matching behavior Service Fabric Documentation Containers for Windows