I was struggling a bit to get cgit running with nginx.

I found quite a lot of websites, that explain running with cgit with nginx, but most are outdated or simply wrong.

The following how-to is unfinished. It is meant to facilitate deployment of git repos with nginx and cgit.

# cgit with nginx

To make cgit available with nginx, some prerequisites need to be considered.

The sequence in which those steps are performed is insignificant, but they make sense the way they're displayed here.

In case you have parts of those steps already configured, just tailor it to your current setup, and it should run fine.

## git-daemon

It is not required in conjunction with cgit, but more than handy, and more often than not, will determine the rest of the configuration.

No matter where the daemon is configured, the important part are the git parameters:

git daemon --verbose --export-all --base-path=/var/cache/git

/var/cache/git is the directory where my repositories are.

I use –export-all so all repos are obtainable with via the git protocol. If you don't like that, or you need repos that aren't to be exported, just remove the option.

## export repo

The project I'm working on, is in a directory named qrencode. qrencode/.git/descripton should contain a line that described the project. Keep it short, more than one line isn't advisable.

To create a repo that is to be uploaded, go to the parent of your project (qrencode/.. so to say) and create a bare clone:

git clone --bare qrencode qrencode.git

Now, I use distributed per-repository configuration for cgit, so qrencode.git needs another file: cgirc.

I advise to keep it simple, I have just one line in there:

owner=polemon

If the project matures, other info, like a logo, an about-page, etc might go in here.

I started git-daemon with –export-all, but I tend to create git-daemon-export-ok anyway inside the repo to be exported (In case git-daemon is started without –export-all, this file is required). It's an empty file (touch git-daemon-export-ok is sufficient). In case you don't want to export every repo with git-daemon, just put it inside the repos that are to be exported.

The qrencode.git folder needs to be put onto the server, in /var/cache/git.

It is now accessible as git://polemon.org/qrencode.git and git://polemon.org/qrencode

The repository is now ready to be pushed onto with git push.

## cgit

I cloned the cgit repository and built it myself. Configuring cgit is a bit weird, you need to edit the Makefile.

My document root for cgit will be /var/www/cgit, this is what goes into the Makefile:

CGIT_SCRIPT_PATH = /var/www/cgit

after that it's building cgit:

$make git-get$ make
$sudo make install Note make git-get here. It'll fetch the latest git version for the daemon. Configuring cgit is quite easy, once you know what you're doing. /etc/cgitrc  1: enable-commit-graph=1 2: enable-tree-linenumbers=1 3: enable-log-filecount=1 4: enable-log-linecount=1 5: remove-suffix=1 6: 7: root-desc=descr 8: root-title=title 9: 10: clone-prefix=git://polemon.org 11: snapshots=tar.gz tar.xz zip 12: 13: virtual-root=/ 14: scan-path=/var/cache/git/  This ensures the cgit executable is transparent, but at the same time, it requires not being part of any url, not even as directory. It is suitable for me, since I use subdomains for git. It took me quite a while to get the correct setup to accomplish this. It seems cgit want's to reside inside a directory. PATH_INFO doesn't work so well right now, but I keep an eye on it. I had to fiddle with this, and the nginx config for quite some time, till it was working correctly. ### caveats /var/cache/git needs to be owned by the same user, that runs the CGI application. This means www-data for Ubuntu. The repos inside that need the correct ownership and access rights. Same thing applies to /var/cache/cgit, if the caching directory does not exist, cgit will crash. Make sure the directory exists and has the correct permissions! ## nginx Comment: I understand nginx is not an option for anyone. In case you feel better using a different server, just skip this section. The docroot for cgit is /var/www/cgit, and the idea is to have a subdomain for it. First, nginx.conf needs a FastCGI wrapper environment statement: inside http section: http { ... upstream fcgiwrap { server unix:/var/run/fcgiwrap.sock; } ... } It's advisable to define that not in the fastcgi_pass argument later, since it's reusable. The rest of the server configuration defines the subdomain and its content: conf/default  1: server { 2: listen 80; 3: server_name git.polemon.org; 4: 5: root /var/www/cgit/; 6: 7: location / { 8: if (-f$request_filename) {
9:       break;
10:     }
11:
12:     if (!-f $request_filename) { 13: rewrite ^/(.*)$ /cgit.cgi?url=$1 last; 14: rewrite ^/$ /cgit.cgi last;
15:       break;
16:     }
17:   }
18:
19:   location ~ \.cgi${ 20: fastcgi_pass fcgiwrap; 21: fastcgi_param SCRIPT_FILENAME$document_root$fastcgi_script_name; 22: include /usr/local/nginx/conf/fastcgi.conf; 23: } 24: }  Note: There is no index directive or something in the server section. To map indexing to cgit.cgi, a rewrite rule is used instead. It still serves static content from the /var/www/cgit directory. The FastCGI params are in a separate file. It seems it isn't quite as distributed as I thought, so I'll present it here: fastcgi.conf  1: fastcgi_param SCRIPT_FILENAME$document_root$fastcgi_script_name; 2: fastcgi_param QUERY_STRING$query_string;
3: fastcgi_param REQUEST_METHOD    $request_method; 4: fastcgi_param CONTENT_TYPE$content_type;
5: fastcgi_param CONTENT_LENGTH    $content_length; 6: 7: fastcgi_param SCRIPT_NAME$fastcgi_script_name;
8: fastcgi_param REQUEST_URI       $request_uri; 9: fastcgi_param DOCUMENT_URI$document_uri;
10: fastcgi_param DOCUMENT_ROOT     $document_root; 11: fastcgi_param SERVER_PROTOCOL$server_protocol;
12:
13: fastcgi_param GATEWAY_INTERFACE CGI/1.1;
14: fastcgi_param SERVER_SOFTWARE   nginx/$nginx_version; 15: 16: fastcgi_param REMOTE_ADDR$remote_addr;
17: fastcgi_param REMOTE_PORT       $remote_port; 18: fastcgi_param SERVER_ADDR$server_addr;
19: fastcgi_param SERVER_PORT       $server_port; 20: fastcgi_param SERVER_NAME$server_name;
21:
22: # PHP only, required if PHP was built with --enable-force-cgi-redirect
23: fastcgi_param REDIRECT_STATUS   200;


## spawn-fcgi / fcgiwrap

nginx cannot run CGI scripts. But it can run FastCGI applications.

We need two things to run a normal CGI application: A FastCGI “interpreter” that will take care of accepting input, run the CGI file in question on input, and then return the output. And something that takes care of starting the interpreter, a server, so to say, preferably multiple instances, and then provide socket communication.

fcgiwrap is is the interpreter, running cgit and passing input/output.

spawn-fcgi is the server, running multiple instances if fcgiwrap and provide the socket for communication.

In fact, fcgiwrap can provide a socket itself, as well as starting multiple instances of itself (prefork), but it's way worse in configuration, etc.

I had no need for special configurations in both tools. I used configure make sudo make install.

The trick is to start them both in a way that it all works nicely together:

spawn-fcgi -u www-data -s /var/run/fcgiwrap.sock -P /var/run/fcgiwrap.pid -F 6 -- /usr/local/sbin/fcgiwrap

### caveats

Check file permissions in /var/run. Also, double-check file ownership of files that are accessed as a different user.

## PHP

Configure with the following parameters:

'./configure' '--enable-fpm' '--with-fpm-user=www-data' '--with-fpm-group=www-data' '--with-zlib' '--with-bz2' '--with-curl' '--enable-exif' '--enable-ftp' '--with-gd' '--with-gettext' '--with-mysql' '--enable-embedded-mysqli' '--enable-zip'

## GeSHi

To add syntax highlighting to cgit, I suggest using GeSHi.

I suggest downloading the GeSHi and extracting it into /var/www/cgit, as this will be a part of this git viewer.

You need a driver file for GeSHi, as it is not a standalone application. Since GeSHi is written in PHP, making a driver in PHP is the easiest solution:

highlight.php

 1: #!/usr/local/bin/php -q
2: <?php
3: include_once "geshi/geshi.php";
4:
5: preg_match("/(?<=.\.)\w+$/", strtolower($argv[1]), $match); 6: 7: while( ($line = fgets(STDIN)) !== false )
8:     $blob .=$line;
9:
10: $geshi = new GeSHi($blob);
11: $geshi->set_language( (! isset($match[0]) && $argv[1] == "Makefile") 12: ? "make" 13: :$geshi->get_language_name_from_extension($match[0]) ); 14: echo$geshi->parse_code();
15: ?>


I suggest putting the file next to cgit.cgi, as /var/www/cgit/highlight.php.

Note: In order for this to work, you need to supply the PHP executable, since this script will basically be run from command line. My PHP binary is located in /usr/local/bin/, yours might be somewhere else, especially if you installed PHP from distro packages! Just make sure, you can run PHP scripts from the command line (this is usually decided upon compile time).

Don't forget the -q switch to the shebang line.

The script needs to be executable, and have the correct ownership.

To make cgit run it whenever it has some sourcecode to display, I simply put it into my /etc/cgitrc file:

cgitrc

 1: enable-commit-graph=1
2: enable-tree-linenumbers=1
3: enable-log-filecount=1
4: enable-log-linecount=1
5: remove-suffix=1
6:
7: root-desc=descr
8: root-title=title
9:
10: clone-prefix=git://polemon.org
11: snapshots=tar.gz tar.xz zip
12: source-filter=/var/www/cgit/highlight.php
13:
14: virtual-root=/
15: scan-path=/var/cache/git/


Note the line source-filter=/var/www/cgit/highlight.php.

# Conclusion

After performing all those steps - aside some trivial prerequisites, like compilers, etc - cgit will run fine with nginx, and git-daemon will allow for anonymous cloning from nicely named URLs.

the http://git.polemon.org subdomain makes sense for easy access to git repos, while git://polemon.org provides a socket for pushing onto git repos.