IIS: Quick and Easy Web Servers

You can install Web servers much more quickly and easily using Windows PowerShell to help.

Jason Helmick

Think about how many times you install IIS. Not much? Really? Consider platforms like Exchange and SharePoint that need IIS as prerequisite software, Web farm deployments, testing environments and development environments. You might spend more time installing IIS than you think.

Add to this the need for disaster recovery automation. Can you bring your Web farm back online in minutes? Installing and configuring IIS along with your Web sites is a simple task. It’s a long and boring process if you have a lot of servers.

No one wants to spend weekends setting up servers. You want to manage your Web farm, Web sites and all that Web “stuff” Monday through Friday, nine to five. You want to take every opportunity to expedite and automate the tasks in your job.

This step-by-step guide will help you deploy IIS and default Web sites to a bunch of servers, all at once, in about four minutes. You can’t do this with the GUI Server Manager tool and the GUI IIS Manager. In fact, the GUI is part of the problem. How can you do these magical things? Windows PowerShell. (Note: This applies to IIS 7.5 and IIS 8.)

PowerShell Remoting

Before we get started, do you have Windows PowerShell Remoting enabled on your servers? If not, you should. That’s how this plan is going to work. Before we get to the quick and easy part of deploying, let’s walk through how to get Windows PowerShell Remoting enabled in case you haven’t done so already.

There are two methods to do this. If you’re going to try this in a test environment, then the first method may be quicker. There are two Windows PowerShell capabilities you need to enable: Windows PowerShell Remoting and script execution. The first method requires that you visit each server you want to manage. You can use Remote Desktop Protocol (RDP) or sneaker-net, and run two commands.

1.   Open a Windows PowerShell console with administrative privileges and use the Enable-PSRemoting cmdlet to enable Windows PowerShell Remoting on each server:

PS> Enable-PSRemoting -Force

2.   You’ll want to use some of the additional modules of cmdlets stored on these servers. To use those later, you’ll need to be able to run scripts—which, by default, Windows PowerShell does not permit. So let’s change that:

PS> Set-ExecutionPolicy RemoteSigned –Force

At this point, you’re ready to deploy and manage your IIS servers. If you have hundreds of servers to manage, you’ll want to issue a Group Policy to make these changes. Running around to all those servers is a ridiculous waste of time, so here are the steps to enable Windows PowerShell Remoting with a Group Policy Object (GPO):

  1. Enable “Allow automatic configuration of listeners,” and set IPv4 and IPv6 to “*”. You’ll find the key at: Computer Configuration\Policies\Administrative templates\Windows Components\Windows Remote Management\WinRM Server.
  2. Enable script execution under “Turn on Script Execution” and set the policy setting to “Allow only signed scripts” or “Allow local scripts and remote signed scripts.” You’ll find the key at: Computer Configuration\Policies\Administrative templates\Windows Components\Windows PowerShell.
  3. Set the Windows Remote Management (WinRM) service to start automatically, at this key: Computer Configuration\Policies\Windows Settings\Security Settings\System Services.

If you have Windows Firewall running on those computers, you’ll need an Inbound Rule because WinRM listens on port 5985. You’ll find the key at: Computer Configuration\Policies\Windows Settings\Windows Firewall with Advanced Security.

Deploy Those Web Servers

Now the fun begins. This is fairly straightforward, as it only takes a few Windows PowerShell one-liners to make the magic happen.

1.   Store a list of all the server names that are going to be part of the deployment to a variable. You can create a list in notepad if you wish, and then use Windows PowerShell to read that list:

PS> $servers= get-content c:\servers.txt

This is a little sloppy, especially when dealing with a large server list. It’s better to make Windows PowerShell do all the work. Did you know that Active Directory cmdlets can get you a list of computer names? To use the Active Directory cmdlets, you’ll need the Remote Server Administration Tools (RSAT) for Active Directory installed. If you know the secret to Windows PowerShell implicit remoting, you can use that without installing the cmdlets locally. With the RSAT installed, the first task is to import the module for the Active Directory cmdlets:

PS> Import-Module ActiveDirectory

Once imported, you can use the Get-ADComputer cmdlet to grab the computer names of your choice. In this example, the computers to which we’ll deploy IIS all begin with the name “Web.” Filter the Get-ADComputer cmdlet to find only those computers that begin with the name “Web,” and pipe to Select-Object to grab only the name of the computer:

PS> $servers= Get-ADComputer -filter 'name -like "web*"' | Select-Object -ExpandProperty name

2.   Now it’s time to use the power of Windows PowerShell Remoting to make easy lifting of what would normally be a long and boring process. Let’s deploy IIS. First, we’ll build a session to all those servers we collected:

PS> $session=New-PSSession -ComputerName $servers

3.   The next step is to import the Server Manager module on the remote computers. This module has the cmdlets that will install and remove server Roles and Features. We’re using the Invoke-Command cmdlet with a parameter for the session we created previously. The interesting thing about this is that all servers will immediately receive any instructions sent inside the script block { }:

PS> Invoke-Command -Session $session {Import-module ServerManager}

This next step is not required in the process. This just checks to see if IIS is already installed on the remote computers. The Get-WindowsFeature cmdlet does a nice job of this:

PS> invoke-command -Session $session {Get-WindowsFeature web-server} | format-table -AutoSize

Let’s talk about installing IIS for a moment before we plunge into the commands. IIS has a default installation that only permits static Web pages. This is great for security reasons, but most of us will need some of the additional components for our own application needs.

When you’re using the GUI for the install, the components are all listed and you can simply check the box. With Windows PowerShell, you have to tell the remote computers specifically what components you’d like. If you’re sitting at any Windows Server 2008 R2 or Windows Server 8 computer, for example, you can use the Get-WindowsFeature to list all the components available for IIS (note that you must import the ServerManager module first):

PS> Get-WindowFeature *web*

Once you know the names of the components, you can use the Add-WindowsFeature to install them. Start with the Web-Server and then add each component, separated by a comma:

PS> Add-WindowsFeature Web-Server, ASP

You can install all the IIS components without typing a long string of them. Keep in mind that installing everything isn’t a good idea for security reasons, but the Add-WindowsFeature cmdlet has a parameter that will help:

PS> Add-WindowsFeature Web-Server -IncludeAllSubFeature

Now back to our remote IIS deployment. We want the default install and the additional components for ASP and ASP.NET. Once again, we’ll use the Invoke-Command cmdlet. Once we run this command, all servers will install IIS:

PS> Invoke-command -Session $session {Add-WindowsFeature web-server,web-asp,web-asp-net}

4.   For testing purposes, we’ll deploy a set of Web pages to the new Web servers. We’ll use a default.htm and a testpage.asp file. Mapping drives to the servers and copying the files to the default Web site would take a long time. Instead, we’ll use Windows PowerShell and the server list to do the copying.

In this example, the Web files are located in c:\files. Copy them with the Copy-Item cmdlet to a destination that’s a UNC path. The UNC needs the server name. We passed the server list ($Servers) to the Foreach-Object cmdlet. Foreach will iterate through each server name in $Server. To fix the UNC path so that we don’t have to type in the server names, use the Windows PowerShell special variable “$_”. This variable holds the current server name from $Server:

PS> $servers | foreach{copy-item -Path c:\files\*.* -Destination "\\$_\c$\inetpub\wwwroot"}

We just deployed IIS and a default Web site to a bunch of servers in about four minutes. To test the Web sites, launch Internet Explorer using the previously described technique. This command will launch a new browser for each server and display the test page:

PS> $servers | foreach{Start-Process iexplore "https://$_/testpage.asp"}

To close all the browsers, get back into Windows PowerShell and try the following:

PS> Stop-Process –Name iexplore

Remove Web Servers

If you’re testing deployments for disaster recovery, or just testing this technique, you might want to remove everything we added and start again from a clean environment. Here’s how to remove the Web site files and the Web server, and perform a reboot of the computers:

PS> $servers | foreach{remove-item -Path "\\$_\c$\inetpub\wwwroot\*.*"} PS> Invoke-command -Session $session {Remove-WindowsFeature web-server,web-asp,web-asp-net} PS> Restart-Computer –Computername $servers -Force

Script the Solution

The best part about Windows PowerShell is that once you’ve done something from the console, you can copy it into a text file and make it a script. No fuss, no programming—just pure automation. If you want to be able to run this deployment at a moment’s notice for disaster recovery and additional testing, copy the commands detailed here into a text file named IISDeploy.ps1. You can just run this script when you need to deploy.

This type of technique opens up a whole new set of possibilities. You can automate deploying multiple Web sites to a Web farm, generate load testing on the farm or even use these techniques for other Roles and Features in Windows.

Check into the WebAdministration module on IIS that has cmdlets to create and configure Web sites, App pools and more. If you need to automate something, Windows PowerShell will make your job much easier and faster.

Jason Helmick

Jason Helmick has more than 20 years in IT as an enterprise consultant, trainer and author. As the director of Windows PowerShell technologies at Interface Technical Training, he focuses on automation with Active Directory and IIS. You can see more about IIS in his upcoming book from Manning Publications, “Learn Windows IIS in a Month of Lunches.” Reach him at the JasonHelmick@gmail.com.