Publish GitWeb with Nginx Reverse-Proxying for Apache

Most installation guides for GitWeb assume that it will be hosted by a single web-server process (either Nginx or Apache). This article will show how to host GitWeb with Nginx acting as a front-end for Apache.

Assumptions

  • The Server OS is Debian/Lenny “stable”
  • Nginx is setup to listen for incoming connections on a publicly-accessible IP
  • Apache is configured to allow for multiple virtual hosts on the localhost IP

Nginx Compatability

For GitWeb to work correctly, the installed version of Nginx must support the try_files directive. Unfortuantely, the Debian “stable” version of Nginx (0.6.xx) does not. Hence, the Nginx install will need to be upgraded to 0.7.27 or higher. In Debian/Lenny, this can be easily accomplished with Backports – refer the Backports FAQ on adding backports to your sources.list file. Once that is done, the only command required is:

aptitude -t lenny-backports install nginx

Nginx Configuration

Add the following to your website configuration file under /etc/nginx/sites-available:

server {

listen my.ip.add.ress:80;
server_name gitweb.domain.com;
server_name_in_redirect off;

log_format domain_gitweb '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/gitweb-domain_access.log domain_gitweb;
error_log /var/log/nginx/gitweb-domain-error.log;

gzip on;
gzip_buffers 16 8k;
gzip_min_length 0;
gzip_proxied no-cache;
gzip_types text/plain text/xml text/css
text/comma-separated-values
text/javascript application/x-javascript;
gzip_disable "MSIE [1-6]\.";
gzip_comp_level 6;

## Only allow GET and HEAD request methods
if ($request_method !~ ^(GET|HEAD)$ ) {
return 444;
}

root /usr/share/gitweb;
#root has to be moved outside any location directives, otherwise adding expire headers
#will break

location / {
try_files $uri @gitweb;
}

location ~* ^.+\.(jpg|jpeg|gif|png|html)$ {
expires 30d;
}

location ~* ^.+\.(css|js)$ {
expires 30d;
gzip_vary on;
}

location @gitweb {
rewrite ([^/]+)/(.*) /gitweb.cgi/$1 break;
rewrite ^(/)$ /gitweb.cgi last;

}
#End Rewrites

#Pass to Apache
location ~* ^.*\.cgi(.*) {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:80;
}

}

Explaining the Nginx Configuration

Some of the core parameters that affect the setup are explained below:

ParamterExplanation
server_name gitweb.domain.com;The rest of the configuration assumes GitWeb is being served from a subdomain. If Gitweb is being hosted at domain.com/gitweb, then the ”/” and ”@gitweb” location directives will need to be modified accordingly
location / {try_files $uri @gitweb;}
This instructs Nginx to try and serve the requested resource from the path specified in the root directive, or else transfer processing to the “gitweb” location

Apache Configuration

Add The following to the site configuration file in /etc/apache2/sites-available:

ServerName gitweb.domain.com
ServerAdmin webmaster@domain.com
LogLevel warn
ErrorLog /var/log/apache2/gitweb-domain_com-error.log
DeflateFilterNote Input input_info
DeflateFilterNote Output output_info
DeflateFilterNote ratio_info
LogFormat '%h %t "%r" %{input_info}n/%{output_info}n (%{ratio_info}n%%)' compressed
CustomLog /var/log/apache2/gitweb-domain-access.log combined
CustomLog /var/log/apache2/gitweb-domain-deflate.log compressed

DocumentRoot /usr/lib/cgi-bin/
#Compression Directives
AddOutputFilterByType DEFLATE application/x-perl
#Additional Compression Directives
BrowserMatch \bMSIE\s(7|8) !no-gzip !gzip-only-text/html #This will need to be modified everytime a new IE version is released
#Following Directives ensure mod_deflate is not used for binary file types
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.avi$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mov$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mp3$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mp4$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.rm$ no-gzip dont-vary
AllowOverride AuthConfig
Order allow,deny
Allow from all
Options +ExecCGI +Indexes
DirectoryIndex gitweb.cgi
SetEnv GITWEB_CONFIG "/etc/gitweb.conf"
AddType application/x-perl .cgi
AddHandler cgi-script .cgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.* /gitweb.cgi/$0 [L,PT]
</Directory>

Explaining the Apache Configuration

Much of the configuration here is directly from the GitWeb README. The only additional directives here pertains to gzip compression of the output, i.e.:

ParamterExplanation
AddType application/x-perl .cgi
The default mime.types file that Apache uses does not recognize cgi files. This adds a handle for the cgi files and activates gzip compression (all settings defaulted) for the output
AddHandler cgi-script .cgi
AddOutputFilterByType DEFLATE application/x-perl

Testing the configuration

Reload Nginx and Apache and then navigate to gitweb.domain.com. The familiar GitWeb page should come up.