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-okdosyası olan repolar erişilebilir olur. Bu değişkenle tüm repolar açılır - ScriptAlias:
/git/ile gelen tüm isteklerigit-http-backendCGI 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_deflateaktif 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!