Team City, MSBuild, MSDeploy, Web Deploy, NTLM and aspnet_client

Ok, more on Team City and build/deploy stuff. In my previous blog post, I showed how to run team city as a domain user account. One of the reasons was for web deploy to not store the username/password in the configuration. There's another gotcha with web deploy I'll help you fix as well, when deploying to the root of a site, there is a cool folder that the updates to .net framework insists on creating. And it doesn't inherit the permissions either. It's aspnet_client. It's a pain. Because it breaks the webdeploy because the permissions prevent it from being deleted. More on that at the end. First, though, I want to go over authenticating to the management service using NTLM and domain accounts. By default, the management service uses Basic Authentication. You can use your domain credentials in here if you want, but that means putting them in the command line in plain text, yuk. Here's how to enable web deployments and NTLM authentication.

  1. Installing the management service on the web servers. (I used the Web Platform Installer from IIS Manager for this)
    • Make sure the IIS: Management Service is installed,
    • Make sure the Web Deploy without SQL support is also installed
  2. Configure the management service
    • Stop the management service (it may already be stopped) -- IIS Manager->Select your server on the left->Goto the Management Service in the middle->Click stop.
    • Check Enable remote connections
    • Set identity credentials to Windows Credentials Only
    • Check Log Requests
    • Check Enabled failed request tracing
      If you want to use a different certificate (one that's not self signed, which is recommended) on the management service, you can choose that certificate here as well.
    • Set the following registry key to 1. It's a DWORD value that you probably have to create.
      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WebManagement\Server\WindowsAuthenticationEnabled
    • Back in IIS Manager, click Start to start the management service
  3. Allow your service account permissions to the site management service
    • In IIS Manager, click the Site you are deploying to, probably Default Web Site.
      Double click IIS Manager Permissions
    • Click Allow User on the right.
    • Click Select->Locations->Choose your Entire Directory->OK->In the big white box, type in your service account name (!teamcity)
    • Click OK
  4. Allow your service account full control to the directory containing your site
    • Click Edit Permissions.
    • Click the security tab.
    • Click the Edit button.
    • Click Add
    • Type your service account. Example: litterbox!teamcity
    • Click OK
    • Check the Full Control box. (Full Control is needed if your deployment will set the permissions)
    • Click OK
    • Click OK

Alright, now NTLM authentication should be enabled, and web deployment should work. Not hard right? Now for the building and deployment process.
Ok, so you already have your stuff building in team city correct? I hope so. If not, follow this site to get it going, they worked pretty well, though it's for an old version of Team City so the pictures were wrong. http://www.troyhunt.com/2010/11/you-deploying-it-wrong-teamcity.html
There is a small change that needs to be made in the build step. Where you put in your command line parameters. Troy has you put in (I bolded what will be changed):

 
/P:Configuration=%env.Configuration%
/P:DeployOnBuild=True
/P:DeployTarget=MSDeployPublish
/P:MsDeployServiceUrl=https://%env.TargetServer%/MsDeploy.axd
/P:AllowUntrustedCertificate=True
/P:MSDeployPublishMethod=WMSvc
/P:CreatePackageOnPublish=True
/P:UserName=AutoDeploy\Administrator
/P:Password=Passw0rd
 

But in order to use NTLM authentication, it needs to be changed to (I have bolded the changes)

 
/P:Configuration=%env.Configuration%
/P:DeployOnBuild=True
/P:DeployTarget=MSDeployPublish
/P:MsDeployServiceUrl=https://%env.TargetServer%/MsDeploy.axd
/P:AllowUntrustedCertificate=True
/P:MSDeployPublishMethod=WMSvc
/P:CreatePackageOnPublish=True
/P:UserName=
/P:AuthType=NTLM
 

The username must be set to blank, I don't know what it was doing, but it wasn't even attempting to authenticate.

If you set a valid certificate for the management service, you should remove the AllowUntrustedCertificate parameter.

Web deploy will now use NTLM authentication. Cool right?

Ok, now that all that is said and done, you're probably running into the problem with the aspnet_client folder. Even before NTLM you might have been. There's a few solutions.

  • Set up a scheduled task running as system to automatically delete the aspnet_client folder (yuk).
  • Add the user that will connect to do the deployments (!teamcity) to the administrators group (no).
  • Add the aspnet_client and all subfolder into your source control, (joking right).
  • Skip deleting the aspnet_client folder during deployments. (the option I opted for)
  • Set the dont delete extra files property. (Don't remember what the actual property was as it's a horrible idea).

So, skipping a folder and/or file proved to be annoying. I was hoping for a way to do it without adding another file to source control, though it does have it's benifits. But, alas, I needed to add a file which would control the Web Publishing Pipeline (WPP). The file name matches your project filename. So if your project filename (not solution name, that doesn't matter), is LitterboxTestApp.csproj (or vbproj for VB) the filename would be LitterboxTestApp.wpp.targets. Inside of this little gem of a file, would be the following.

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- SKIP DIRECTORIES/FILES -->
  <PropertyGroup>
    <AfterAddIisSettingAndFileContentsToSourceManifest>
      $(AfterAddIisSettingAndFileContentsToSourceManifest);
      AddCustomSkipRules;
    </AfterAddIisSettingAndFileContentsToSourceManifest>
  </PropertyGroup>
  
  <Target Name="AddCustomSkipRules">
    <Message Text="Adding Custom Skip Rules" />
    <ItemGroup>
      <MsDeploySkipRules Include="SkipAspNetClientFolder">
        <ObjectName>dirPath</ObjectName>
        <AbsolutePath>$(_MSDeployDirPath_FullPath)\\aspnet_client</AbsolutePath>
      </MsDeploySkipRules>
    </ItemGroup>
  </Target>
  <!-- END SKIP DIRECTORIES/FILES -->
</project>

Place that file in the same folder as your project file and check it into source control.

Now, the aspnet_client folder will be ignored during the deleting extra files part of deployment. Of course, you can change the aspnet_client to any other path to not delete those as well. Things like app_data or uploads might be ones you don't want to delete on a production environment. You can put other things in this file as well, like what permissions you want set on the folders (this is where the Full Control permissions come from above).

Hopefully having all of this information in one place will help some people out, I spent about 2 days sifting through a bunch of random sites to get little pieces of it all...very annoying.