caddy + Cgit + Gitolite = self-hosted Git repositories

Part of the beauty of git is that it is distributed. I’ve often hosted projects on more centralized services like GitHub or GitLab. I’ve also hosted some repos on private servers using just plain git and ssh. But, for a while now I’ve wanted to host mirrors of projects on my own servers, but still have some access control and a web interface. No need for the overhead of issues and pull requests if I accept patches via an email-based workflow.

I hope to flesh this blog post out a little more in the future, but for now, I just want to log some of the configuration hoops I needed to jump through to get things working. Previous posts I could find don’t use Caddy v2 (with caddy-cgi). Consider this a work in progress.

Install dependencies

  • If you’re using plain Caddy, you will need to install Caddy with the caddy-cgi module. To do so, add the module on their download page.
  • Install the other system dependencies (gitolite3, cgit, etc).
    sudo apt install gitolite3 cgit python-is-python3 python3-pygments python3-markdown docutils-common groff

Configuration

This was on a server running Ubuntu 20.04 LTS.

  1. Make a git user.
    sudo adduser --system --shell /bin/bash --group --disabled-password --home /home/git git
  2. Configure gitolite of the git user (~/.gitolite.rc).
    # default umask gives you perms of '0700'; see the rc file docs for
    # how/why you might change this
    UMASK                           =>  0027,
    
    # look for "git-config" in the documentation
    GIT_CONFIG_KEYS                 =>  'gitweb.description gitweb.owner gitweb.homepage gitweb.category',
  3. Add caddy to the git group.
  4. Configure cgit (/etc/cgitrc).
    css=/cgit/cgit.css
    logo=/cgit/cgit.png
    favicon=/cgit/favicon.ico
    
    enable-index-links=1
    enable-commit-graph=1
    enable-blame=1
    enable-log-filecount=1
    enable-log-linecount=1
    enable-git-config=1
    
    branch-sort=age
    repository-sort=age
    
    clone-url=https://git.example.com/$CGIT_REPO_URL git://git.example.com/$CGIT_REPO_URL ssh://[email protected]:$CGIT_REPO_URL
    
    root-title=hsiao.dev git repositories
    root-desc=mirrors of random projects
    
    ##
    ## List of common mimetypes
    ##
    mimetype.gif=image/gif
    mimetype.html=text/html
    mimetype.jpg=image/jpeg
    mimetype.jpeg=image/jpeg
    mimetype.pdf=application/pdf
    mimetype.png=image/png
    mimetype.svg=image/svg+xml
    
    # Enable syntax highlighting
    source-filter=/usr/lib/cgit/filters/syntax-highlighting.py
    
    # Format markdown, restructuredtext, manpages, text files, and html files
    # through the right converters
    about-filter=/usr/lib/cgit/filters/about-formatting.sh
    
    ##
    ## Search for these files in the root of the default branch of repositories
    ## for coming up with the about page:
    ##
    readme=:README.md
    readme=:readme.md
    readme=:README.mkd
    readme=:readme.mkd
    readme=:README.rst
    readme=:readme.rst
    readme=:README.html
    readme=:readme.html
    readme=:README.htm
    readme=:readme.htm
    readme=:README.txt
    readme=:readme.txt
    readme=:README
    readme=:readme
    readme=:INSTALL.md
    readme=:install.md
    readme=:INSTALL.mkd
    readme=:install.mkd
    readme=:INSTALL.rst
    readme=:install.rst
    readme=:INSTALL.html
    readme=:install.html
    readme=:INSTALL.htm
    readme=:install.htm
    readme=:INSTALL.txt
    readme=:install.txt
    readme=:INSTALL
    readme=:install
    
    robots=noindex, nofollow
    project-list=/home/git/projects.list
    scan-path=/home/git/repositories
  5. Add the git site to Caddy2 (/etc/caddy/Caddyfile).
    git.example.com {
            handle_path /cgit* {
                    root * /usr/share/cgit
                    file_server
            }
            handle {
                    cgi * /usr/lib/cgit/cgit.cgi
            }
    }

References

Posts from blogs I follow

The 'free' server build

Man takes old computer, turns it into a home server again. Man happy.

via ./techtipsy July 09, 2026

The console wars have been lost

Valve wins by doing absolutely nothing

via Xe Iaso's blog July 09, 2026

Implementing standard.site on a nonstandard site

Now that this site is written in Go1, I've turned to restoring and adding more features connecting it to the open web. While I maintain a healthy skepticism of Bluesky the company, I'm enamored with open protocols and ATProto falls under that umbrella. ATP…

via Cory Dransfeldt • Posts July 07, 2026

Generated by openring-rs from my blogroll.