Azure Site Extensions

David Ebbo edited this page May 8, 2018 · 66 revisions


This post introduces the Site Extension UI in the Preview Portal. Also, checkout this blog post for great information on getting started. The info below offers more technical details about how things work.

When you have an Azure Web Site, an IIS applicationhost.config gets generated by Azure for your site. In some scenarios, it can be interesting to tweak how this file is generated. Site Extensions provide a powerful way to do this using XDT Transforms.

There are two main types of Site Extensions:

  1. Pre-Installed: they live under Program Files (x86) and are available to all sites. Kudu and Monaco are examples of this.
  2. Private: installed by the user as part of the site files. Only apply to one site at a time.

Generally, site extensions can modify applicationhost.config in arbitrary ways by applying transforms to it. Some common usage:

  1. Adding new applications to the 'scm' site: the Kudu service runs at the root of the scm site, but you can add sub-applications. e.g. /foo on the scm endpoint can be an unrelated app. The advantage of running under the scm endpoint is that it is protected by authentication, making it a great place to run admin tools of all kind.
  2. Adding new applications (and vdirs) to the main site. Note that there is a simpler way to do this via the Azure Portal, so using Site Extensions this way is less common.
  3. Arbitrary other changes: e.g. tweak the <fastCgi>, <httpCompression/> or <httpModules/> sections, etc...

Pre-Installed Site Extensions

All pre-installed Site Extensions are under %ProgramFiles(x86)%\SiteExtensions. e.g.

d:\Program Files (x86)
                kudu bits...
                kudu bits...

Note: you should use either ApplicationHost.xdt or scmApplicationHost.xdt:

  • If only transforming the scm site, use scmApplicationHost.xdt
  • If transforming the runtime site (or both, which is very rare), use ApplicationHost.xdt.

extension.xml has the following format:


version can take the following values:

  • latest: all sites get the latest non-prerelease version of the Extension. This is the default in case there is no extension.xml (which is why Kudu doesn't have this file)
  • beta: all sites get the latest prerelease version of the Extension
  • disabled: sites don't get the extension at all
  • Exact version: e.g. 1.2.3456. Sites get this exact version of the Extension. If it does not exist, they get the latest non-prerelease version.
  • Tilde version: ~2 maps to the latest 2.x non-prerelease if any. Failing that, use the latest 2.x prerelease. If no 2.x exists at all, it will use the latest overall non-prerelease.

Each site can override the version by specifying <extension>_EXTENSION_VERSION in the AppSettings (e.g. from the Azure Portal). e.g. for Kudu you could set KUDU_EXTENSION_VERSION=beta to make the site get pre-release versions (if any are available).

Note that if newer Pre-Installed versions become available later, all sites will get them if it matches their version selection. However, as site restart is necessary for the site to get the newer version.

Pre-Installed Site Extensions Package

To become pre-installed site extension, partners must first contact the Kudu team. In order for us to add or update the Windows Azure pre-installed site extension, we will need a single zip package. The zip filename should be in <extension>.<semver>.zip format (for example, or The layout in the zip file should also be consistent with the zip file name. For instance, layout should be

            kudu bits... 

Or layout should be

            Monaco bits... 

After installation on Windows Azure, it will be lay out (unzip) exactly to %ProgramFiles(x86)%\SiteExtensions\<extension>

Important: please make sure you automate the building of the zip as part of your build. When this is done manually, there tends to be issues and inconsistencies from build to build.

Private Extensions

The site owner can overwrite the existing site extensions with their own implementations or introduce a totally new set of site extensions altogether.

Important note: Site Extensions only get applied after the site is restarted. However, if you modify existing extensions without changing the applicationHost.xdt, no manual restart is needed.

Also, note that the Restart button on the Site Extension Kudu tab only restarts the scm site (by just killing the process). If your xdt effects the Main site, you will need to either kill the non-Scm w3wp.exe in Kudu's Process Explorer, or fully restart the site from the Azure Portal.

There are two flavors of Private site extensions: 'named' and 'top level'.

Named private extensions

These work the same way as the 'pre-installed' extensions discussed above, except they're brought in by the site owner.

Here is a complete Site Extension sample.

All you need to do is upload the extension bits into a SiteExtensions folder. Below examples illustrate overriding the Kudu extension as well as introducing a new Foo extension. Note that unlike pre-installed extensions, these are not in versioned folders.

            kudu bits...
            foo bits...

Top level private extension

There can be only one such extension for a given site, and it consists of a single applicationHost.xdt file living in the site folder. It is typically used to make general tweaks to your site's ApplicationHost.config.


Authoring XDT transforms

There is an awesome site extension written by shibayan that makes it super easy to auther correct xdt's. It's called IISManager, and you can install it using Kudu or the (new) Azure Portal. It let's you edit applicationhost.config, and automatically generates the xdt for you.

Please check out XDT Transform Samples for a set of examples of what you can do with XDT files.

There are a set of environment variables passed to the XDT to assist in locating the appropriate elements and set the proper property.

  • XDT_SITENAME is the current site name
  • XDT_SCMSITENAME is the current scm site name
  • XDT_EXTENSIONPATH is the version specific extension physical path
  • HOME is the site root path

Site Extension Gallery

Site extensions can be shared with others using the Site Extensions gallery. See this post for more information.

Updating for site extensions

You can add the ability for your site extensions to auto-update when you publish a new version. See here for more details.

Install/Uninstall scripts for gallery extensions

An extension installed from the gallery can contain install/uninstall scripts. To use this, simply include an install.cmd and/or uninstall.cmd at the root of your extension. You can find an example here (taken from the Image Compressor extension).

Understanding what could go wrong with xdt transforms

There are several categories of issues that could cause things to not work, and it's very important to understand this difference in order to be successful with XDTs.

Invalid XDT

If your applicationhost.xdt is not valid, the XDT transform operation will fail. This could happen if you have malformed XML, or if you are incorrectly using XDT concepts like xdt:Transform attributes.

When that happens, you will see an error in the XDT log (see debugging section below).

Valid XDT that doesn't do what you want it to

Here, your XDT file is valid, but it does not modify your applicationhost.config in the way that you expect. The XDT syntax can be tricky, and it can take a few tries to get it right (looking at samples often helps!)

To diagnose this kind of issues, look at the generated applicationhost.config (see debugging section below), and see if it has what you expect.

Transform does what you expect, but applicationhost.config semantic is not what you expect

Here, the transform does exactly what you ask it to, and therefore the generated applicationhost.config looks exactly the way you intended.

However, that applicationhost.config does not work as you expect, possibly due to misunderstanding of the applicationhost.config schema or semantic.

It's important to note that these issues have nothing to do with XDT transforms. They are pure applicationhost.config issues, much like you'd see on your local IIS.

Debugging private Extensions

Finding your applicationhost.config

Before trying to apply any transform, you may want to see what the applicationhost.config looks like. Likewise, after applying a transform, you'll want to look at applicationhost.config to make sure it looks ok.

Here is one way to do it (we should try to make this easier in the future):

  • Go to the Kudu Console
  • Click the 'planet' icon
  • Click the Config folder
  • Click the download button for applicationhost.config. Or you can click the Edit button to look at it directly in the browser (but don't attempt to modify it from here, as it's read only!)

Finding the log of what happened during the transform

If you look under D:\home\LogFiles\Transform you should see a log that gives info about what happened during the transforms. This can be very useful when errors happen.

Disabling the private extension transform

If you run into problems and hose your site, all you have to do is set WEBSITE_PRIVATE_EXTENSIONS=0 in the site AppSettings, and none of your XDT will be applied. After disabling it, you can still look at the previous 'bad' applicationhost.config. You will find it at the root on the %TMP% folder (from the Kudu Console).

Running transforms locally

This is the XDT transformation package used by Azure App Service: You should be able to use it locally to test transform operations outside of App Service.

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.