Set up your own Smart HTTP Git Server with Gitolite, Cgit and Apache

10 Aug 2020

This guide is for people want to setup their own git server but don’t want something as big as GitLab or Gitea, and don’t want something overly simple like bare git repository over SSH. Also, it is made on the assumption that you know how to setup and use Apache with https and virtual hosts, and SSH server with public key authentication. Your gitolite user will be available over SSH so make sure it is secured.

If you follow this guide, you will have a git server with read-write access over SSH and read access over HTTPS. Your repositories will also be displayed using cgit web interface. Gitolite will give you the ability to easily add new repositories and manage complex permissions, ideal when you have to work with multiple people on a same project. Gitolite also works very well with cgit and git-http-backend. For example, if you make a repository that is not readable by everyone, gitolite won’t add it to projects.list which cgit uses to decide what repositories to display, it also won’t add git-deamon-export-ok file in repository directory, which git-http-backend uses to decide whether it should serve a repository over http.


First install necessary software. Package python-pygments is used by cgit for syntax highlighting. Check optional dependencies for cgit, you probably want to add all of them.

pacman -Sy --needed gitolite cgit python-pygments

We will use git-http-backend CGI program (it is part of the git package) to serve our repositories as read only over https. Since CGI programs are ran by default Apache user (http on my system, check your httpd.conf) and our repositories will belong to the gitolite user, we will add http user to gitolite group to later allow it to access repositories. Cgit is also a CGI program that needs to be able to access repositories.

usermod -aG gitolite http

You will also need to enable mod_cgi, mod_alias and mod_env in your Apache configuration, since we are using CGI programs.

Setting up gitolite

First you will need to copy your public ssh key to your server and rename it to . Then you will copy it to gitolite user’s home directory. You can use this command:

install -o gitolite -g gitolite -m 640 /var/lib/gitolite/

Per default gitolite uses umask of 077, meaning that only gitolite user can read, write and execute gitolite files. Since we want users in gitolite group to be able to read and execute gitolite files, we will need to set umask that gitolite uses to 027. However, when we run gitolite setup it uses default .gitolite.rc configuration file if it can’t find one. We can of course change directories it made with chmod -R g+rX /var/lib/gitolite/repositories, but why not do it right the first time?

Generate .gitolite.rc with command gitolite print-default-rc > .gitolite.rc . Then change lines 21 and 24 to UMASK => 0027, and GIT_CONFIG_KEYS => '.*', respectively. We changed line 24 so that we could use gitweb keys in gitolite-admin repository to tell cgit who is repository owner and repository description.

This is how your .gitolite.rc should look like without comments, you should of course keep comments, they are useful.

%RC = (
    UMASK                   =>  0027,
    GIT_CONFIG_KEYS         =>  '.*',
    LOG_EXTRA               =>  1,
    ROLES => {
    READERS                 =>  1,
    WRITERS                 =>  1,
    ENABLE => [

You can copy it to gitolite user’s home directory.

install -o gitolite -g gitolite -m 640 .gitolite.rc /var/lib/gitolite/

Now we are done with configuring gitolite and we can actually set it up. Login to gitolite user and run gitolite setup.

sudo -iu gitolite
gitolite setup -pk

Now, we finished setting up gitolite. You can use git clone ssh:// on your client machine to clone gitolite administrator repository. In gitolite-admin repository you have conf and keydir directories. keydir keeps public keys for all available users, you can of course have multiply keys per user. You can use gitweb.owner and gitweb.description to set repository owner and description in cgit. Cgit can only display repositories in projects.list file and git-http-backend can only export them if git-deamon-export-ok file is present, in other words, only if it’s readable by everyone (R = @all).
Here you have an example gitolite.conf:

repo gitolite-admin
    RW+     =   username

repo testing
    RW+     =   username
    R       =   @all
    config gitweb.owner = Your Name
    config gitweb.description = Simple testing repo

You can do bunch of things in gitolite and they are explained in great detail on it’s website.

Configuring cgit

Configuration file below is quite self explanatory so I won’t go over it. Edit it per your needs, just make sure that scan-path is at the end of the file. You can find explanation for each line in cgitrc(5) man page. Files (css, icons) that cgit uses can be found at /usr/share/webapps/cgit/ . You can install this configuration file using install -o root -g root -m 644 cgitrc /etc/ .


root-title=Yours repositories
root-desc=Here you can find all my public projects.
snapshots=tar.gz zip



#not default

#nice to have...

# if you do not want that webcrawler (like google) index your site
# robots=noindex, nofollow

# if cgit messes up links, use a virtual-root. For example, has this value:

# Allow using gitweb.* keys

## List of common mimetypes

## Search for these files in the root of the default branch of repositories
## for coming up with the about page:

#gitolite repos

Configuring Apache

And finally, the last step, connecting everything using Apache.

GIT_PROJECT_ROOT variable is used by git-http-backend to locate repositories.
ScriptAliasMatch part I took from git-http-backend and changed it so that it only allows http clients to git pull but not to git push . Alias part is where cgit should look for additional files (css, png), if you want to change it don’t forget to change /etc/cgitrc . ScriptAlias is part where cgit actually executes.
Files and Directory entries just tell Apache that it can access given files.
For more information check out Apache documentation,

You can just append this to your httpd-vhosts-le-ssl.conf file, you should of course edit it per your needs.

<IfModule mod_ssl.c>
<VirtualHost *:443>
#    ServerAdmin
    DocumentRoot "/srv/http/"

    SetEnv GIT_PROJECT_ROOT /var/lib/gitolite/repositories/

    ScriptAliasMatch \
    "(?x)^/(.*/(HEAD | \
        info/refs | \
        objects/info/[^/]+ | \
        git-upload-pack))$" \

    Alias /cgit-css "/usr/share/webapps/cgit/"
    ScriptAlias / "/usr/lib/cgit/cgit.cgi/"

    <Files "git-http-backend">
      Require all granted

    <Directory "/usr/share/webapps/cgit/">
      AllowOverride None
      Options None
      Require all granted

    <Directory "/usr/lib/cgit/">
      AllowOverride None
      Options ExecCGI FollowSymlinks
      Require all granted

    ErrorLog "/var/log/httpd/"
    CustomLog "/var/log/httpd/" common

SSLCertificateFile /etc/letsencrypt/live/
SSLCertificateKeyFile /etc/letsencrypt/live/
Include /etc/letsencrypt/options-ssl-apache.conf

Don’t forget to restart Apache for changes to take effect! That’s all, hope you like your new git server!

If you found any mistakes, or that something is outdated, badly explained or you have something to add, feel free to contact me.