Programming Blog

Jeremy Morgan

Mostly Coherent Ramblings of a Silicon Forest Software Developer

Comparing and Syncing IIS Configurations

Author: Jeremy Morgan

Imagine you’re an administrator at ACME Widgets and it’s time to upgrade your IIS server. You’ll just copy over some folders and point the DNS to the new server and be done right? If you’ve ever done this before you know that isn’t the case. The new IIS server needs to be configured identically to the old one or you’re going to have problems, and you don’t have time for problems.


Can’t We Just Move This from One Server to Another?

As you stare at the Server Manager on the new machine you plan your next move. Your old i3 server that’s worked for years has all of your websites and applications on it. The shiny new XEON machine is just waiting to go into service. It has Windows 2016 on it and ready to go.

To do this transfer you’ll need to:

  • Install IIS and the necessary modules
  • Find a way to match the old server’s configuration
  • Create websites and applications

In this article we’re only concerned with the first two parts, which is making sure IIS is installed and configured like it was on the first server. If you copy over the new sites and simply install IIS and fire it up, it…..might work. Unless you have the most basic websites running, it won’t.

There are other problems moving from one server to another. What if the operating system is different? It probably will be. Though IIS remarkably good at forward compatibility the UI changes with each release, so if you’re staring at IIS manager to find the settings, it will likely be different.


Internet Information Services (IIS) Manager


So you can look through all these settings and try to figure out which modules are installed, which aren’t etc. Or maybe you can go into server manager to the Add Roles and Features Wizard and try to decipher it from there:


Add Roles and Features Wizard


This is certainly one way to figure out what’s installed. In fact I’ve done it a few times this way years ago when I first started out with this stuff. You won’t have to do this, because we’re going to look at a much better way to compare IIS Installations and replicate servers.


Getting the IIS Configuration

We need to copy the IIS installation configuration from ALPHA which is the existing server to BRAVO which is the new one.

Since you’re a Windows DevOps professional (or would like to be) you’re going to use PowerShell for this task. It’s extremely easy to get the current IIS installation information from a PowerShell prompt. Type in the following:

1
Get-WindowsFeature -Name Web-*

Get-WindowsFeature will output every windows feature and it’s installation status, and by specifying a name of Web-* we’ll get all the features that pertain to IIS and Web Services. Our ALPHA server currently looks like this:


Managing IIS with PowerShell


This shows our features and whether they are installed on the current server. We can filter it down a little so it only shows the features that are installed instead of all of them:

1
Get-WindowsFeature -Name Web-* | where installed

By using the pipe and filtering for “where installed” we only show the modules that are currently installed.


Managing IIS with PowerShell


This is a quick way to spot check what we have installed. When we run this on BRAVO, the new server, we can see that IIS isn’t installed at all.


Managing IIS with PowerShell


So now we have a clear idea of the IIS Configuration, how it’s setup on ALPHA, and how it’s set up on the new server (not at all).


Comparing the IIS Servers with a Deterministic Method

So you can visually see the differences in your old server and your new server with the commands we just ran. Now you just have to remember what’s installed on the first one and carry it over to the new server. But you’ve been really digging into the DevOps thing and keep hearing about making things deterministic. Saying it looks “close enough” won’t cut it, you need to prove it. Here’s a method I’ve come up with that works well for this.

We’re going to use one of the oldest methods in the book: the diff.

So you run the following command on your ALPHA server, which again is the existing server we want to replicate:

1
Get-WindowsFeature > ALPHA.txt

What this does is pipe the output from Get-WindowsFeature to a text file named ALPHA.txt. Then we’ll copy that text file to our workstation.

Now on the BRAVO server, do the same thing:

1
Get-WindowsFeature > BRAVO.txt

Now we’ll copy that file to our workstation as well.

Now we’ll run a simple diff on those two files, I’m using KDiff3 for this:


Managing IIS with PowerShell


Now you can clearly see the differences in the two configurations and you can prove it, keeping the DevOps gods happy.


Syncing up Settings in a Repeatable Way

Now that we know exactly what the differences are in our configuration, we need to set up the new server with those settings so we can move our websites and applications over.

Again we’re going to do this in a Devops friendly fashion. You can just install all the items in the diff and be done with the task. But again we want to do this in a deterministic and repeatable way. We want to know for certain it’s the same and be able to do it multiple times. Who knows how many more times you’ll have to change servers or move to the cloud. Wouldn’t you rather have a script to do this for you?

So we’ll take all the items from our DIFF and put them into a list. We are only interested in the NAME of the feature, found here:


Managing IIS with PowerShell


We have our list and it looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Web-Server
Web-WebServer
Web-Common-Http
Web-Default-Doc
Web-Dir-Browsing
Web-Http-Errors
Web-Static-Content
Web-Health
Web-Http-Logging
Web-Custom-Logging
Web-Performance
Web-Stat-Compression
Web-Dyn-Compression
Web-Security
Web-Filtering
Web-App-Dev
Web-Net-Ext45
Web-ASP
Web-Asp-Net45
Web-ISAPI-Ext
Web-ISAPI-Filter
Web-Mgmt-Tools
Web-Mgmt-Console
NET-Framework-45-ASPNET

So, that’s a lot to Install right? It would be far easier to just build a script to do this, so you can just run it any time you need to set up a server with this configuration. In the the last tutorial we learned how to use DISM to create a repeatable IIS installation but for fun, we’ll do something a little different.

So let’s create a PowerShell script.

At the top, I’ll put in a string array of all these features:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$features = @(

    "Web-Server",
    "Web-WebServer",
    "Web-Common-Http",
    "Web-Default-Doc",
    "Web-Dir-Browsing",
    "Web-Http-Errors",
    "Web-Static-Content",
    "Web-Health",
    "Web-Http-Logging",
    "Web-Custom-Logging",
    "Web-Performance",
    "Web-Stat-Compression",
    "Web-Dyn-Compression",
    "Web-Security",
    "Web-Filtering",
    "Web-App-Dev",
    "Web-Net-Ext45",
    "Web-ASP",
    "Web-Asp-Net45",
    "Web-ISAPI-Ext",
    "Web-ISAPI-Filter",
    "Web-Mgmt-Tools",
    "Web-Mgmt-Console",
    "NET-Framework-45-ASPNET"
)

This is a good list that we can come back and modify if needed later down the road. We’ll just loop through it to install everything using a foreach loop:

1
2
3
foreach ($feature in $features){
    # do something
}

Inside that foreach loop we’ll do something like the following:

1
2
3
4
5
6
foreach ($feature in $features){
    if(Get-WindowsFeature -Name $feature | Where-Object {$_. installstate -ne "installed"}){
        Write-Output "Feature $feature not installed. Installing"
        Install-WindowsFeature -Name $feature
    } 
}

Now as we can see here, we loop through each feature in the list, and say if the feature is not installed, we’ll write out a message saying it isn’t installed, and then install it. If the feature is not installed, we’ll do nothing.

This is an example of an idempotent script. This is another key DevOps concept, it means we can run this script over and over and it should do the same thing each time. The expected state (all of these features installed) should be the same no matter how many times we run it.

Once we run the script on our BRAVO (new) server, it looks like this:


Managing IIS with PowerShell


Now we should have all the same features installed. We run another Get-WindowsFeature check and diff, and see the following:


Managing IIS With PowerShell


Success! You have now compared the two configurations, determined what you needed to install and scripted it. Now you can take this script and run it on any new server that will host your websites and applications.


Conclusion

You’re now once again the hero of the ACME Widgets Information Services department. You had an existing IIS server that was running our websites and applications, and duplicated the configuration to a new server. It’s the same concept we covered in the previous article on DISM, only this time we took it a step further by doing a deterministic comparison, then using PowerShell instead of a batch file. This is a more advanced and extendable way.

We used some patterns and methods here that fit in well with DevOps practices:

  • Deterministic - We didn’t guess at what the configuration differences were, we proved it
  • Automated - Rather than jumping in and installing things we scripted it
  • Idempotent - We created a repeatable process that produces the same results every time we do it.

This is important stuff, and will take to the next level of Administrator. I cover this topic in detail and many similar operations in my course Installing and Configuring IIS Servers on Pluralsight. It covers many ways you can make your life easier as an Administrator.

Questions? Comments? Yell at me on Twitter!