Apache ile Git Smart HTTP Sunucusu Kurulumu

Ekip içinde kod paylaşmak, versiyon kontrolü yapmak ve özellikle iç ağda kendi Git sunucunuzu işletmek istiyorsanız, Apache üzerinde Git Smart HTTP protokolünü kullanmak son derece pratik bir çözüm. GitHub veya GitLab gibi platformlara bağımlı kalmadan, tam kontrol sizde olacak şekilde kurumsal ya da kişisel bir Git sunucusu kurabilirsiniz. Bu yazıda adım adım Apache ile Git Smart HTTP sunucusu kuracağız, kimlik doğrulaması ekleyeceğiz ve gerçek dünya senaryolarına göre yapılandıracağız.

Git Smart HTTP Nedir?

Git, uzak repolarla iletişim kurmak için birkaç farklı protokol destekler: SSH, Git protokolü ve HTTP/HTTPS. Smart HTTP, Git 1.6.6 ile gelen ve dumb HTTP’nin aksine çift yönlü iletişime izin veren bir yöntem. Yani hem git clone hem de git push işlemlerini HTTP üzerinden yapabiliyorsunuz.

Dumb HTTP sadece statik dosyaları sunar ve salt okunur erişim sağlar. Smart HTTP ise arkada git-http-backend adlı bir CGI betiği çalıştırır ve Git protokolünü tam anlamıyla HTTP üzerinden taklit eder. Firewall geçişi, HTTPS şifreleme, HTTP kimlik doğrulaması gibi avantajlar sayesinde özellikle kurumsal ortamlarda çok tercih edilen bir çözümdür.

Gereksinimler

Başlamadan önce şunların hazır olması gerekiyor:

  • Ubuntu 20.04/22.04 veya CentOS/RHEL 8+ sistemi
  • Apache 2.4+ kurulu ya da kurulabilir durumda
  • Git paketi kurulu
  • Root veya sudo yetkisi
  • Tercihen bir alan adı veya iç DNS kaydı

Apache ve Git Kurulumu

Önce sistemi güncelleyip gerekli paketleri kuralım.

Ubuntu/Debian için:

sudo apt update && sudo apt upgrade -y
sudo apt install apache2 git -y

CentOS/RHEL için:

sudo dnf update -y
sudo dnf install httpd git -y
sudo systemctl enable httpd
sudo systemctl start httpd

Kurulum tamamlandıktan sonra Apache’nin çalıştığını doğrulayalım:

sudo systemctl status apache2    # Ubuntu
sudo systemctl status httpd      # CentOS

Gerekli Apache Modüllerini Etkinleştirme

Git Smart HTTP, Apache’nin CGI desteğine ihtiyaç duyar. Bunun yanı sıra kimlik doğrulaması için mod_auth_basic ve erişim kontrolü için mod_authz_groupfile modüllerini de etkinleştireceğiz.

sudo a2enmod cgi alias env auth_basic authn_file
sudo systemctl restart apache2

CentOS’ta bu modüller genellikle varsayılan olarak yüklü gelir, ayrıca etkinleştirmenize gerek yoktur. Ama kontrol etmek için:

httpd -M | grep -E "cgi|alias|env|auth"

Git Repolarının Dizin Yapısını Oluşturma

Repolarımızı düzenli tutmak için uygun bir dizin yapısı kuralım. Ben /srv/git dizinini kullanmayı tercih ediyorum, ama /var/git veya /opt/git de olur.

sudo mkdir -p /srv/git
sudo chown -R www-data:www-data /srv/git    # Ubuntu
# CentOS için:
# sudo chown -R apache:apache /srv/git
sudo chmod 2775 /srv/git

Şimdi ilk test repomuzу oluşturalım. Git Smart HTTP için repolar --bare formatta olmalı:

sudo -u www-data git init --bare /srv/git/proje1.git
sudo -u www-data git init --bare /srv/git/proje2.git

Bare repo oluşturduğumuzda dizin içeriği şöyle görünmeli:

ls -la /srv/git/proje1.git/
# HEAD  branches  config  description  hooks  info  objects  refs

Önemli bir nokta: Bare repolarda git-http-backend‘in düzgün çalışması için http.receivepack ayarını etkinleştirmemiz gerekiyor. Bu olmadan push işlemleri çalışmaz.

sudo -u www-data git -C /srv/git/proje1.git config http.receivepack true

Bunu her repo için tek tek yapmak yerine, tüm repolar için geçerli olacak bir script yazabiliriz. Ama önce Apache konfigürasyonunu tamamlayalım.

Apache VirtualHost Konfigürasyonu

/etc/apache2/sites-available/git.conf (Ubuntu) ya da /etc/httpd/conf.d/git.conf (CentOS) adında bir konfigürasyon dosyası oluşturalım:

sudo nano /etc/apache2/sites-available/git.conf

Aşağıdaki konfigürasyonu dosyaya yapıştırın:

<VirtualHost *:80>
    ServerName git.sirket.local
    ServerAlias git.sirket.com

    DocumentRoot /var/www/html

    SetEnv GIT_PROJECT_ROOT /srv/git
    SetEnv GIT_HTTP_EXPORT_ALL

    ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

    <Directory "/usr/lib/git-core/">
        Options ExecCGI Indexes
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>

    <LocationMatch "^/git/.*/git-receive-pack$">
        AuthType Basic
        AuthName "Git Repository"
        AuthUserFile /etc/apache2/git-htpasswd
        Require valid-user
    </LocationMatch>

    <LocationMatch "^/git/.*/git-upload-pack$">
        AuthType Basic
        AuthName "Git Repository"
        AuthUserFile /etc/apache2/git-htpasswd
        Require valid-user
    </LocationMatch>

    ErrorLog ${APACHE_LOG_DIR}/git-error.log
    CustomLog ${APACHE_LOG_DIR}/git-access.log combined
</VirtualHost>

Bu konfigürasyonda birkaç önemli nokta var:

  • GIT_PROJECT_ROOT: Git repolarımızın bulunduğu ana dizini Apache’ye bildiriyor
  • GIT_HTTP_EXPORT_ALL: Bu değişken olmadan sadece git-daemon-export-ok dosyası olan repolar erişilebilir olur. Bu değişkenle tüm repolar açılır
  • ScriptAlias: /git/ ile gelen tüm istekleri git-http-backend CGI betiğine yönlendiriyor
  • LocationMatch: Push ve pull işlemlerine kimlik doğrulaması ekliyoruz

CentOS’ta git-http-backend farklı bir konumda olabilir. Nerede olduğunu bulalım:

which git-http-backend
# ya da
find / -name "git-http-backend" 2>/dev/null

CentOS’ta genellikle /usr/libexec/git-core/git-http-backend konumundadır. Konfigürasyonu buna göre güncelleyin.

Şimdi siteyi etkinleştirelim:

sudo a2ensite git.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

Kimlik Doğrulama Ayarları

Kimlik doğrulaması için htpasswd aracını kullanacağız. İlk kullanıcıyı oluşturalım:

sudo htpasswd -c /etc/apache2/git-htpasswd ahmet
# Şifre girmenizi isteyecek

# Sonraki kullanıcılar için -c parametresi OLMADAN kullanın
sudo htpasswd /etc/apache2/git-htpasswd mehmet
sudo htpasswd /etc/apache2/git-htpasswd ayse

Dosyanın içeriğini kontrol edelim:

sudo cat /etc/apache2/git-htpasswd
# ahmet:$apr1$xyz...
# mehmet:$apr1$abc...

Dosya izinlerini düzeltelim:

sudo chown www-data:www-data /etc/apache2/git-htpasswd
sudo chmod 640 /etc/apache2/git-htpasswd

Repoya İlk Commit ve Test

Şimdi her şeyin çalışıp çalışmadığını test edelim. Önce local makinemizde:

mkdir /tmp/test-clone
cd /tmp/test-clone
git clone http://[email protected]/git/proje1.git
# Şifre soracak, giriyoruz
cd proje1
echo "# Proje 1" > README.md
git add .
git commit -m "İlk commit"
git push origin master

Eğer push başarısız olursa, repoda http.receivepack ayarını kontrol edin:

sudo -u www-data git -C /srv/git/proje1.git config http.receivepack true

Ya da tüm repolar için bu ayarı global yapmak isterseniz:

sudo git config --system http.receivepack true

HTTPS ile Güvenli Bağlantı

Gerçek bir üretim ortamında HTTP yerine HTTPS kullanmalısınız. Let’s Encrypt ile ücretsiz sertifika alabiliriz:

sudo apt install certbot python3-certbot-apache -y
sudo certbot --apache -d git.sirket.com

Eğer iç ağda kullanıyorsanız ve Let’s Encrypt kullanamıyorsanız, self-signed sertifika oluşturun:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 
    -keyout /etc/ssl/private/git.key 
    -out /etc/ssl/certs/git.crt 
    -subj "/C=TR/ST=Istanbul/L=Istanbul/O=Sirket/CN=git.sirket.local"

Ardından Apache konfigürasyonunu HTTPS için güncelleyin:

<VirtualHost *:443>
    ServerName git.sirket.local

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/git.crt
    SSLCertificateKeyFile /etc/ssl/private/git.key

    SetEnv GIT_PROJECT_ROOT /srv/git
    SetEnv GIT_HTTP_EXPORT_ALL

    ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

    <Directory "/usr/lib/git-core/">
        Options ExecCGI Indexes
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>

    <LocationMatch "^/git/">
        AuthType Basic
        AuthName "Git Repository"
        AuthUserFile /etc/apache2/git-htpasswd
        Require valid-user
    </LocationMatch>

    ErrorLog ${APACHE_LOG_DIR}/git-ssl-error.log
    CustomLog ${APACHE_LOG_DIR}/git-ssl-access.log combined
</VirtualHost>

<VirtualHost *:80>
    ServerName git.sirket.local
    Redirect permanent / https://git.sirket.local/
</VirtualHost>

SSL modülünü etkinleştirip Apache’yi yeniden başlatalım:

sudo a2enmod ssl
sudo systemctl restart apache2

Repo Yönetimi için Yardımcı Script

Günlük operasyonlarda yeni repo oluşturmak, kullanıcı eklemek gibi işleri hızlandırmak için küçük bir bash script yazalım:

#!/bin/bash
# /usr/local/bin/git-repo-manager.sh

GIT_ROOT="/srv/git"
HTPASSWD_FILE="/etc/apache2/git-htpasswd"
GIT_USER="www-data"

function yeni_repo() {
    REPO_ADI="$1"
    if [ -z "$REPO_ADI" ]; then
        echo "Kullanim: $0 yeni-repo <repo-adi>"
        exit 1
    fi

    REPO_PATH="${GIT_ROOT}/${REPO_ADI}.git"

    if [ -d "$REPO_PATH" ]; then
        echo "Hata: $REPO_ADI zaten mevcut!"
        exit 1
    fi

    sudo -u $GIT_USER git init --bare "$REPO_PATH"
    sudo -u $GIT_USER git -C "$REPO_PATH" config http.receivepack true
    echo "description: $REPO_ADI" | sudo -u $GIT_USER tee "$REPO_PATH/description"
    echo "Repo olusturuldu: $REPO_PATH"
    echo "Klon URL: https://git.sirket.local/git/${REPO_ADI}.git"
}

function kullanici_ekle() {
    KULLANICI="$1"
    if [ -z "$KULLANICI" ]; then
        echo "Kullanim: $0 kullanici-ekle <kullanici-adi>"
        exit 1
    fi

    if [ -f "$HTPASSWD_FILE" ]; then
        htpasswd "$HTPASSWD_FILE" "$KULLANICI"
    else
        htpasswd -c "$HTPASSWD_FILE" "$KULLANICI"
    fi
    echo "Kullanici eklendi: $KULLANICI"
}

function repo_listesi() {
    echo "Mevcut repolar:"
    for repo in ${GIT_ROOT}/*.git; do
        REPO_ADI=$(basename "$repo" .git)
        BOYUT=$(du -sh "$repo" 2>/dev/null | cut -f1)
        echo "  - ${REPO_ADI} (${BOYUT})"
    done
}

case "$1" in
    "yeni-repo")
        yeni_repo "$2"
        ;;
    "kullanici-ekle")
        kullanici_ekle "$2"
        ;;
    "liste")
        repo_listesi
        ;;
    *)
        echo "Kullanim: $0 {yeni-repo|kullanici-ekle|liste}"
        exit 1
        ;;
esac
sudo chmod +x /usr/local/bin/git-repo-manager.sh

# Kullanim ornekleri:
sudo git-repo-manager.sh yeni-repo backend-api
sudo git-repo-manager.sh kullanici-ekle fatma
sudo git-repo-manager.sh liste

Erişim Kontrolü: Repo Bazlı İzinler

Farklı ekiplere farklı repolara erişim vermek isteyebilirsiniz. Bu senaryoda Apache konfigürasyonunu biraz genişletmemiz gerekiyor. Örneğin frontend ekibi sadece frontend repolarına, backend ekibi backend repolarına erişebilsin:

# Frontend ekibi için kullanicilar
sudo htpasswd /etc/apache2/frontend-users ali
sudo htpasswd /etc/apache2/frontend-users veli

# Backend ekibi için kullanicilar
sudo htpasswd /etc/apache2/backend-users osman
sudo htpasswd /etc/apache2/backend-users hatice

Apache konfigürasyonunda her repo için ayrı Location bloğu:

<LocationMatch "^/git/frontend">
    AuthType Basic
    AuthName "Frontend Git Repository"
    AuthUserFile /etc/apache2/frontend-users
    Require valid-user
</LocationMatch>

<LocationMatch "^/git/backend">
    AuthType Basic
    AuthName "Backend Git Repository"
    AuthUserFile /etc/apache2/backend-users
    Require valid-user
</LocationMatch>

Git Hooks ile Otomatik Deploy

Git Smart HTTP sunucusunun güzel yanlarından biri de server-side hook desteği. Örneğin her push sonrası otomatik olarak bir web uygulamasını güncelleyebilirsiniz. /srv/git/webapp.git/hooks/post-receive dosyasını oluşturalım:

#!/bin/bash
# post-receive hook

DEPLOY_DIR="/var/www/webapp"
BRANCH="refs/heads/main"

while read oldrev newrev refname; do
    if [ "$refname" = "$BRANCH" ]; then
        echo "Main branch'e push algilandi, deploy basliyor..."
        GIT_WORK_TREE=$DEPLOY_DIR git checkout -f main
        echo "Deploy tamamlandi: $DEPLOY_DIR"
        
        # Gerekirse servisi yeniden baslat
        # sudo systemctl restart webapp.service
    fi
done
sudo chmod +x /srv/git/webapp.git/hooks/post-receive
sudo chown www-data:www-data /srv/git/webapp.git/hooks/post-receive

Sorun Giderme

Kurulum sırasında karşılaşılan yaygın sorunlar ve çözümleri:

403 Forbidden hatası alıyorsanız:

# SELinux aktifse (CentOS) izinleri kontrol edin
sudo setsebool -P httpd_can_network_connect 1
sudo chcon -R -t httpd_sys_content_t /srv/git
sudo chcon -R -t httpd_sys_rw_content_t /srv/git

Push sırasında “Repository not found” hatası:

# Repo dizin izinlerini kontrol edin
ls -la /srv/git/
sudo chown -R www-data:www-data /srv/git/

CGI hatası alıyorsanız:

# git-http-backend yolunu dogrulayin
which git-http-backend
ls -la $(which git-http-backend)

# Apache error log inceleyin
sudo tail -f /var/log/apache2/git-error.log

SSL sertifika hatası (self-signed) için client tarafında:

# Gecici cozum olarak SSL dogrulamayi devre disi birakin
git config --global http.sslVerify false

# Ya da sadece bu sunucu icin
git config --global http.https://git.sirket.local.sslVerify false

Performans Önerileri

Repo sayısı ve kullanıcı sayısı arttıkça bazı optimizasyonlar gerekebilir:

  • git gc: Repolarınızda periyodik olarak çöp toplama yapın. Cron job ile her hafta git gc --auto çalıştırabilirsiniz
  • Apache KeepAlive: Büyük repolar için KeepAlive açık tutun, her istek için yeni bağlantı kurulmasını engelleyin
  • Compression: Apache’de mod_deflate aktif edin, Git nesneleri sıkıştırılmış olarak transfer edilsin
  • Disk I/O: Git repolarını ayrı bir disk bölümüne koyun, özellikle büyük binary dosyalar içeren repolar için SSD tercih edin
  • Git LFS: Büyük binary dosyalar için Git LFS kullanmayı düşünün, standart Git repolarının şişmesini önler

Sonuç

Apache ile Git Smart HTTP sunucusu kurmak göründüğü kadar karmaşık değil. Temel olarak git-http-backend CGI betiğini Apache’ye tanıtıyor, kimlik doğrulaması ekliyoruz ve repo dizin izinlerini düzgün ayarlıyoruz. Bu yapı küçük ve orta ölçekli ekipler için son derece yeterli.

GitHub Enterprise veya GitLab’ın getirdiği web arayüzü, pull request sistemi, CI/CD entegrasyonu gibi özellikler elbette burada yok. Ama tam kontrol sizde, dış bağımlılık yok, kurumsal veri dışarı çıkmıyor ve kaynak tüketimi son derece düşük. İç ağda izole çalışması gereken projeler, veri gizliliği hassas olan kurumlar ya da internet erişimi kısıtlı ortamlar için bu çözüm birebir.

Eğer web arayüzü de istiyorsanız, bu altyapının üzerine Gitweb veya cgit gibi hafif bir arayüz ekleyebilirsiniz. Ama o konu başka bir yazının konusu. Şimdilik sağlam ve çalışan bir Git Smart HTTP sunucunuz var, iyi kodlamalar!

Yorum yapın