Edgewall Software

Version 3 (modified by Jun Omae, 9 years ago) ( diff )

Use th: intertrac for pages on trac-hacks.org

IIS configuration for Trac 1.0x and IIS 7.5 (windows server 2012 and Windows 8)

what you get

Trac using WSGI interface hosted by Microsoft IIS using FastCGI handler.

Static content served by IIS rather than through Trac.

Windows Authentication, if you want it, done by IIS, but authorization managed via Permissions in Trac. No need for AccountManagerPlugin.

What You Need

Windows Server 2012 or Windows 8 Professional with IIS 7.5 installed.

The URL Rewrite extension for your version of IIS.

FastCGI.py from the Python Tools for Visual Studio project. This is the indispensible glue, all props to the PTVS folks for providing it.

Disclaimers

Probably works for IIS 7.0 or IIS Express (free!) on Windows Server 2008r2 or Windows 7, but I have not tested it, and won't be doing so.

I have not tried to generalize for collection of Trac environments under a common parent.

This configuration only allows 1 Trac site (environment or parent) per IIS server, because the FastCGI application is defined at the server level and is identified by executable + arguments. To support multiple Trac virtual directories (on default or additional websites, doesn't matter), you might be able to clone wFastCgi.py with different names and different hardcoded environment variable settings, or hack it to accept environment variable definitions from the command line. Either way, you could then define multiple FastCGI applications with different command line arguments and they would be distinguishable by IIS.

What Goes Where

<virtualenv> (in examples below, N:\vePython\trac27)
contains Python interpreter, Trac and plugins. As the name implies, I used a python virtual environment rather than the main install. I don't think it matters.
<tracVDir> (C:\inetpub\wwwroot\tracWSGI)
the physical path to an IIS virtual directory, e.g c:\inetpub\wwwroot\trac. Contains the static content for your Trac environments. This does not need to be a separate site or a .net application under IIS, just a virtual directory.
<tracEnv>(N:\tracenv\tracWSGI)
Trac environment somewhere not under IIS.
Not a requirement, but how I happened to have Trac already running.
<tracURL> (http://localhost/tracWSGI)
The URL of the Trac environment.

Configuration Steps

(I apologize for using the IIS command line here. It is concise and unambiguous, but finickey. But trying to describe gestures in the GUI would be even worse.)

Install CGI and FastCGI handler in IIS:

      c:\> start /w pkgmgr /iu:IIS-WebServerRole;IIS-WebServer;IIS-CommonHttpFeatures;IIS-StaticContent;IIS-DefaultDocument;IIS-DirectoryBrowsing;IIS-HttpErrors;IIS-HealthAndDiagnostics;IIS-HttpLogging;IIS-LoggingLibraries;IIS-RequestMonitor;IIS-Security;IIS-RequestFiltering;IIS-HttpCompressionStatic;IIS-WebServerManagementTools;IIS-ManagementConsole;WAS-WindowsActivationService;WAS-ProcessModel;WAS-NetFxEnvironment;WAS-ConfigurationAPI;IIS-CGI

See here for GUI.

Download and install URL Rewrite extension

From here.

Rules get configured below

Deploy static content from Trac into IIS:

trac-admin <tracEnv> deploy <tracVDir>

Configure the FastCGI application at the IIS server root.

Note that IIS only supports one FastCGI application with a given executable and command line. So you're limited to a single Trac environment per IIS server unless you get creative with wFastCgi.py.

FastCGI application invokes Python interpreter (from <virtualenv>) running wfastcgi.py as the argument. wfastcgi.py needs 3 or 4 environment variables.

c:\> appcmd.exe set config -section:system.webServer/fastCgi ^
         /+"fullPath='`<virtualenv>` N:\vePython\trac27\Scripts\python.exe', arguments='n:\vePython\trac27\scripts\wfastcgi.py'"
c:\>appcmd.exe set config -section:system.webServer/fastCgi ^
         /+"[fullPath='N:\vePython\trac27\Scripts\python.exe'].environmentVariables.[name='TRAC_ENV_PATH', value='n:\tracenv\tracWSGI']" /commit:apphost
c:\>appcmd.exe set config -section:system.webServer/fastCgi ^
         /+"[fullPath='N:\vePython\trac27\Scripts\python.exe'].environmentVariables.[name='PYTHON_EGG_CACHE', value='n:\tracenv\tracWSGI.egg-cache']" /commit:apphost
c:\>appcmd.exe set config -section:system.webServer/fastCgi ^
         /+"[fullPath='N:\vePython\trac27\Scripts\python.exe'].environmentVariables.[name='WSGI_HANDLER', value='trac.web.main.dispatch_request']" /commit:apphost

Configure the Handler Map in the Trac virtual directory to invoke the FastCGI application

c:\> appcmd.exe set config "Default Web Service/tracWSGI" -section:system.webServer/handlers ^
          /+"name='Python_FastCGI_WSGI', path='*', verb='*', modules='FastCgiModule', scriptProcessor='n:\vePython\trac27\scripts\python.exe|n:\vePython\trac27\scripts\wfastcgi.py', resourceType='Unspecified', requireAccess='Script'"

The ResourceType=Unspecified is key: otherwise IIS insists that the URI match a file in <tracVdir> before invoking the handler.

Add rewrite rule(s)

These rewrite chrome/common/... and chrome/site/... to htdocs/common/... and htdocs/site/..., respectively.

c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/rewrite/rules ^
         /+"[name='siteToHtdocs',stopProcessing='True']" /commit:apphost
c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/rewrite/rules ^
         /[name='siteToHtdocs',stopProcessing='True'].match.url:"chrome/site/(.*)"  /commit:apphost
c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/rewrite/rules /[name='siteToHtdocs',stopProcessing='True'].action.type:"Rewrite" ^
         /[name='siteToHtdocs',stopProcessing='True'].action.url:"htdocs/site/{R:1}" ^
         /[name='siteToHtdocs',stopProcessing='True'].action.logRewrittenUrl:"True"  /commit:apphost

c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/rewrite/rules ^
         /+"[name='commonToHtdocs',stopProcessing='True']" /commit:apphost
c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/rewrite/rules ^
         /[name='commonToHtdocs',stopProcessing='True'].match.url:"chrome/common/(.*)"  /commit:apphost
c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/rewrite/rules /[name='commonToHtdocs',stopProcessing='True'].action.type:"Rewrite" ^
         /[name='commonToHtdocs',stopProcessing='True'].action.url:"htdocs/common/{R:1}" ^
         /[name='commonToHtdocs',stopProcessing='True'].action.logRewrittenUrl:"True"  /commit:apphost

There is some magic here: we configure the FastCGI handler to handle *all* URIs under the virtual directory, but also tell rewrite to edit URIs under <vdir>/chrome. Somehow, IIS understands that the rewritten URI should not be passed to FastCGI. But why?

Enable Windows authentication, disable anonymous (if you aren't using AccountManagerPlugin)

Trac receives the authenticated user name and greets him/her as a logged in user.

c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:"False"  /commit:apphost
c:\> appcmd.exe set config "Default Web Site/tracWSGI" -section:system.webServer/security/authentication/windowsAuthentication /enabled:"True"  /commit:apphost
Note: See TracWiki for help on using the wiki.