NGINX Unit
v. 1.18.0

Trac§

Warning

So far, Unit doesn’t support handling the REMOTE_USER headers directly, so authentication should be implemented via external means. For example, consider using trac-oidc or OAuth2Plugin.

To install and run the Trac issue tracking system using Unit:

  1. Install Unit with a Python 2 language module.

    Note

    As of now, Trac doesn’t fully support Python 3. Mind that Python 2 is officially deprecated.

  2. Prepare and activate a virtual environment to contain your installation (assuming virtualenv is installed):

    $ mkdir /path/to/trac/
    $ cd /path/to/trac
    $ virtualenv env
    $ source env/bin/activate
    
  3. Next, install Trac and its optional dependencies, then initialize a Trac environment and deploy static files:

    (env) $ pip install Trac
    (env) $ pip install babel docutils genshi \
                        pygments pytz textile             # optional dependencies
    (env) $ mkdir static/                                 # will store Trac's /chrome/ tree
    (env) $ mkdir trac_env/
    (env) $ trac-admin trac_env/ initenv                  # initialize Trac environment
    (env) $ trac-admin trac_env/ deploy static/           # extract Trac's static files
    (env) $ mv static/htdocs static/chrome                # align static file paths
    (env) $ rm -rf static/cgi-bin/                        # remove unneeded files
    (env) # chown -R trac_user:trac_group /path/to/trac/
    
  4. Unit uses WSGI to run Python apps, so a wrapper script is required to run Trac as a Unit app; let’s save it as /path/to/trac/trac_wsgi.py. Here, the application callable serves as the entry point for the app:

    import trac.web.main
    
    def application(environ, start_response):
        environ["trac.locale"] = "en_US.UTF8"
        return trac.web.main.dispatch_request(environ, start_response)
    
  5. Finally, prepare and upload the configuration to Unit (note the use of home and environment):

    {
        "listeners": {
            "*:80": {
                "pass": "routes/trac"
            }
        },
    
        "routes": {
            "trac": [
                {
                    "match": {
                        "uri": "/chrome/*"
                    },
                    "action": {
                        "share": "/path/to/trac/static/"
                    }
                },
                {
                    "action": {
                        "pass": "applications/trac"
                    }
                }
            ]
        },
    
        "applications": {
            "trac": {
                "type": "python 2",
                "path": "/path/to/trac/",
                "home": "/path/to/trac/env/",
                "user": "trac_user",
                "module": "trac_wsgi",
                "environment": {
                    "TRAC_ENV": "/path/to/trac/trac_env/",
                    "PYTHON_EGG_CACHE": "/path/to/trac/trac_env/eggs/"
                }
            }
        }
    }
    

    The route serves requests for static files in Trac’s /chrome/ hierarchy from the static/ directory.

    Assuming the config is saved as trac.json:

    # curl -X PUT --data-binary @trac.json --unix-socket \
           /var/run/control.unit.sock http://localhost/config
    
    Trac on Unit - New Ticket Screen