Changes between Initial Version and Version 1 of TracFastCgi

Show
Ignore:
Timestamp:
01/25/14 15:31:21 (11 years ago)
Author:
trac
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • TracFastCgi

    v1 v1  
     1= Trac with FastCGI = 
     2 
     3Since version 0.9, Trac supports being run through the [http://www.fastcgi.com/ FastCGI] interface. Like [wiki:TracModPython mod_python], this allows Trac to remain resident, and is faster than external CGI interfaces which must start a new process for each request. However, unlike mod_python, it is able to support [http://httpd.apache.org/docs/suexec.html SuEXEC]. Additionally, it is supported by much wider variety of web servers. 
     4 
     5'''Note for Windows:''' Trac's FCGI does not run under Windows, as Windows does not implement `Socket.fromfd`, which is used by `_fcgi.py`. If you want to connect to IIS, your choice may be [trac:TracOnWindowsIisAjp AJP]. 
     6 
     7== Simple Apache configuration == 
     8 
     9There are two FastCGI modules commonly available for Apache: `mod_fastcgi` and 
     10`mod_fcgid`.  The `FastCgiIpcDir` and `FastCgiConfig` directives discussed 
     11below are `mod_fastcgi` directives; the `DefaultInitEnv` is a `mod_fcgid` 
     12directive. 
     13 
     14For `mod_fastcgi`, add the following to an appropriate Apache configuration 
     15file: 
     16{{{ 
     17# Enable fastcgi for .fcgi files 
     18# (If you're using a distro package for mod_fcgi, something like 
     19# this is probably already present) 
     20<IfModule mod_fastcgi.c> 
     21   AddHandler fastcgi-script .fcgi 
     22   FastCgiIpcDir /var/lib/apache2/fastcgi  
     23</IfModule> 
     24LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so 
     25}}} 
     26Setting `FastCgiIpcDir` is optional if the default is suitable. Note that the `LoadModule` line must be after the `IfModule` group. 
     27 
     28Configure `ScriptAlias` or similar options as described in TracCgi, but 
     29calling `trac.fcgi` instead of `trac.cgi`. 
     30 
     31You can set up the `TRAC_ENV` as an overall default: 
     32{{{ 
     33FastCgiConfig -initial-env TRAC_ENV=/path/to/env/trac 
     34}}} 
     35 
     36Or you can serve multiple Trac projects in a directory like: 
     37{{{ 
     38FastCgiConfig -initial-env TRAC_ENV_PARENT_DIR=/parent/dir/of/projects 
     39}}} 
     40 
     41But neither of these will work for `mod_fcgid`.  A similar but partial 
     42solution for `mod_fcgid` is: 
     43{{{ 
     44DefaultInitEnv TRAC_ENV /path/to/env/trac/ 
     45}}} 
     46But this cannot be used in `Directory` or `Location` context, which makes it 
     47difficult to support multiple projects. 
     48 
     49A better method which works for both of these modules (and for  [http://www.lighttpd.net/ lighttpd] and CGI as well), because it involves 
     50no server configuration settings for environment variables, is to set one 
     51of the variables in `trac.fcgi`, e.g.: 
     52{{{ 
     53import os 
     54os.environ['TRAC_ENV'] = "/path/to/projectenv" 
     55}}} 
     56or 
     57{{{ 
     58import os 
     59os.environ['TRAC_ENV_PARENT_DIR'] = "/path/to/project/parent/dir" 
     60}}} 
     61 
     62Using this method, different projects can be supported by using different 
     63`.fcgi` scripts with different `ScriptAliases`, copying and appropriately 
     64renaming `trac.fcgi` and adding the above code to create each such script. 
     65 
     66See [https://coderanger.net/~coderanger/httpd/fcgi_example.conf this fcgid example config] which uses a !ScriptAlias directive with trac.fcgi with a trailing / like this: 
     67{{{ 
     68ScriptAlias / /srv/tracsite/cgi-bin/trac.fcgi/ 
     69}}} 
     70 
     71== Simple Cherokee Configuration == 
     72 
     73Configuration wanted. 
     74 
     75== Simple Lighttpd Configuration == 
     76 
     77The FastCGI front-end was developed primarily for use with alternative webservers, such as [http://www.lighttpd.net/ lighttpd]. 
     78 
     79lighttpd is a secure, fast, compliant and very flexible web-server that has been optimized for high-performance 
     80environments.  It has a very low memory footprint compared to other web servers and takes care of CPU load. 
     81 
     82For using `trac.fcgi`(prior to 0.11) / fcgi_frontend.py (0.11) with lighttpd add the following to your lighttpd.conf: 
     83{{{ 
     84#var.fcgi_binary="/path/to/fcgi_frontend.py" # 0.11 if installed with easy_setup, it is inside the egg directory 
     85var.fcgi_binary="/path/to/cgi-bin/trac.fcgi" # 0.10 name of prior fcgi executable 
     86fastcgi.server = ("/trac" => 
     87    
     88                   ("trac" => 
     89                     ("socket" => "/tmp/trac-fastcgi.sock", 
     90                      "bin-path" => fcgi_binary, 
     91                      "check-local" => "disable", 
     92                      "bin-environment" => 
     93                        ("TRAC_ENV" => "/path/to/projenv") 
     94                     ) 
     95                   ) 
     96                 ) 
     97}}} 
     98 
     99Note that you will need to add a new entry to `fastcgi.server` for each separate Trac instance that you wish to run. Alternatively, you may use the `TRAC_ENV_PARENT_DIR` variable instead of `TRAC_ENV` as described above, 
     100and you may set one of the two in `trac.fcgi` instead of in `lighttpd.conf` 
     101using `bin-environment` (as in the section above on Apache configuration). 
     102 
     103For using two projects with lighttpd add the following to your `lighttpd.conf`: 
     104{{{ 
     105fastcgi.server = ("/first" => 
     106                   ("first" => 
     107                    ("socket" => "/tmp/trac-fastcgi-first.sock", 
     108                     "bin-path" => fcgi_binary, 
     109                     "check-local" => "disable", 
     110                     "bin-environment" => 
     111                       ("TRAC_ENV" => "/path/to/projenv-first") 
     112                    ) 
     113                  ), 
     114                  "/second" => 
     115                    ("second" => 
     116                    ("socket" => "/tmp/trac-fastcgi-second.sock", 
     117                     "bin-path" => fcgi_binary, 
     118                     "check-local" => "disable", 
     119                     "bin-environment" => 
     120                       ("TRAC_ENV" => "/path/to/projenv-second") 
     121                    ) 
     122                  ) 
     123                ) 
     124}}} 
     125Note that field values are different.  If you prefer setting the environment 
     126variables in the `.fcgi` scripts, then copy/rename `trac.fcgi`, e.g., to 
     127`first.fcgi` and `second.fcgi`, and reference them in the above settings. 
     128Note that the above will result in different processes in any event, even 
     129if both are running from the same `trac.fcgi` script. 
     130{{{ 
     131#!div class=important 
     132'''Note''' It's very important the order on which server.modules are loaded, if mod_auth is not loaded '''BEFORE''' mod_fastcgi, then the server will fail to authenticate the user. 
     133}}} 
     134For authentication you should enable mod_auth in lighttpd.conf 'server.modules', select auth.backend and auth rules: 
     135{{{ 
     136server.modules              = ( 
     137... 
     138  "mod_auth", 
     139... 
     140) 
     141 
     142auth.backend               = "htpasswd" 
     143 
     144# Separated password files for each project 
     145# See "Conditional Configuration" in 
     146# http://trac.lighttpd.net/trac/file/branches/lighttpd-merge-1.4.x/doc/configuration.txt 
     147 
     148$HTTP["url"] =~ "^/first/" { 
     149  auth.backend.htpasswd.userfile = "/path/to/projenv-first/htpasswd.htaccess" 
     150} 
     151$HTTP["url"] =~ "^/second/" { 
     152  auth.backend.htpasswd.userfile = "/path/to/projenv-second/htpasswd.htaccess" 
     153} 
     154 
     155# Enable auth on trac URLs, see 
     156# http://trac.lighttpd.net/trac/file/branches/lighttpd-merge-1.4.x/doc/authentication.txt 
     157 
     158auth.require = ("/first/login" => 
     159                ("method"  => "basic", 
     160                 "realm"   => "First project", 
     161                 "require" => "valid-user" 
     162                ), 
     163                "/second/login" => 
     164                ("method"  => "basic", 
     165                 "realm"   => "Second project", 
     166                 "require" => "valid-user" 
     167                ) 
     168               ) 
     169 
     170 
     171}}} 
     172Note that lighttpd (I use version 1.4.3) stopped if password file doesn't exist. 
     173 
     174Note that lighttpd doesn't support 'valid-user' in versions prior to 1.3.16. 
     175 
     176Conditional configuration is also useful for mapping static resources, i.e. serving out images and CSS directly instead of through FastCGI: 
     177{{{ 
     178# Aliasing functionality is needed 
     179server.modules += ("mod_alias") 
     180 
     181# Setup an alias for the static resources 
     182alias.url = ("/trac/chrome/common" => "/usr/share/trac/htdocs") 
     183 
     184# Use negative lookahead, matching all requests that ask for any resource under /trac, EXCEPT in 
     185# /trac/chrome/common, and use FastCGI for those 
     186$HTTP["url"] =~ "^/trac(?!/chrome/common)" { 
     187# Even if you have other fastcgi.server declarations for applications other than Trac, do NOT use += here 
     188fastcgi.server = ("/trac" => 
     189                   ("trac" => 
     190                     ("socket" => "/tmp/trac-fastcgi.sock", 
     191                      "bin-path" => fcgi_binary, 
     192                      "check-local" => "disable", 
     193                      "bin-environment" => 
     194                        ("TRAC_ENV" => "/path/to/projenv") 
     195                     ) 
     196                   ) 
     197                 ) 
     198} 
     199}}} 
     200The technique can be easily adapted for use with multiple projects by creating aliases for each of them, and wrapping the fastcgi.server declarations inside conditional configuration blocks. 
     201Also there is another way to handle multiple projects and it's to use TRAC_ENV_PARENT_DIR instead of TRAC_ENV and use global auth, let's see an example: 
     202{{{ 
     203#  This is for handling multiple projects 
     204  alias.url       = ( "/trac/" => "/path/to/trac/htdocs/" ) 
     205 
     206  fastcgi.server += ("/projects"  => 
     207                      ("trac" => 
     208                        ( 
     209                          "socket" => "/tmp/trac.sock", 
     210                          "bin-path" => fcgi_binary, 
     211                          "check-local" => "disable", 
     212                          "bin-environment" => 
     213                            ("TRAC_ENV_PARENT_DIR" => "/path/to/parent/dir/of/projects/" ) 
     214                        ) 
     215                      ) 
     216                    ) 
     217#And here starts the global auth configuration 
     218  auth.backend = "htpasswd" 
     219  auth.backend.htpasswd.userfile = "/path/to/unique/htpassword/file/trac.htpasswd" 
     220  $HTTP["url"] =~ "^/projects/.*/login$" { 
     221    auth.require = ("/" => 
     222                     ( 
     223                       "method"  => "basic", 
     224                       "realm"   => "trac", 
     225                       "require" => "valid-user" 
     226                     ) 
     227                   ) 
     228  } 
     229}}} 
     230 
     231Changing date/time format also supported by lighttpd over environment variable LC_TIME 
     232{{{ 
     233fastcgi.server = ("/trac" => 
     234                   ("trac" => 
     235                     ("socket" => "/tmp/trac-fastcgi.sock", 
     236                      "bin-path" => fcgi_binary, 
     237                      "check-local" => "disable", 
     238                      "bin-environment" => 
     239                        ("TRAC_ENV" => "/path/to/projenv", 
     240                        "LC_TIME" => "ru_RU") 
     241                     ) 
     242                   ) 
     243                 ) 
     244}}} 
     245For details about languages specification see [trac:TracFaq TracFaq] question 2.13. 
     246 
     247Other important information like [http://trac.lighttpd.net/trac/wiki/TracInstall this updated TracInstall page], [wiki:TracCgi#MappingStaticResources and this] are useful for non-fastcgi specific installation aspects. 
     248 
     249If you use trac-0.9, read [http://lists.edgewall.com/archive/trac/2005-November/005311.html about small bug] 
     250 
     251Relaunch lighttpd, and browse to `http://yourhost.example.org/trac` to access Trac. 
     252 
     253Note about running lighttpd with reduced permissions: 
     254 
     255  If nothing else helps and trac.fcgi doesn't start with lighttpd settings __server.username = "www-data"__, __server.groupname = "www-data"__, then in the `bin-environment` section set `PYTHON_EGG_CACHE` to the home directory of `www-data` or some other directory accessible to this account for writing. 
     256 
     257 
     258== Simple !LiteSpeed Configuration == 
     259 
     260The FastCGI front-end was developed primarily for use with alternative webservers, such as [http://www.litespeedtech.com/ LiteSpeed]. 
     261 
     262!LiteSpeed web server is an event-driven asynchronous Apache replacement designed from the ground-up to be secure, scalable, and operate with minimal resources. !LiteSpeed can operate directly from an Apache config file and is targeted for business-critical environments. 
     263 
     264Setup 
     265 
     2661) Please make sure you have first have a working install of a Trac project. Test install with “tracd” first. 
     267 
     2682) Create a Virtual Host for this setup. From now on we will refer to this vhost as TracVhost. For this tutorial we will be assuming that your trac project will be accessible via: 
     269 
     270{{{ 
     271http://yourdomain.com/trac/ 
     272}}} 
     273 
     2743) Go “TracVhost → External Apps” tab and create a new “External Application”. 
     275 
     276{{{ 
     277Name: MyTracFCGI         
     278Address: uds://tmp/lshttpd/mytracfcgi.sock 
     279Max Connections: 10 
     280Environment: TRAC_ENV=/fullpathto/mytracproject/ <--- path to root folder of trac project 
     281Initial Request Timeout (secs): 30 
     282Retry Timeout (secs): 0 
     283Persistent Connection   Yes 
     284Connection Keepalive Timeout: 30 
     285Response Bufferring: No  
     286Auto Start: Yes 
     287Command: /usr/share/trac/cgi-bin/trac.fcgi  <--- path to trac.fcgi 
     288Back Log: 50 
     289Instances: 10 
     290}}} 
     291 
     2924) Optional. If you need to use htpasswd based authentication. Go to “TracVhost → Security” tab and create a new security “Realm”. 
     293 
     294{{{ 
     295DB Type: Password File 
     296Realm Name: MyTracUserDB               <--- any name you wish and referenced later 
     297User DB Location: /fullpathto/htpasswd <--- path to your htpasswd file 
     298}}} 
     299 
     300If you don’t have a htpasswd file or don’t know how to create the entries within one, go to http://sherylcanter.com/encrypt.php, to generate the user:password combos. 
     301 
     3025) Go to “PythonVhost → Contexts” and create a new “FCGI Context”. 
     303 
     304{{{ 
     305URI: /trac/                              <--- URI path to bind to python fcgi app we created     
     306Fast CGI App: [VHost Level] MyTractFCGI  <--- select the trac fcgi extapp we just created 
     307Realm: TracUserDB                        <--- only if (4) is set. select realm created in (4) 
     308}}} 
     309 
     3106) Modify /fullpathto/mytracproject/conf/trac.ini 
     311 
     312{{{ 
     313#find/set base_rul, url, and link variables 
     314base_url = http://yourdomain.com/trac/ <--- base url to generate correct links to 
     315url = http://yourdomain.com/trac/      <--- link of project 
     316link = http://yourdomain.com/trac/     <--- link of graphic logo 
     317}}} 
     318 
     3197) Restart !LiteSpeed, “lswsctrl restart”, and access your new Trac project at:  
     320 
     321{{{ 
     322http://yourdomain.com/trac/ 
     323}}} 
     324 
     325=== Simple Nginx Configuration === 
     326 
     3271) Nginx configuration snippet - confirmed to work on 0.5.36 
     328{{{ 
     329    server { 
     330        listen       10.9.8.7:443; 
     331        server_name  trac.example; 
     332 
     333        ssl                  on; 
     334        ssl_certificate      /etc/ssl/trac.example.crt; 
     335        ssl_certificate_key  /etc/ssl/trac.example.key; 
     336 
     337        ssl_session_timeout  5m; 
     338 
     339        ssl_protocols  SSLv2 SSLv3 TLSv1; 
     340        ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; 
     341        ssl_prefer_server_ciphers   on; 
     342 
     343        location / { 
     344            auth_basic            "trac realm"; 
     345            auth_basic_user_file /home/trac/htpasswd; 
     346 
     347            # full path 
     348            if ($uri ~ ^/([^/]+)(/.*)) { 
     349                 set $script_name $1; 
     350                 set $path_info $2; 
     351            } 
     352 
     353            # index redirect  
     354            if ($uri ~ ^/([^/]+)$) { 
     355                 rewrite (.+) $1/ permanent;  
     356            } 
     357          
     358            # socket address 
     359            fastcgi_pass   unix:/home/trac/run/instance.sock; 
     360 
     361            # python - wsgi specific 
     362            fastcgi_param HTTPS on; 
     363 
     364            ## WSGI REQUIRED VARIABLES 
     365            # WSGI application name - trac instance prefix.  
     366            fastcgi_param  SCRIPT_NAME        /$script_name; 
     367            fastcgi_param  PATH_INFO          $path_info; 
     368 
     369            ## WSGI NEEDED VARIABLES - trac warns about them 
     370            fastcgi_param  REQUEST_METHOD     $request_method; 
     371            fastcgi_param  SERVER_NAME        $server_name; 
     372            fastcgi_param  SERVER_PORT        $server_port; 
     373            fastcgi_param  SERVER_PROTOCOL    $server_protocol; 
     374 
     375            # for authentication to work 
     376            fastcgi_param  REMOTE_USER        $remote_user; 
     377        } 
     378    } 
     379}}} 
     380 
     3812) Modified trac.fcgi: 
     382 
     383{{{ 
     384#!/usr/bin/env python 
     385import os 
     386sockaddr = '/home/trac/run/instance.sock' 
     387os.environ['TRAC_ENV'] = '/home/trac/instance' 
     388 
     389try: 
     390     from trac.web.main import dispatch_request 
     391     import trac.web._fcgi 
     392 
     393     fcgiserv = trac.web._fcgi.WSGIServer(dispatch_request,  
     394          bindAddress = sockaddr, umask = 7) 
     395     fcgiserv.run() 
     396 
     397except SystemExit: 
     398    raise 
     399except Exception, e: 
     400    print 'Content-Type: text/plain\r\n\r\n', 
     401    print 'Oops...' 
     402    print 
     403    print 'Trac detected an internal error:' 
     404    print 
     405    print e 
     406    print 
     407    import traceback 
     408    import StringIO 
     409    tb = StringIO.StringIO() 
     410    traceback.print_exc(file=tb) 
     411    print tb.getvalue() 
     412 
     413}}} 
     414 
     4153) reload nginx and launch trac.fcgi like that: 
     416 
     417{{{ 
     418trac@trac.example ~ $ ./trac-standalone-fcgi.py  
     419}}} 
     420 
     421The above assumes that: 
     422 * There is a user named 'trac' for running trac instances and keeping trac environments in its home directory. 
     423 * /home/trac/instance contains a trac environment 
     424 * /home/trac/htpasswd contains authentication information 
     425 * /home/trac/run is owned by the same group the nginx runs under 
     426  * and if your system is Linux the /home/trac/run has setgid bit set (chmod g+s run) 
     427  * and patch from ticket #T7239 is applied, or you'll have to fix the socket file permissions every time 
     428 
     429Unfortunately nginx does not support variable expansion in fastcgi_pass directive.  
     430Thus it is not possible to serve multiple trac instances from one server block.  
     431 
     432If you worry enough about security, run trac instances under separate users.  
     433 
     434Another way to run trac as a FCGI external application is offered in ticket #T6224 
     435 
     436---- 
     437See also TracCgi, TracModPython, TracInstall, TracGuide, [trac:TracNginxRecipe TracNginxRecipe]