Running Trac on IIS 6 using Isapi-wsgi
Contributed by:
Seb Patane
I did this with:
- Windows Server 2003 SP2
- Python 2.7
- IIS 6
- Trac 0.12
It may work for other versions.
Jeremy Mattke, Minneapolis, USA. I was able to do this with:
- Windows 8.1
- Python 2.7
- IIS 8.5
- Trac 1.0
I also haven't tested standard authentication as I use the AccountManagerPlugin. I also found this to be significantly faster than the TracOnWindowsIisAjp.
The only downside is that whenever a plugin is manually installed/code is changed a full iisreset
needs to be done to reload the ISAPI dll. Restarting the IIS Site alone doesn't seem to be enough.
- Download & install the latest Isapi-wsgi (I used 0.4.2 exe), depends on pywin32 (I used Build 216 exe)
- Generate a
trac.wsgi
script usingtrac-admin <env> deploy <dir>
(see TracInstall#cgi-bin) - copy
trac.wsgi
into a new file calledtrac_wsgi.py
for Isapi-wsgi. Replace the dot with the underscore! - Append these extra bits so Isapi-wsgi can generate an ISAPI DLL:
import isapi_wsgi # The entry points for the ISAPI extension. def __ExtensionFactory__(): # can also be isapi_wsgi.ISAPISimpleHandler return isapi_wsgi.ISAPIThreadPoolHandler(application) if __name__=='__main__': # If run from the command-line, install ourselves. from isapi.install import * params = ISAPIParameters() # Setup the virtual directories - this is a list of directories our # extension uses - in this case only 1. # Each extension has a "script map" - this is the mapping of ISAPI # extensions. sm = [ ScriptMapParams(Extension="*", Flags=0) ] # To serve from root, just set Name="/" vd = VirtualDirParameters(Name="/trac", Description = "ISAPI-WSGI Trac", ScriptMaps = sm, ScriptMapUpdate = "replace" ) params.VirtualDirs = [vd] HandleCommandLine(params)
- Ensure everything has the right Permissions for the IIS Site user.
- READ/EXECUTE: imports from site-packages (including eggs), generated ISAPI dll, trac directory & subdirectories
- WRITE/MODIFY: trac/conf/trac.ini, trac/log directory, trac/plugins directory, trac/attachments directory (?), trac/db directory (?), .htpasswd file (if using Account Manager)
- Generate and Install the ISAPI dll using
python trac_wsgi.py install [--server=<IIS Web Site Name>]
. Don't forget to do aniisreset
whenever the filter is reinstalled.- This will automatically create the Virtual Directory, install the ISAPI filter and allow it in Web Service Extensions
- That's it, everything should work! NOTE: if you have a problem with trac.web.main being found you need to unzip your eggs in the python/lib/site-packages directory for Trac, Genshi and setuptools
If there are problems you can enable debugging by inserting the following at the top of trac_wsgi.py
, reinstalling the ISAPI dll and running python -m win32traceutil
(will also display TracLogging to stderr
).
import sys if hasattr(sys, "isapidllhandle"): import win32traceutil
TracModWSGI is probably a good starting point as well, even though it deals with Apache.
Broken Authentication
I had a problem with the AccountManagerPlugin always returning Invalid Username or Password
. This is because the REMOTE_USER
environment variable is set (I'm not sure why, since it seems to be empty).
In any event, putting del environ['REMOTE_USER']
in trac_wsgi.py
solved the problem.
Appendix A - My working trac_wsgi.py (with useful extras)
# -*- coding: utf-8 -*- # # Copyright (C)2008-2009 Edgewall Software # Copyright (C) 2008 Noah Kantrowitz <noah@coderanger.net> # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. # # Author: Noah Kantrowitz <noah@coderanger.net> # # IMPORTANT: when you make changes to this file you need to # update the ISAPI filter with the following commands - # C:\Inetpub\trac\cgi-bin> python trac_wsgi.py install --server=Trac # C:\Inetpub\trac\cgi-bin> iisreset # import os """ # Uncommenting this enables debug output # you can see it by opening up a command prompt and executing # > python -m win32traceutil import sys if hasattr(sys, "isapidllhandle"): import win32traceutil """ def application(environ, start_request): if not 'trac.env_parent_dir' in environ: environ.setdefault('trac.env_path', 'C:\\Inetpub\\trac') if 'PYTHON_EGG_CACHE' in environ: os.environ['PYTHON_EGG_CACHE'] = environ['PYTHON_EGG_CACHE'] elif 'trac.env_path' in environ: os.environ['PYTHON_EGG_CACHE'] = \ os.path.join(environ['trac.env_path'], '.egg-cache') elif 'trac.env_parent_dir' in environ: os.environ['PYTHON_EGG_CACHE'] = \ os.path.join(environ['trac.env_parent_dir'], '.egg-cache') # Required for Account Manager logins to work del environ['REMOTE_USER'] from trac.web.main import dispatch_request return dispatch_request(environ, start_request) """ # Uncommenting this enables middleware profiling at /__profile__ # Requires the repoze.profiler egg to be installed from repoze.profile.profiler import AccumulatingProfileMiddleware application = AccumulatingProfileMiddleware(application, log_filename='C:\\repoze.log', discard_first_request=True, flush_at_shutdown=True, path='/__profile__') """ import isapi_wsgi # The entry points for the ISAPI extension. def __ExtensionFactory__(): return isapi_wsgi.ISAPIThreadPoolHandler(application) if __name__=='__main__': # If run from the command-line, install ourselves. from isapi.install import * params = ISAPIParameters() # Setup the virtual directories - this is a list of directories our # extension uses - in this case only 1. # Each extension has a "script map" - this is the mapping of ISAPI # extensions. sm = [ ScriptMapParams(Extension="*", Flags=0) ] # To serve from root, just set Name="/" vd = VirtualDirParameters(Name="/trac", Description = "ISAPI-WSGI Trac", ScriptMaps = sm, ScriptMapUpdate = "replace" ) params.VirtualDirs = [vd] HandleCommandLine(params)