Ansible | How to get the size of a directory from a linux server

To get the filesystem size, used, available, % used, and what it’s mounted on run this simple ansible script to pull the data.

It uses the df -h command of /var/log. You can modify it for any other directory you like

---
- name: get the size of 
  hosts: all
  tasks:
    - name: get disk space using df -h /var/log
      command: df -h /var/log
      register: var_log_space_raw
    - set_fact:
        folder_size:
        #  "{{ var_log_space_raw.stdout.split()[8,11]}}"
          "{{ var_log_space_raw.stdout_lines}}"
        register: folder_size
    - debug:
        msg: "{{ folder_size }}"

The remarked out line gives the fields for Size and Used%

How To: Windows 2008R2 to 2012R2 upgrade for IIS Servers [CONFIRMED VALID UPGRADE]

How To: Upgrade from Windows 2008R2 to Windows 2012R2 running IIS and Windows Services

We’ve been tasked with upgrading all our 2008R2 Windows Servers to Windows 2012R2. This is due to Microsoft removing support for Windows 2008R2 in January 2020. We’ve performed this upgrade on all our non prod servers first to iron out the issues with 2008 upgrades. I’ll post the errors I ran into when I gather them up but once you go through the steps, it’s VERY easy to upgrade if you follow these simple steps:

Read through this multiple times before you start. There are verification steps you should follow before you start.

2012R2 Upgrade Procedures:

  1. Verify your backup of your server. In a perfect world (which I live in), your 2008R2 will be a virtual machine running on VMware and the backups are automatic the evening before.
  2. Create a local administrator. This is to ensure that if your 2008 upgrade to 2012 doesn’t go well, or it gets removed from the domain, you still have a local user that you’re confident works to get you into the server
  3. Check the C: drive size of the computer. You will need to expand it to have somewhere like 40GB of free space for the upgrade
  4. Check the system log and app logs for errors. You want to have a baseline of any errors occuring on your system so you’re aware of what errors are due to the upgrade to Windows 2012 and what was existing. Please don’t skip this step
  5. Take a snapshot of your server. Yes, you have a backup but a snapshot will ensure that if you need to roll back from Windows 2012R2 back to Windows 2008R2, you can do it immediately. You also won’t have to bother your backup administrator either 🙂
  6. If your servers are part of a load balanced system, Remove it from traffic. Drain and halt the server and verify no traffic is going to it. You should also verify that you can hit the servers websites prior to doing the upgrade as well. We use HOSTS files for this and it works fairly well. Also, if you terminate SSL/TLS at the load balancer, you should also add a VIP with the same SSL/TLS certificate on it so you can mimic your traffic like production. Many people try and hit their server directly and if you’re terminating traffic in front of your server and pass traffic back on port 80, chances are, your browser won’t allow you to do this due to HSTS implemented by your developers. Here is a document explaining HSTS of you need to know more: https://www.globalsign.com/en/blog/what-is-hsts-and-how-do-i-use-it/
  7. Perform the upgrade to 2012R2. Depending on the server’s power (CPU’s and Memory) along with how much data is on it. This upgrade will take around 2 – 5 hours to complete Also, do this from VMware console and NOT from RDP. I repeat… Do this from VMware console and NOT from RDP. If you don’t understand this, you need to before you start this upgrade.
  8. Once the upgrade is complete. Run updates over and over and over until all updates are installed. At this point, if .NET 4.8 isn’t installed, you will get lots of errors running Server Manager and IIS. Things just won’t work correctly. This is to be expected
  9. Perform POST installations of required software. These include:
    1. .NET 4.8 (Download from here: https://docs.microsoft.com/en-us/dotnet/framework/deployment/deployment-guide-for-developers)
    2. HTTP Platform Handler (Download from here: https://www.iis.net/downloads/microsoft/httpplatformhandler)
    3. .net-hosting 2.2.7 (If your sites use this) (Download from here: https://dotnet.microsoft.com/download/dotnet-core/2.2)
    4. URL Rewrite (Download from here: https://www.iis.net/downloads/microsoft/url-rewrite)
    5. Enable the SchUseStrongCrypto property in the Windows registry: If your server does TLS SSL connections outbound to API’s like UPS, Paypal, Braintree or any other site, you will need to force your .NET software to connect using TLS 1.1 or TLS 1.2. To do this, there is a simple registry entry that needs to be added.
      1. Start Regedit and navigate to:
        HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NetFramework\v4.0.30319
      2. Right click in the right pane and create a new DWORD (32-bit) value and name it SchUseStrongCrypto
      3. Enter the Value in the data field of 1 and it should be Hexadecimal. Click on OK
      4. Repeat steps 1-3 for the following WOW6432Node located here:
        HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319
  10. Reboot the server
  11. Check system logs for new errors
  12. Check Application logs for new errors
  13. Verify IIS and Windows services are running
  14. Verify Domain membership is valid. If it isn’t, re-add it to the domain
  15. Perform smoke testing to your server. Again, if you’re load balanced, you would have created smoke vips on your load balancer to point to the new server. Use the HOSTS file entries to smoke test your server.
  16. Request end to end testing from your Software Quality Engineers or Test Engineers
  17. Check the size of your C: drive again. Make sure you’re not out of space
  18. If there are any servers that connect to this server via UNC or via API’s, you should consider rebooting them now. Also, check these servers for connection errors. We’ve seen our servers that connect via \\server\share can’t connect until you reboot them. Do this now!
  19. Once your verification is complete, swap in your new server in your load balancer and pull out the others that haven’t been upgraded. Run and test. A few days.
  20. Remove snapshots when you’re comfortable
  21. Remove the Temporary Admin account that you created
  22. Rinse and Repeat

Conclusion:

I’ve performed this upgrade process for Windows 2008R2 to Windows 2012 many times and these are the gold standard for upgrading a server that is running IIS and Windows Services. Make sure you have a roll back plan and perform that roll back on your development servers FIRST. So, upgrade, test, roll back. Then Upgrade again.

Powershell – How to delete files and folders older than a date

Ok. so this seems pretty simple but sometimes can be daunting figuring out how to actually delete files and folders (recursively). In the script below, all you need to do is define the variables for the directory and how old do you want to go back. Simply change the $directory and $OlderThan variables and kick the script off. Actually, I’ve got a line commented out for you to run this script in “WhatIf” mode. In WhatIf mode, the script simply tells you what it would do if you ran it. Pretty cool!

# Delete items older than a date including subfolders
$directory = 'e:\path\to\what\you\want\to\delete' 
$OlderThan = 365
# To do a Whatif: Get-ChildItem $directory | Where-Object {$_.CreationTime -le (Get-Date).AddDays(-$OlderThan)} | Foreach-Object { Remove-Item $_.FullName -Recurse -Verbose -Force -whatif}
Get-ChildItem $directory | Where-Object {$_.CreationTime -le (Get-Date).AddDays(-$OlderThan)} | Foreach-Object { Remove-Item $_.FullName -Recurse -Verbose -Force}

Upgrade TFS 2017 to TFS 2018 – Walkthrough

How we upgraded TFS from 2017 to 2018 in 3 steps. It was very easy and straight forward but if you haven’t done this before, I hope this post helps.

Upgrading TFS can be very easy if you keep it current or very difficult if you don’t keep it up to date and delay the upgrade until there are many versions between where you are at today and where you want to get to. Luckily, our company has kept our TFS infrastructure up to date every year. Don’t quote me but as I understand it, Microsoft updates TFS quarterly and major updates every year. So, you should plan on updating TFS at least one a quarter. As far as I know, this is the TFS feature timeline: https://docs.microsoft.com/en-us/vsts/release-notes/

To update from TFS 2017 to 2018, here are the steps high level. It was a 3 step process for us. Out infrastructure looks like this: 1 VMWare virtual TFS server and 1 VMWare virtual MS SQL Server with reporting and the TFS Database on it.

  • Disable old work item form (Not really a step. Just check the box)
  • Backup and Upgrade SQL to 2016 SP1
  • Upgrade TFS from TFS 2017 to TFS 2018
  • Upgrade SQL from 2016 SP1 to SQL 2017

Step 1 – Upgrade SQL to to version 2016 SP1

There is usually an overlapping version of SQL between TFS versions. Microsoft has designed TFS this way to easily upgrade to new versions and keep a common Database version on the back end. For us, when we started looking at TFS 2018, we found that we were on SQL 2012 (I believe) and we needed to upgrade to SQL 2016 SP1. Both TFS 2017 and TFS 2018 support SQL 2016 SP1. This was our first step. To do this, here was our procedure. This took from start to finish almost 2 hours:

  • Shut down TFS Server
  • Snapshot TFS Server while off
  • Backup existing TFS databases manually (We didn’t use TFS to do the backup)
  • Once the snapshot and databases were backed up, We essentially had a backout plan (Which we used twice until we got this right. I won’t go into detail here but it worked flawlessly).
  • Shutdown SQL Server and take a VMWare snapshot of it
  • Turn on SQL Server
  • Update compatability mode of all databases to 2016
  • Turn on TFS
  • Update SQL 2016 configuration of the new 2016 features
  • Verify that upgrade was successful

Roll back of SQL upgrade plan

In case the SQL upgrade didn’t go well…

  • Turn off TFS and revert snapshot
  • Restore SQL Manual backups
  • Turn on TFS

Step 2 – Upgrade TFS from 2017 to 2018

This was a bit confusing as there was TFS 2018 RTW and TFS 2018 Update 1 RC. Please make sure you understand the difference here. RTW means “Release to Web” and RC means “Release Candidate” Unless you’re living on the edge, I wouldn’t upgrade your production TFS to a RC version. We went to the RTW version.

We waited 1 week between upgrading SQL to 2016 and upgrading TFS to 2018. This was to ensure we were only making one change at a time. This will ensure you are sure what the procedure you performed is the issue. We did not have any issues after upgrading SQL to 2016 before our TFS 2018 upgrade.

This is where we had problems. First, I couldn’t find anywhere on the web that someone write instructions for the actual upgrade from TFS 2017 to TFS 2018. Since there were no clear instructions, I decided to write these 🙂 Also, our steps listed below worked like a charm. Our restore process had to be executed twice. We were not sure why our data tier couldn’t authenticate the account that was performing the upgrade, we backed out. After we determined the correct rights, We proceed without issues. So you know, the account that you’re using to perform the upgrade MUST be a TFS administrator AND at lease “ServerAdmin” role. We gave my account temporary SA rights to perform the upgrade. Then removed them when done.

  •  Shutdown TFS and take a VMWare snapshot
  • Perform a SQL backup (This is a SQL backup) and should be done following best practices. our SQL administrator performed these steps.
  • Power on TFS
  • Perform TFS Update
  • Test TFS

Backout plan to roll the failed TFS 2018 upgrade back to TFS 2017

  • Shut down TFS
  • Use VMWare snapshots to revert to the snapshot you took above
  • Restore the 2017 SQL backup
  • Turn on TFS
  • Test

Step 3 – Upgrade SQL from SQL 2016 to 2017

As of this writing, we haven’t upgraded SQL from 2016 to 2017. Here are our procedures as of this writing. When we complete it. I’ll update this blog post (I hope).

  • Shut down TFS
  • Snapshot TFS
  • Backup existing TFS user databases manually before SQL upgrade
  • Stop SQL services
  • Take a VM snapshot of SQL server
  • Start SQL services
  • Upgrade the comparability mode of all databases to 2017 Update SQL 2016 configuration to take advantage of new 2017 features
  • Turn on TFS
  • Verify successful upgrade (Both in TFS and SQL)

How to Create TLS Certificates using OpenSSL with wildcards in the SAN

UPDATED 2/4/2021
UPDATE 4/16/2021 – Added commands to

Below are the basic steps to use OpenSSL and create a TLS certificate request using a config file and a private key. You will first create/modify the below config file to generate a private key. Then you will create a .csr. This CSR is the file you will submit to a certificate authority to get back the public cert. Once you have the private key and the resulting public certificate, you will chain them all together (including the CA’s public certs) to create a certificate that you will install on a linux server, load balancer or even convert it to a .pfx file for windows. I’ve been doing this for years and it works very well.

Some gotcha’s… If you are creating wildcard certificates, you always have to have the root domain and the *.domain in the certificate.
For example, if you wan to create a certificate with domaina.com and domainb.com, and support all names like www.domaina.com, abc.domaina.com AND domaina.com, you need to have both the *.domaina.com and domain.com in the SAN area of the config file. Look carefully at the file below. you will see both in it.

Create a config file

Modify this config file to use to create your certificate.

## Start of File
# OpenSSL configuration to generate a new key with signing requst for a x509v3
# multidomain certificate
[ req ]
default_bits = 2048
default_md = sha256
default_keyfile = key.pem
prompt = no
encrypt_key = no
# base request
distinguished_name = req_distinguished_name
# extensions
req_extensions = v3_req
# distinguished_name
[ req_distinguished_name ]
countryName = "US" # C=
stateOrProvinceName = "Minnesota" # ST=
localityName = "Your City" # L=
organizationName = "Your Company" # O=
commonName = "domain.com" # CN=
# req_extensions
[ v3_req ]
# The subject alternative name extension allows various literal values to be
# included in the configuration file
# http://www.openssl.org/docs/apps/x509v3_config.html
subjectAltName = DNS:*.domain.com,DNS:domain.com,DNS:domainb.com,DNS:*domainb.com # multidomain certificate
## End of File

Generate a key for the new certificate.

You could re-use a key but that’s not so secure so always generate a new key every time!

openssl genrsa -out <private key file name>.key 2048

Create the CSR request.

Use the .cnf you created in step 1

openssl req -new -key <private key file name>.key -config <DomainName>.cnf -out <csr file name>.csr

Submit your CSR

Open your .csr file in a text editor (Never use Notepad) and copy the contents. Then submit it to an authority (internal for our sake) and then down load your certificate as a base64. If you are going to submit it to an online authority, use a repeatable authority like DigiCert. Don’t use Thawte or Symantec. They are going away soon.

Merge your public key

Merge your public key, intermediate cert, root cert, and private key (in that order) and save it as a .pem file

NOTE: if this is for a public website, you don’t need to add the root cert to the chain. The browsers computers should have that and it’s trusted more if you leave the root out.

Should look like this (replace your public key and private keys at the top and bottom)

-----BEGIN CERTIFICATE-----
### Replace me with the certificate you received from the authority ###
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
### INTERMEDIATE CERT HERE ###
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
### ROOT CERT HERE ###
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
### replace me with your .key file ###
-----END RSA PRIVATE KEY-----

If necessary, convert your cert from PEM to PFX

If you need to convert your cert from .PEM to .PFX. If you dont need a friendlyname, omit that:

openssl pkcs12 -export -out CERTNAME.pfx -in CERTNAME.pem -name "friendlyname"

Copy your certificate over to your server and install it. You can either install it using the Certificates MMC or import it into IIS. If you are using a .pem file and working on linux, you can import the cert into your load balancer of linux server of choice.

How to set screen saver lock screen local policy on a non domain server

After being tasked to set up a screen saver password or a lock screen for inactivity on servers that are not joined to a domain, I decided to post this so it’s easier to find when others are searching for this.

To be PCI compliant, this is a requirement for any servers that are in-scope for your payment system.

For Microsoft Windows 2008 and 2012, it is easy to do but you have to set all three settings below for it to become active. This will enable a screen saver policy that locks your screen after a set time of inactivity. For PCI controlled servers, this is a requirement and must be less than 15 minutes.

This is easily done if the computer is part of an Active Directory domain but not as easily done if they are members of a workgroup.

How to Set the Screen Saver Lock Screen

The procedure is to open MMC snapin and add the Local Computer Policy snapin. To do this, click on the Windows button, and then simply type in MMC. For Windows 2012, select MMC snapin (mmc.exe) and not the Embedded Lockdown Manager.

Then navigate to User Configuration >> Administrative Templates >> Control Panel >> Personalization (as seen in the graphic I’ve attached).

Set the following settings:
Enable Screensaver: Enabled
Password protect the screen saver: Enabled
Screen saver timeout: Enabled with a value of 600

No need to reboot. Just log out and back in and the setting will be applied. Then wait 10 minutes to verify that your screen locks.

Here is a graphic of what needs to be set:

How to set a local policy to activate the lock screen on servers.

How to add a AD CA certificate to Windows 2012 RDP for PCI compliance

For PCI compliance, a requirement is to have RDP port 3389 connect with TLSv1.1 or TLSv1.2 and have the certificate have the same name as the server. Most servers issue self signed certificates which is not acceptable with PCI compliance.

To fix this, you have to re-issue new certificates from a trusted CA. You should use an internal CA within your company to avoid the cost of purchasing and maintaining certificates for RDP services.

How to issue and import a certificate:

Issue a certificate from your Root CA. You can go through the process I’ve outlined to create a certificate using OpenSSL

Import the certificate to the store using MMC and add the Certificates snapin

Move the Root and Intermediate to the correct store

Get the SHA1 thumbprint off of the certificate by opening up the certificate, go to the “Details” tab and scroll down to below the Thumbprint algorythm and selecting the “Thumbprint”
highlight the thumbprint
copy the thumbprint into a Command Shell and remove the spaces and the hidden character at the beginning.

Put the thumbprint in this command and run it on the server

wmic /namespace:\\root\cimv2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="<EnterSHA1ThumbprintHere>"

Restart Remote Desktop Services Note: this will disconnect you from your RDP session.

Log back in and you should not be prompted.

Retest by scanning your computer with Nessus or another approved scanning software.

How To: Powershell Get Local Administrators and Active Directory Nested Groups – SOX

For the past few years, I’ve been tasked with ensuring that our in-scope servers for Sarbanes-Oxley (SOX) have the correct users and groups in them. Before we would have to screen shot the members of the local admins and all the groups that are in the local admins. I decided to take the time to create a script that gets the local admins of the server and write the output to a transcript file.

Script to get Server Local Administrators:

I named the script Get-ServerLocalAdministrators:

Get-ServerLocalAdministrators.ps1 -domain domain -computername computername

The steps the PowerShell script goes through are:

  • Get domain and server
  • Import PowerShell Modules
  • Get Date and Time
  • Get the working directory
  • Convert the domain and computername to upper and lower for pattern matches
  • Start the transcript in the current directory and use some variables for naming the transcript
  • Get the server’s local administrators object using Get-WmiObject and a where cause for the group component
  • Get the members of the local admins and determine if it’s a user or group.
  • If user, put it in the transcript and tag the user as uer
  • If Group, put the group in a variable to loop through later
  • In the transcript, I’m doing a Write-Host to tag each group. If the group has a sub group, (nested group), then put that in another variable to loop through that as well

Since we have Group Memebers that are cross domain, I had to include the -Server paramater get the object’s distinguished Name and use that for -Server.
The only line you have to change in this script (because I was lazy) is to change line 32 to your domain. So, if your server FQDN is server.subdomain.domain.com you would call this “Domain.com” if it was simply “server.domain.com” then you would call this “com”.

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True,Position=1)]
        [string]$domain,
    [Parameter(Mandatory=$True,Position=2)]
        [string]$computername
    )

# Importing Modules
if (! @(get-module -name ActiveDirectory).count) 
{
	import-module ActiveDirectory
}

if (! @(get-module -name Microsoft.Powershell.Host).count) 
{
	import-module Microsoft.Powershell.Host
}

if (! @(get-module -name Microsoft.WSMan.Management).count) 
{
	import-module Microsoft.WSMan.Management
}

# Variables
$TimeStamp = get-date -Format yyyyMMddHHmmss
$workingDirectory = (Resolve-Path .\).Path
$ComputerNameLower = $computername.ToLower()
$DomainLower = $domain.ToLower()
$ComputerNameUpper = $computername.ToUpper()
$DomainUpper = $domain.ToUpper()
$parentDomain = "domain.com"
[string]$strcomputer = $computername

Start-Transcript -Path $workingDirectory\AREA6_$DomainUpper.$ComputerNameUpper.$TimeStamp.txt -force

# Getting the Local Admins Group
$admins = Get-WmiObject win32_groupuser –computer "$computername.$domain.$parentDomain"
$admins = $admins | where {$_.groupcomponent –like '*"Administrators"'} 
[array]$DomainGroups = @()
[array]$IsGroup = @()

Write-Host "----------------------------------------------------------------"
Write-Host $computername "Local Administrators"
Write-Host "----------------------------------------------------------------"

# Getting Members of Local Admins
$admins | ForEach-Object {  
    $_.partcomponent –match "Win32_(.+).+Domain\=(.+)\,Name\=(.+)$" > $nul  
    $matches[2].trim('"') + "\" + $matches[3].trim('"') + " Type: " + $matches[1]
    # Finding if Local Administrator member is a Domain Group and adding it to $DomainGroups
    $String = 'Win32_Group.Domain="'+$DomainUpper+'"'
    if ($matches[0].Contains($string)){
        $DomainGroups += ($matches[3].trim('"'))
        }
    }

# Looping through all the Domain Groups in the Local Admins and getting their members
foreach ($DomainGroup in $DomainGroups){
    Write-Host "----------------------------------------------------------------"
    Write-Host "$DomainGroup"
    Write-Host "----------------------------------------------------------------"
    $Members = Get-ADGroupMember $DomainGroup -server "$DomainLower.$parentDomain"
    # If a group member is another group write it to $IsGroup so we can get them later
    foreach ($member in $members){
        If ($member.objectclass -eq "user"){
            Write-host ($member.name)" Type:"($member.objectClass)
            }
        elseif ($member.objectclass -eq "group" -And $IsGroup -notcontains $member){
            Write-Host ($member.name)" Type:"($member.objectClass)
            $IsGroup += $member
            }
        elseif($member.objectclass -eq "group" -And $IsGroup -contains $member){
            }
        }
    }
# As stated above, getting the members of nested groups
foreach ($item in $IsGroup){
    Write-Host "----------------------------------------------------------------"
    Write-Host $item.name
    Write-Host "----------------------------------------------------------------"
    $DN = $item.distinguishedName
    $objectDomain = ((($DN -replace "(.*?)DC=(.*)",'$2') -replace "DC=","") -replace ",",".")
    $members = Get-ADGroupMember $item -server $objectDomain
    foreach ($member in $members){
        write-host $member.name" Type:"$member.objectClass
        }
    }

Stop-Transcript

Limitations: This script only loops through to levels of Active Directory groups on the server. So, if you have nested groups more than that, it won’t continue deeper. I’m going to rewrite this to do full recursion in a function so you can look for that post in the future.

Adding Folder Permissions to IIS_IUSRS via Powershell

For you scripting guys that want to automate everything, For website deployments, you can modify your permissions using the NTFSSecurity Module. This is a simple way to modify ACL’s with powershell. Much easier to use the NTFSSecurity module…

First download the module from here: https://ntfssecurity.codeplex.com/

I would put it in your modules directory on the server. Then import the module with Get-Module -ListAvailable and Import-Module NTFSSecurity.

Now, on to the simple and easy code:

Add-NTFSAccess -Path 'C:\SomeFolder\SubFolder' -Account BUILTIN\IIS_IUSRS -AccessRights Read

You can also use the following AccessRights. Actually, you should be able to get any name as the parameter but these are the most common:
Modify
Read

Also, as a note, IIS_IUSRS is a special internal group that you shouldn’t/can’t prefix with the computer or domain name.

For the Network Service or IUSR, you have to use “NT AUTHORITY\NETWORK SERVICE” OR “NT AUTHORITY\IUSR”

Install / Setup Docker on Windows Server 2016

I’ve been working on installing Docker on Server 2016. Here are the steps I’ve followed and some issues I ran into:

First, you have to have Windows Server 2016.

Run Powershell as Administrator (Right click on PowerShell and RunAs Administrator) – yes, you also have to be a local administrator of the box.

Commands in order:

Install-PackageProvider containerimage -Force

Then you want to see what operating system container images are available:

This step wasn’t in the instructions I was following but is necessary and was raised on the GitHub site as well. The server will reboot after the below command is executed. After it reboots, you need to run the command again. Ugh. I thought it was done and tried to install Windows Server Core and it failed after about 30 minutes.

This is installing and then enabling the Docker Container feature on Windows

Enable-WindowsOptionalFeature -Online -FeatureName Containers

As stated above, run the command again. Once done, it will actually tell you that it’s Online and True:

Install Windows Server Core Container Image

Install the WindowsServerCore Container Image by typing the following command below. This does take a while as it downloads Windows Server Core Container Image:

Install-ContainerImage -Name WindowsServerCore

I went to have a bite to eat, took a nap, Surfed Reddit for a while, went to the bathroom and then it was done!

You can check if the image was downloaded by running looking in the directory:

ls c:\programdata\Microsoft\windows\images

The output should look like this:

 

Now we’re going to install Docker in Windows Server 2016

First, you want to download the Update-ContainerHost.ps1 powershell script. Here is the command:

Invoke-WebRequest https://aka.ms/tp5/Update-Container-Host -Outfile Update-ContainerHost.ps1

Run the command. I actually ran this to download the script while the above install of the Windows Server Core was running:

To be continued…