Programming Blog

Jeremy Morgan

Mostly Coherent Ramblings of a Silicon Forest Software Developer

Comparing and Syncing IIS Configurations

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!

Using DISM to Create a Repeatable IIS Installation

Repeatable installs are all the rage in Devops these days. As developers we have this “automate everything” mentality, and for good reason. In this article I’ll show you how you can do that with IIS installation as well. There’s no reason to go hunting and pecking around the GUI every time you need to do this. This is the just one of many ways to automate IIS installs, which I’ll be covering in the next few weeks.

I also cover this in depth in my latest Pluralsight course on Installing IIS.

Why would I ever need to do this?

"How To Create Repeatable Installs in IIS"

Most of the time administrators probably have a task like “throw IIS on the server and make sure the application works” and they do just that. That’s how I used to do it too. I was working on a project many years ago that required us to spin up VM servers on a virtual network as a “stack”.

This stack was a small snapshot of our production network, so to make sure our software worked with everyone’s updates, we had to build a new stack a few times a week.

A few times a week, we’d have to click through the GUI install and remember each box to check. Yeah, you can get good at it but it’s a waste of time.

Naturally I had to find a way to automate it, and break out some PowerShell. You do this, because you save time that can be spent doing fun stuff. So let’s learn how to create automated, repeatable IIS installations.

Getting Started

So you’re an administrator for ACME Widgets and you want to create a custom install of IIS and make it automated. You create a new server and are ready to go.

To find out if IIS is installed, we’ll run a command called DISM. DISM is a tool to build and service Windows images, it’s mostly used to create and maintain images for Virtual Machines, it’s extremely powerful, but we’ll cover that in a future article. For now we’ll use it to check features on the machine.

Open up a command prompt, and run the following command:

1
dism /online /get-featureinfo /featurename:IIS-WebServer 

As I run it on my virtual machine, I can see that IIS is not yet installed.

Repeatable Installs in IIS

You can also find a list of everything that’s enabled with this command:

1
DISM /online /get-features /format:table | find "Enabled"

And you’ll see something like this:

Repeatable Installs in IIS

by piping the output into find and searching for enabled we can get a full list of features that are already enabled on the server.

We can also quickly see if a single feature is enabled like we did before, but piping the results into find and checking the state:

1
dism /online /get-featureinfo /featurename:IIS-WebServer | find "State"

Repeatable Installs in IIS

Here we can quickly and clearly see IIS is not installed.

Creating a Batch File

So now that we know we can get this type of output, we’re going to build a little batch file to do it, and we’ll run the command a little different this time. This is pretty light programming, but it will be a set of tests to see if particular items are installed.

Type in notepad webinstall.bat and let’s create a batch file. Add the following:

1
2
@ECHO OFF
dism /online /get-featureinfo /featurename:IIS-WebServer | find "State : Disabled" > nul

We’re typing in dism, online, get-featureinfo, featurename, then piping that to find. We’ll look for state saying disabled, and if that phrase is found, that means IIS is disabled, or not installed. That will change our error level, which we’ll add next.

1
2
3
if %ERRORLEVEL% == 0 (
echo "IIS Web Server is not installed"
)

If our error level is set to zero, that means the phrase state enabled was found in our output. Let’s test it out.

Repeatable Installs in IIS

Now in our batch file we can see that IIS is not installed, and we have a block inside the statement to install IIS.

We could do that with a block of code like this:

1
2
3
4
if %ERRORLEVEL% == 0 (
echo "IIS Web Server is not installed"
dism /online /enable-feature /featurename:IIS-WebServer /all
)

This is the first basic IIS install script. At the end we can put a check to see if it’s installed:

1
dism /online /get-featureinfo /featurename:IIS-WebServer | find "State"

The finished batch file is available here.

Running the Script

Now after we run the file, it should do the following set of steps:

  • Check to see if IIS is installed
  • If it’s not installed, install it
  • Check again to see if it’s installed.

So the end result is, if IIS is installed it does nothing, if it’s not installed then adds it, and looks like this:

Repeatable Installs in IIS

This small, simple script can make sure IIS is installed on the machine. And it’s repeatable.

Customizing the Install

Of course as you’re building your script, you may need to install other IIS modules, chances are it won’t be just a plain IIS install.

If you run the following command, you can see everything related to IIS that can be installed here:

1
dism /online /get-features | find "IIS"

This is a good way to get a list of IIS features available:

Repeatable Installs in IIS

So, if you’d like to add more IIS features, it’s as easy as making more loops to check for them:

ASP.NET:

1
2
3
4
5
6
dism /online /get-featureinfo /featurename:IIS-ASPNET45 | find "State : Disabled" > nul

if %ERRORLEVEL% == 0 (
echo "ASPNET is not installed. We should install it."
dism /online /enable-feature /featurename:IIS-ASPNET45 /all
)

HTTP Redirect:

1
2
3
4
5
6
dism /online /get-featureinfo /featurename:IIS-HttpRedirect | find "State : Disabled" > nul

if %ERRORLEVEL% == 0 (
echo "HTTP Redirect is not installed . We should install it."
dism /online /enable-feature /featurename:IIS-HttpRedirect /all
)

HTTP Logging:

1
2
3
4
5
6
dism /online /get-featureinfo /featurename:IIS-HttpLogging | find "State : Disabled" > nul

if %ERRORLEVEL% == 0 (
echo "HTTP Logging is not installed . We should install it."
dism /online /enable-feature /featurename:IIS-HttpLogging /all
)

You get the idea. You can build a custom installation that can be run from a batch file, quickly and easily.

Conclusion

So now you’re set to create a neat little batch file you can run on any machine to install IIS to 100 different VMs if you want to. You can put this on an Azure stack, or run it on a development machine. As I stated I cover this and many other repeatable installations in my latest course on Pluralsight. It covers ways to effectively install IIS at a large scale.

You can even run DISM remotely or on VM Images that aren’t even booted. It’s a great tool to get to know.

Unit Testing With Dotnet Core

So you’ve just started building .Net Core applications and really starting to gain some traction. You quickly learn how mature and thorough the .Net Core framework is becoming and think “I need to start writing some unit tests for this!”. As it turns out, it’s super easy and very intuitive, especially for C# developers.

Set Up Easy File Sharing With Samba

In this tutorial, I’ll show you how easy it is to setup file sharing on your network using SAMBA. You can easily share files between Linux and Windows machines with a pretty minimal amount of setup.

Windows to Go With the Spyrus USB Drive

What we need is a good bootable live USB stick for Windows. I’ve said this many times over the years, and hacked together things to make that very thing happen, but nothing that worked really well. So when the folks at Spyrus sent me a Windows to Go USB to check out, I was pretty excited.

Which Distribution of Linux Should I Use?

I’m often asked this question: “hey, you’re a Linux guy right? What Linux should I use? I have this friend who recommends _____ and I want to know what you think?” I usually reply with the same question: what do you want to do? So I decided to make a blog post about it that I can send people instead.

My Latest Virtualization Setup

Like many geeks of the time I spent the 90s and 2000s with at least 2 or 3 old computers in a closet, connected by a switch running various operating systems with various services running on them. Giant, loud, clunky machines whirring away.

Load Testing Your IIS Web Server

All the theory, calculations, and estimations in the world aren’t going to tell you how your website will truly perform under a load. If you’re deploying a new server, or doing any kind of performance enhancements you don’t want to test your results in production. It’s always a good idea to see how your system behaves before your visitors do. To do that, you can use a load testing tool, and here are a few I use quite frequently.

Update: I’ve featured these tools is my latest IIS course on Pluralsight, IIS Administration in Depth, check it out!

How to Install Microsoft SQL Server on Ubuntu Linux in 5 Minutes

I must admit I was surprised when I learned that Microsoft SQL Server would be availble in Linux. They’ve been pushing the open source initiative hard, but I didn’t expect something this big. Oh yeah, Visual Studio is now available for Mac as well. I just saw a pig flying by.

While MS-SQL is not open source they have made it available to run on open source platforms such as Linux and OSX, which I can imagine took a ton of work. So I decided to take advantage of this new option and try it out. It works great! It took 5 minutes to install. Here’s how you can do it too. Note that you will need a server with 3.5 gigs of RAM for this.