-
Notifications
You must be signed in to change notification settings - Fork 653
Xdt transform samples
Note: this section applies to both Pre-Installed and Private site extensions.
There is a very cool Site Extension called IIS Manager which lets you very easily create XDT files simply by editing your applicationhost.config. This page contains a bunch of sample XDT's, but if you don't find what you want, it's pretty easy to just create your own, as long as you know the IIS applicationhost.config syntax.
The simplest way to apply one of the transforms below for your site is:
- Use Kudu Console to create an
applicationHost.xdt
file under your 'site' folder (i.e.d:\home\site\applicationHost.xdt
), and copy the content from the samples below into it
See Xml Document Transform for detailed documentation on the XDT syntax.
The following will inject an environment variable named FOO
, with value BAR
, and add a folder to the PATH
:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<runtime xdt:Transform="InsertIfMissing">
<environmentVariables xdt:Transform="InsertIfMissing">
<add name="FOO" value="BAR" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
<add name="PATH" value="%PATH%;%HOME%\FolderOnPath" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</environmentVariables>
</runtime>
</system.webServer>
</configuration>
You may wonder how Kudu or other extensions gets set up in the SCM site. The key is the applicationHost.xdt (notice one exists for each versioned folders). The Xml Document Transform file is used to transform the actual applicationHost.config for the site.
This transform adds a /somepath IIS application under the SCM site.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<sites>
<site name="%XDT_SCMSITENAME%" xdt:Locator="Match(name)">
<application path="/somepath" xdt:Transform="Insert">
<virtualDirectory path="/" physicalPath="%XDT_EXTENSIONPATH%" />
</application>
</site>
</sites>
</system.applicationHost>
</configuration>
It is a variation of the above but simply adds a /somepath IIS application under the main site (%XDT_SITENAME%
) instead.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<sites>
<site name="%XDT_SITENAME%" xdt:Locator="Match(name)">
<application path="/somepath" xdt:Transform="Insert">
<virtualDirectory path="/" physicalPath="%XDT_EXTENSIONPATH%" />
</application>
</site>
</sites>
</system.applicationHost>
</configuration>
It is a variation of the above but simply adds a /somepath/subpath IIS application under the main site (%XDT_SITENAME%
).
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<sites>
<site name="%XDT_SITENAME%" xdt:Locator="Match(name)">
<application path="/somepath/subpath" xdt:Transform="Insert">
<virtualDirectory path="/" physicalPath="%XDT_EXTENSIONPATH%" />
</application>
</site>
</sites>
</system.applicationHost>
</configuration>
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<sites>
<site name="%XDT_SITENAME%" xdt:Locator="Match(name)">
<limits xdt:Transform="Remove" />
<limits xdt:Transform="Insert" maxUrlSegments="64" />
</site>
</sites>
</system.applicationHost>
</configuration>
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<httpCompression>
<dynamicTypes>
<add mimeType="application/foo" enabled="true" xdt:Transform="Insert" />
</dynamicTypes>
</httpCompression>
</system.webServer>
</configuration>
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<httpCompression xdt:Transform="SetAttributes(noCompressionForProxies)" noCompressionForProxies="false" >
</httpCompression>
</system.webServer>
</configuration>
Note: the default is 1000
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<applicationPools>
<add name="%XDT_SITENAME%" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(queueLength)" queueLength="5000">
</add>
</applicationPools>
</system.applicationHost>
</configuration>
This transform finds the <application>
tag that has the v5.4 full path, and adds a new queueLength
attribute to it.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<fastCgi>
<application xdt:Locator="Match(fullPath)" xdt:Transform="SetAttributes(queueLength)"
fullPath="D:\Program Files (x86)\PHP\v5.4\php-cgi.exe" queueLength="5000"/>
</fastCgi>
</system.webServer>
</configuration>
This transform changes the value of maxInstances
for PHP 5.4.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<fastCgi>
<application xdt:Locator="Match(fullPath)" xdt:Transform="SetAttributes(maxInstances)"
fullPath="D:\Program Files (x86)\PHP\v5.4\php-cgi.exe" maxInstances="8"/>
</fastCgi>
</system.webServer>
</configuration>
Use the following technique if you need to make changes to php.ini that can't be overridden in user.ini. The steps assume PHP 5.5, so tweak in the obvious way for other versions.
- In the Kudu console, click on the planet-looking icon.
- From there go in the
config
folder, and then in thePHP-5.5.18
folder (or whatever version you're using). - Run
copy php.ini d:\home\site
to copy it to your site folder. - Click the Home icon, and then go in the site folder to find your copy of php.ini.
- Edit it and make any changes you need. e.g. to disable impersonation, comment out the line that has
fastcgi.impersonate=1
. - Now, deploy the
applicationhost.xdt
below to that samesite
folder (changing 5.5 to other version if needed). It will cause PHP to use your php.ini instead of the default. - Restart your site.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<fastCgi>
<application fullPath="D:\Program Files (x86)\PHP\v5.5\php-cgi.exe" xdt:Locator="Match(fullPath)">
<environmentVariables>
<environmentVariable name="PHPRC" xdt:Locator="Match(name)" value="d:\home\site\php.ini" xdt:Transform="SetAttributes(value)" />
</environmentVariables>
</application>
</fastCgi>
</system.webServer>
</configuration>
Use the following technique if you want to bring your own php-cgi.exe (for example, D:\home\site\custom-php\php-cgi.exe
)
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<runtime xdt:Transform="InsertIfMissing">
<environmentVariables xdt:Transform="InsertIfMissing">
<add name="EDISGA" value="VALUE2" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
<add name="PATH" value="%PATH%;%HOME%\BAR" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</environmentVariables>
</runtime>
<defaultDocument enabled="true" xdt:Transform="SetAttributes(enabled)">
<files>
<add value="index.php" xdt:Locator="Match(value)" xdt:Transform="InsertIfMissing"/>
</files>
</defaultDocument>
<directoryBrowse enabled="false" xdt:Transform="SetAttributes(enabled)"/>
<fastCgi>
<application fullPath="D:\home\site\custom-php\php-cgi.exe" activityTimeout="600" requestTimeout="601" instanceMaxRequests="10000" maxInstances="0" signalBeforeTerminateSeconds="5" xdt:Transform="Insert">
<environmentVariables>
<environmentVariable name="PHP_FCGI_MAX_REQUESTS" value="10000" />
<environmentVariable name="PHPRC" value="D:\home\site\custom-php\php.ini" />
</environmentVariables>
</application>
</fastCgi>
</system.webServer>
<location path="%XDT_SITENAME%" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<handlers accessPolicy="Read, Script" xdt:Transform="InsertIfMissing">
<add name="MYPHP_FastCGI" path="*.php" verb="GET,HEAD,POST" modules="FastCgiModule" scriptProcessor="D:\home\site\custom-php\php-cgi.exe"
resourceType="Either"
xdt:Transform="Insert"/>
</handlers>
</system.webServer>
</location>
</configuration>
e.g. this enables parent paths
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<asp xdt:Transform="SetAttributes(enableParentPaths)" enableParentPaths="true" />
</system.webServer>
</configuration>
e.g. this enables native module (native module must be registered at globalModules)
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<globalModules>
<add name="Your Module Name" image="<path to dll such as d:\home\SiteExtensions\MyNative\module.dll>" preCondition="bitness32" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
</globalModules>
</system.webServer>
</configuration>
e.g. this enables SomeModule on the main site
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location path="%XDT_SITENAME%" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<modules xdt:Transform="InsertIfMissing">
<add name="SomeModule" type="SomeModule.SomeModuleType" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing"/>
</modules>
</system.webServer>
</location>
</configuration>
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<security>
<isapiCgiRestriction xdt:Transform="SetAttributes(notListedIsapisAllowed)" notListedIsapisAllowed="true"/>
</security>
</system.webServer>
</configuration>
This will apply IP restrictions on both the main site and Scm site. To only make it apply to the Main site, you can add a location attribute as in the "Registering an IIS Managed HttpModule" sample.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<security>
<ipSecurity xdt:Transform="RemoveAttributes(allowUnlisted)">
<add ipAddress="204.79.197.200" allowed="true" xdt:Transform="Insert"/>
</ipSecurity>
</security>
</system.webServer>
</configuration>
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<httpLogging xdt:Transform="SetAttributes(selectiveLogging)" selectiveLogging="LogSuccessful" />
</system.webServer>
</configuration>
The default is 50, and the following changes it to 100.
Note that the cleanup happens is a kind of unusual way. When maxLogFiles
is reached, half the files get deleted. So for example when set to 100, you'll have between 50 and 100 at any given time.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.applicationHost>
<sites>
<site name="%XDT_SITENAME%" xdt:Locator="Match(name)">
<traceFailedRequestsLogging xdt:Transform="Remove" />
<traceFailedRequestsLogging xdt:Transform="Insert" enabled="true" customActionsEnabled="true" directory="D:\home\LogFiles" maxLogFileSizeKB="4096" maxLogFiles="100" />
</site>
</sites>
</system.applicationHost>
</configuration>
The following makes FREB logs only for 409
requests
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<tracing>
<traceFailedRequests>
<add path="*" xdt:Locator="Match(path)">
<failureDefinitions xdt:Transform="SetAttributes(statusCodes)" statusCodes="409" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
</configuration>
The following does the equivalent of enabling Web Sockets in the portal
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<globalModules>
<add name="WebSocketModule" xdt:Locator="Match(WebSocketModule)" xdt:Transform="Remove" />
<add name="WebSocketModule" image="%windir%\System32\inetsrv\iiswsock.dll" xdt:Transform="Insert" />
</globalModules>
<webSocket xdt:Transform="SetAttributes(pingInterval)" pingInterval="00:02:30" />
</system.webServer>
<location path="" xdt:Locator="Match(path)" xdt:Transform="InsertIfMissing">
<system.webServer xdt:Transform="InsertIfMissing">
<modules xdt:Transform="InsertIfMissing">
<add name="WebSocketModule" xdt:Locator="Match(WebSocketModule)" xdt:Transform="Remove" />
<add name="WebSocketModule" lockItem="true" xdt:Transform="Insert" />
</modules>
</system.webServer>
</location>
</configuration>
Add a rule that returns a 403 if a certain http header is present
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer xdt:Transform="InsertIfMissing">
<rewrite xdt:Transform="InsertIfMissing">
<rules xdt:Transform="InsertIfMissing">
<rule name="MyRule" xdt:Locator="Match(name)" xdt:Transform="RemoveAll"/>
<rule name="MyRule" xdt:Locator="Match(name)" patternSyntax="Wildcard" stopProcessing="true" xdt:Transform="InsertIfMissing">
<match url="*" />
<conditions>
<add input="{HTTP_X_FORWARDED_SSL30}" pattern="1" />
</conditions>
<action type="CustomResponse" statusCode="403" subStatusCode="900" statusReason="Forbidden" statusDescription="Forbidden" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Update (11/1/2017): there is now a new httpsOnly
flag on the site object that you can set to true to achieve this in a much easier way. You can use ARM, PowerShell, or Resource Explorer to set it. There is also UI for it in the Azure Portal.
Original sample for historical purpose
This redirects all http traffic to https. It also makes sure that the site warmup request gets through, which makes things work correctly in site swap and Always On scenarios.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location path="%XDT_SITENAME%" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<applicationInitialization xdt:Transform="InsertIfMissing">
<add initializationPage="/" xdt:Transform="InsertIfMissing"/>
</applicationInitialization>
<rewrite xdt:Transform="InsertIfMissing">
<rules xdt:Transform="InsertIfMissing">
<rule name="Force HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</location>
</configuration>
Add CONTENT_TYPE
to the list of allowed variables:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<rewrite>
<allowedServerVariables>
<add name="CONTENT_TYPE" xdt:Transform="InsertIfMissing" />
</allowedServerVariables>
</rewrite>
</system.webServer>
</configuration>
Add .log
mimetype. If you want this to apply to SCM (kudu) only, add scmApplicationHost.xdt file (instead of applicationHost.xdt).
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<staticContent>
<mimeMap fileExtension=".log" mimeType="text/plain" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
</staticContent>
</system.webServer>
</configuration>