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.


    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/ 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