Ditching Github for bare git repos with cgit and lighttpd

published: 21 August 2025

last edited: 22 August 2025

I’m transferring my git repos from Microsoft Github to self hosted repos on my server. Not relying on a big corporation and all that. I’ve decided to use ‘plain’ bare git repositories because I don’t need anything very complex and I can easily use ssh to push/pull.

Despite this I still want a website where I can see all my repos including the files and commits. This is where cgit comes in as a web interface for the ordinary git repos. It is written in C and designed to be fast which is great for my use case.

My server runs DietPi, a Debian derivative. It has cgit as a package so I could simply apt install cgit. Then I needed to set up lighttpd (the web server that I use) to work with it.

My config files


# /etc/lighttpd/lighttpd.conf
# only for the src.tombrandis.uk domain
server.document-root = "/usr/lib/cgit"  
server.indexfiles = ("cgit.cgi")  
cgi.assign = ("cgit.cgi" => "")  
  
$HTTP["url"] =~ ".*(\.css|\.png|\.well-known|robots\.txt).*" {  
    server.document-root = "/usr/share/cgit"  
} else  
{  
    url.rewrite = ( "(.*)" => "/cgit.cgi/$1")  
}

The integration of the cgit CGI script and lighttpd still seems slightly incomprehensible to me, particually the cgi.assign line. In the second part some paths are served as static files from the share directory. Everything else is sent to the cgit script which is in /usr/lib/cgit.cgi.


# /etc/cgitrc
css=/cgit.css  
logo=/cgit.png  
enable-git-config=1  
enable-index-owner=0  
enable-commit-graph=1  
enable-index-links=1  
enable-log-linecount=1  
enable-log-filecount=1  
remove-suffix=1  
side-by-side-diffs=1  
virtual-root=/  
root-title=Tom's repos  
root-desc=git repositories self hosted by Tom Brandis (https://tombrandis.uk)  
clone-prefix=https://src.tombrandis.uk ssh://git@tombrandis.uk/repos/public  
scan-path=/repos/public/

The cgit configuration is fairly straight forward and you can find all the options in the man page.

Setting up repositories

I git clone --bare‘d the repos that I wanted to move over and then copied the bare repos to /repos/public on the server. They are owned by the git user and the publicgit group.

This means that I can use git clone ssh://git@tombrandis.uk/repos/public/repo_name and everything just works. I could also add other people to the publicgit group (or make more groups) if I wanted to give anyone else access.


git remote remove origin
git remote add origin git@tombrandis.uk/repos/public/repo_name

For repos that I was importing from github, I removed the current remote and added the new one seamlessly.

Scraping protection

The site is now dynamic meaning that I don’t really want a crawler clicking every link.


User-agent: *  
Disallow: /  
Allow: /$  
Allow:/*/$
Disallow:/*/refs/
Disallow:/*/log/
Disallow:/*/tree/
Disallow:/*/commit/
Disallow:/*/diff/

I set my robots.txt to only allow the index page and one page for each repo.

Written by Tom Brandis