Cgit solution for my network
History
Experimentation using gitweb and cgit was carried out on d2-02a at some point before 2020-10. Cgit on Devuan (d2-02a) was examined after investigating a key Stackoverflow post and determined to meet my needs.
Overview
Git-scm itself provides native mechanisms to allow operations through http, and basic Apache httpd configuration examples abound. Adding a decent web frontend with cgit is a small additional step. This setup also uses Apache httpd basic auth to limit read and write access to the true git projects, but not the cgit simple http clone operations.
Prerequisites
Apache httpd is installed. TLS certificate exists and is already in use.
Installing entire cgit solution
Installing and configuring cgit
Install cgit from stackrpms repo for el8, which uses https://src.fedoraproject.org/fork/tmz/rpms/cgit or https://src.fedoraproject.org/forks/tmz/rpms/cgit.git to build the rpm. Tmz is the Fedora maintainer of this package, so his adaptation of it for el8 is trustworthy.
sudo dnf install cgit
Modify /etc/cgitrc
with my own customizations. See internal file
/mnt/public/Support/Programs/cgit/files/cgitrc for the original configuration.
Install a few dependencies. Python3-markdown is also from stackrpms for el8,
because I had to build it on my
copr, also from its source https://src.fedoraproject.org/rpms/python-markdown.
sudo dnf install python3-pygments python3-markdown
These dependencies support displaying markdown (.md) files as the cgit and
repo "about" pages. I tend to use markdown for these types of files. Copy in a
logo file for myself to /usr/share/cgit/bgstack15_64.png
. The top-level
readme file is configured in the example cgitrc to /var/www/git/readme.md
Configuring httpd
Set up file /etc/git_access.conf
with snippets that will be included by the
httpd config. This file will control access to the git repositories over git
itself, not the cgit web presentation.
# File /etc/git_access.conf
# Part of cgit solution for Mersey network, 2021-04-15
# The last phrase can be "all granted" to allow anybody to read.
# Use httpd "Require" strings for param2, param3. Param2 grants read/write permission, Param3 is read-only.
#Use Project dirname "user alice bob charlie" "all granted"
#Use Project dirname "user charlie" "user bob alice"
Use Project certreq "user bgstack15" "all granted"
In the above example, the "certreq" is a project name (directory name under
/var/www/git). The second and third parameters, the "user bgstack15" and "all
granted" will be passed to Apache "Require" directives. They represent "read-
write access" and "read-only access" respectively. Apache interprets the
example, resolved "Required all granted" as anonymous read access is allowed.
One of the main operations described under the Operations heading below is
adding new entries to this list of projects. Set up file /etc/gitweb.conf
which is traditionally for gitweb, a different implementation of serving git
repos over http, but can also be used here.
$export_auth_hook = sub {
my $repo = shift;
my $user = $cgi->remote_user;
if($repo =~ s/\/var\/www\/git\///) {
open FILE, '/etc/git_access.conf';
while(<FILE>) {
if ($_ =~ m/Use Project $repo \"(.*)\" \"(.*)\"/)
{
my $users = $1 . ' ' . $2;
$users =~ s/all granted/$user/;
$users =~ s/user//;
if ( $users =~ m/$user/ ) {
return 1;
}
}
}
}
return 0;
};
I do not understand this perl file: It came straight from reference
2. Set up file
/etc/git_access
with htpasswd(1).
sudo htpasswd -c /etc/git_access bgstack15
Set up file /etc/httpd/conf.d/cgit.conf
with modifications. This file is
laid down by the cgit rpm, but might need some adjustments. The exact contents
as of the time of this writing are the following.
Alias /cgit-data /usr/share/cgit
ScriptAlias /cgit /var/www/cgi-bin/cgit
RedirectMatch ^/cgit$ /git/
<Directory "/usr/share/cgit/">
AllowOverride None
Require all granted
</Directory>
Set up the apache virtualhost. For server storage1, this means modifying
extant file /etc/httpd/conf.d/local_mirror.conf
. Inside the main VirtualHost
definition (the port 80 one), add contents:
# cgit + git. See /mnt/public/Support/Programs/cgit/cgit-README.md
SetEnv GIT_PROJECT_ROOT /var/www/git
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv REMOTE_USER=$REDIRECT_REMOTE_USER
SetEnv GITWEB_CONFIG /etc/gitweb.conf
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
<Directory "/usr/libexec/git-core*">
Options +ExecCGI +Indexes
Order allow,deny
Allow from all
Require all granted
</Directory>
# a2enmod macro # for Devuan
<Macro Project $repository $rwstring $rostring>
<LocationMatch "^/git/$repository.*$">
AuthType Basic
AuthName "Git Access"
AuthUserFile /etc/git_access
Require $rwstring
Require $rostring
</LocationMatch>
<LocationMatch "^/git/$repository/git-receive-pack$">
AuthType Basic
AuthName "Git Access"
AuthUserFile /etc/git_access
Require $rwstring
</LocationMatch>
</Macro>
# Devuan apache2 works with IncludeOptional but EL8 httpd doesn't work with it.
Include /etc/git_access.conf
# https://ic3man5.wordpress.com/2013/01/26/installing-cgit-on-debian/
# depends on conf-enabled/cgit.conf (available as cgit.conf.devuan)
<Directory "/usr/share/cgit/">
SetEnv CGIT_CONFIG /etc/cgitrc
SetEnv GIT_URL cgit
AllowOverride all
Options +ExecCGI +FollowSymLinks +Indexes
DirectoryIndex cgit.cgi
AddHandler cgi-script .cgi
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /cgit/cgit.cgi/$1 [END,QSA]
</Directory>
After making changes to these files, test (sudo httpd -t), and then reload or restart httpd.
Configure SELinux
I used the standard mechanisms to troubleshoot SELinux.
sudo setenforce 0
semodule --disable_dontaudit --build
echo "" | sudo tee /var/log/audit/audit.log 1>/dev/null
# perform a large number of git and cgit operations
sudo tail -n15000 /var/log/audit/audit.log | audit2allow -M foo
# manually merge any new entries into cgitmersey.te
semodule --build
_func() {sudo checkmodule -M -m -o cgitmersey.mod cgitmersey.te && sudo semodule_package -o cgitmersey.pp -m cgitmersey.mod && sudo semodule -i cgitmersey.pp ; } ; time _func
Final asset is cgitmersey.te
which can be loaded and installed with the last
line of the above command block.
module cgitmersey 1.0;
require {
type git_script_t;
type httpd_t;
type httpd_cache_t;
type var_t;
class process { noatsecure rlimitinh siginh };
class file { getattr map open read };
class dir { getattr open read search };
}
#============= git_script_t ==============
allow git_script_t var_t:dir read;
allow git_script_t var_t:file { read getattr open };
allow git_script_t httpd_cache_t:dir { getattr open read search };
allow git_script_t httpd_cache_t:file { map getattr open read };
#============= httpd_t ==============
allow httpd_t git_script_t:process { noatsecure rlimitinh siginh };
Populating cgit with my content
See separate blog post Populating my New Cgit Instance for this whole task.
Summary of associated files
- /etc/gitweb.conf
- /usr/share/cgit/bgstack15_64.png
- /etc/git_access.conf
- /etc/git_access
-
/etc/cgitrc
cache-size=300
clone-prefix=https://www.example.com/git css=/cgit-data/cgit.css
Disable owner on index page
enable-index-owner=0 enable-index-links=1
Allow http transport git clone
enable-http-clone=1
Show extra links for each repository on the index page
enable-index-links=0
Enable blame page and create links to it from tree page
enable-blame=0
Enable ASCII art commit history graph on the log pages
enable-commit-graph=0
Show number of affected files per commit on the log pages
enable-log-filecount=0
Show number of added/removed lines per commit on the log pages
enable-log-linecount=0
Sort branches by age or name
branch-sort=name
favicon=/favicon.ico
Use a custom logo
logo=/cgit-data/bgstack15_64.png
Enable statistics per week, month, quarter, or year
max-stats=
Set the title and heading of the repository index page
root-title=Stackrpms git root-readme=/var/www/git/readme.md root-desc=Bgstack15 local repos
Allow download of tar.gz, tar.bz2 and zip-files
snapshots=tar.gz tar.bz2 zip 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 (requires the highlight package)
source-filter=/usr/libexec/cgit/filters/syntax-highlighting.sh
Format markdown, restructuredtext, manpages, text files, and html files
through the right converters
about-filter=/usr/libexec/cgit/filters/about-formatting.sh 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 section-from-path=1 enable-subject-links=1 virtual-root=/cgit/ scan-path=/var/www/git/
-
/etc/httpd/conf.d/cgit.conf
- /var/www/git/readme.md
- /mnt/public/Support/Programs/cgit/cgitmersey.te
Operations
Some useful operations are described here.
Making a new project
To set up a new project that can receive pushes, you need to initialize a new git bare repo. Make the "newname" project in /var/www/git, and grant access to the apache user.
cd /var/www/git ; git init --bare newname ; sudo chgrp apache -R newname
Set up permissions for the new project in /etc/git_access.conf
. For example:
Use Project "newname" "user adminuser1 adminuser2 adminuser3" "user1 user2 user3"
After making changes, ensure httpd accepts the new config (because it loads /etc/git_access.conf as an included file), and then reload httpd.
sudo httpd -t
sudo systemctl reload httpd
Changing cgit-related attributes of a project
Cgit can be configured to read a file named cgitrc
within a git repository.
I tend to use just the top directory of these bare git repos, so for project
certreq, use /var/www/git/certreq/cgitrc
. See cgitrc(5) for more info, but a
brief list of useful attributes (var=value) include: defbranch, desc, hide,
homepage, ignore, logo, name, owner, readme, section, url. For the description
of a repo that appears in the main index, use regular file in a git bare repo:
description
.
Adding a new user
Use regular htpasswd mechanism to add users or change passwords. See htpasswd(1).
htpasswd /etc/git_access bgstack15
Removing a project
Just delete the project directory.
Changing cgitrc values
Changing cgitrc values take effect immediately (when caching is set to 0); no httpd reload is necessary.
References
- https://stackoverflow.com/questions/26734933/how-to-set-up-git-over-http git_access.conf
- https://stackoverflow.com/a/50317063/3569534 /etc/gitweb.conf and httpd.conf macro and other snippets
- https://stackoverflow.com/questions/40924641/setting-up-git-http-backend-with-apache-2-4
- https://stackoverflow.com/a/2200662/3569534 had to convert my sample project to a bare git one
Comments