Gerrit GIT Code Review

Gerrit Code Review Server Installation mit apache2 als SSL Proxy und ssh Zugang über knockd. Gerrit hat keine eigene Benutzer Registrierung/Verwaltung und greift dafür auf externe Dienste wie openid, ldap, oauth, http, … zurück. Da ich nicht jedem erlauben will sich anzumelden und mir die Konfiguration eines LDAP Servers als zu kompliziert erschien, erfolgt die Anmeldung über den apache2 server mittels http auth.

Vorraussetzungen sind ein laufender/funktionierender apache2, mariadb (mysql) und iptables Dienst sowie ein letsencrypt SSL Zertifikat, auf die wird hier nicht näher eingegangen.

Installation

Pakete aus den Linux Manjaro (Arch) Paketquellen installieren. Gerrit ist in den AUR Paketquellen enthalten und kann mittels yaourt installiert werden, wovon die folgenden Schritte ausgehen. Alternativ kann man sich auch gerrit von der Webseite herunterladen.

sudo pacman -S jre8-openjdk-headless jre8-openjdk gnu-netcat knockd
trizen -S gerrit

Konfiguration

Mysql

Anlegen des Benutzers gerrit mit Passwort secret und der Datenbank gerrit mit Zeichensatz UTF-8.

CREATE USER 'gerrit'@'localhost' IDENTIFIED BY 'secret';
CREATE DATABASE gerrit;
ALTER DATABASE gerrit charset=utf8;
GRANT ALL ON gerrit.* TO 'gerrit'@'localhost';
FLUSH PRIVILEGES;

Gerrit

Nutzer gerrit in Linux anlegen und Benutzer:Gruppe für Verzeichnis /var/lib/gerrit ändern. Danach meldet man sich als gerrit an und startet die Konfiguration.

sudo adduser gerrit
sudo chown gerrit:gerrit -R /var/lib/gerrit
sudo su - gerrit
java -jar /usr/share/java/gerrit/gerrit.war init -d /var/lib/gerrit

Die Konfiguration fragt diverse Dinge und erstellt am Ende die Datei /var/lib/gerrit/etc/gerrit.config. In meiner Datei steht folgendes, da kann rauslesen was ich bei welchem Schritt angegeben habe. Falls man nochmal etwas ändern will, kann man das direkt über die Datei machen, oder man startet die Konfiguration einfach nochmal. Die alte Konfiguration wird geladen, so das man nicht wieder alles eingeben muss, sondern selektiv etwas ändern kann!

[gerrit]
        basePath = /srv/gerrit
        serverId = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
        canonicalWebUrl = https://review.example.com/
[database]
        type = mysql
        hostname = localhost
        database = gerrit
        username = gerrit
[index]
        type = LUCENE
[auth]
#       type = development_become_any_account
        type = HTTP
        logoutUrl = https://logout@review.example.com
[receive]
        enableSignedPush = false
[sendemail]
        smtpServer = localhost
        from = MIXED
[container]
        user = gerrit
        javaHome = /usr/lib/jvm/java-8-openjdk/jre
[sshd]
        listenAddress = *:29418
[httpd]
        listenUrl = proxy-https://127.0.0.1:8443/
[cache]
        directory = cache

Wenn die Konfiguration abgeschlossen ist, kann man gerrit starten, als User gerrit!

sudo su - gerrit
/var/lib/gerrit/bin/gerrit.sh start

Apache2

Damit man das Zertifikat von letsencrypt bei laufendem Server aktualiseren kann, braucht man einen Virtualhost für Port 80 (http) und einen für Port 443 (https). Alle unverschlüsselten Anfragen (http), bis auf die zur Zertifikats Aktualisierung (Untervereichnis .well-known), sollen auf https umgeleitet werden.

Damit ergeben sich folgende Konfigurationen für den Servernamen review.example.com:

<VirtualHost *:80>
    ServerAdmin webmaster@example.com
    DocumentRoot "/srv/http/gerrit"
    ServerName review.example.com
    ErrorLog "/var/log/httpd/review.example.com_error.log"
    CustomLog "/var/log/httpd/review.example.com_access.log" common

    RewriteEngine On
    RewriteCond %{HTTPS} off
    # Redirect all hits except for Let's Encrypt's ACME Challenge verification  
    RewriteCond %{REQUEST_URI} !^/\.well\-known/
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    <Directory "/srv/http/gerrit">
        AllowOverride All
        Options FollowSymlinks
        Require all granted
    </Directory>
</VirtualHost>
<VirtualHost *:443>
    ServerAdmin webmaster@example.com
    DocumentRoot "/srv/http/gerrit"
    ServerName review.example.com
    ErrorLog "/var/log/httpd/review.example.com_error_ssl.log"
    CustomLog "/var/log/httpd/review.example.com_access_ssl.log" common

    SSLEngine On
    SSLProtocol All -SSLv2 -SSLv3
    SSLCertificateFile    /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

    # Authentication directory for letsencrypt certificate
    ProxyPass /.well-known !
    <Directory "/srv/http/gerrit/.well-known">
        Options -Indexes
        Require all granted
    </Directory>

    ProxyRequests Off
    ProxyVia Off
    ProxyPreserveHost On

    <Proxy *>
        Require all granted
    </Proxy>

    <Location />
        AuthType Basic
        AuthName "Gerrit Code Review"
        AuthUserFile /etc/httpd/passwords_gerrit
        Require valid-user
    </Location>

    # path for repository downloads over https with authentication over gerrit
    <Location /a/>
        Require all granted
    </Location>

    AllowEncodedSlashes On
    ProxyPass / http://127.0.0.1:8443/
</VirtualHost>

Knockd

Gerrit hat seinen eigenen SSH Server zur Kommunikation mit GIT. Damit dieser nicht völlig offen dem Internet ausgesetzt ist, ist er in iptables nicht freigegeben. Stattdessen wird er Port temporär für 10 Sekunden durch knockd geöffnet. Die Knocking Ports 4444,6666,7777 sind nur Beispiele und sollten anders gewählt werden.

[opencloseSSHgerrit]
      sequence      = 4444,6666,7777
      seq_timeout   = 15
      tcpflags      = syn
      start_command = /usr/sbin/iptables -I INPUT -s %IP% -p tcp --dport 29418 -j ACCEPT
      cmd_timeout   = 10
      stop_command  = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 29418 -j ACCEPT

SSH Client

Damit das freischalten vom Gerrit SSH Port automatisch funktioniert, wenn man z.B. git fetch gerrit  schreibt, muss man folgendes in der lokalen (nicht auf dem Server) ~/.ssh/config ergänzen:

Host review.example
    User mustermann
    Hostname review.example.com
    Port 29418
    ProxyCommand bash -c 'knock review.example.com 4444 6666 7777 -d 200; sleep 1; nc %h %p'

Der User, Hostname, Port und die Knocking Ports müsst ihr entsprechend eurer Konfiguartion ändern.

GIT Kommandos

Nun kann man GIT ganz normal per ssh bedienen, knock schaltet den Gerrit SSH Port im Hintergrund frei.

git clone ssh://review.example/<PROJECT>
git remote add gerrit ssh://review.example/<PROJECT>
git fetch gerrit
git push gerrit HEAD:refs/for/master