Ein eigener Git Server bietet volle Kontrolle über Ihre Code-Repositories. Von einfachen Bare-Repositories bis zu kompletten Lösungen wie Gitea oder GitLab.
Bare Repository (Einfachste Methode)
Repository erstellen
# Verzeichnis erstellen
mkdir -p /srv/git/projekt.git
cd /srv/git/projekt.git
# Bare Repository initialisieren
git init --bare
# Berechtigungen
chown -R git:git /srv/gitGit-User erstellen
# Benutzer für Git-Zugriff
useradd -m -s /usr/bin/git-shell git
# SSH-Verzeichnis
mkdir -p /home/git/.ssh
chmod 700 /home/git/.ssh
# Authorized Keys
touch /home/git/.ssh/authorized_keys
chmod 600 /home/git/.ssh/authorized_keys
chown -R git:git /home/git/.sshSSH-Key hinzufügen
# Öffentlichen Schlüssel hinzufügen
echo "ssh-rsa AAAA... user@host" >> /home/git/.ssh/authorized_keysRepository nutzen
# Klonen
git clone git@server:/srv/git/projekt.git
# Remote hinzufügen
git remote add origin git@server:/srv/git/projekt.git
git push -u origin mainGit Daemon (Read-Only)
Installation und Konfiguration
# Systemd Service
cat > /etc/systemd/system/git-daemon.service << EOF
[Unit]
Description=Git Daemon
After=network.target
[Service]
ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/
Restart=always
User=git
Group=git
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now git-daemonRepository freigeben
# Datei erstellen für Export
touch /srv/git/projekt.git/git-daemon-export-okKlonen via Git-Protokoll
git clone git://server/projekt.gitGitea (Leichtgewichtiger Git Server)
Installation mit Docker
# docker-compose.yml
version: "3"
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea
volumes:
- ./gitea-data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:22"
depends_on:
- db
restart: always
db:
image: postgres:15
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea
- POSTGRES_DB=gitea
volumes:
- ./postgres-data:/var/lib/postgresql/data
restart: alwaysNative Installation
# Benutzer erstellen
useradd -m -s /bin/bash git
# Binary herunterladen
wget -O /usr/local/bin/gitea https://dl.gitea.io/gitea/1.21/gitea-1.21-linux-amd64
chmod +x /usr/local/bin/gitea
# Verzeichnisse
mkdir -p /var/lib/gitea/{custom,data,log}
mkdir -p /etc/gitea
chown -R git:git /var/lib/gitea /etc/gitea
chmod 750 /etc/giteaSystemd Service
# /etc/systemd/system/gitea.service
[Unit]
Description=Gitea
After=network.target postgresql.service
Wants=postgresql.service
[Service]
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
[Install]
WantedBy=multi-user.targetWeb-Setup
http://server:3000/install
Einstellungen:
- Datenbank: PostgreSQL/MySQL/SQLite
- SSH Port: 22 oder 2222
- Repository Root: /var/lib/gitea/repositories
- Admin-Account erstellenGitLab (Enterprise Features)
Docker Installation
# docker-compose.yml
version: '3.6'
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab
hostname: gitlab.example.com
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://gitlab.example.com'
gitlab_rails['gitlab_shell_ssh_port'] = 2222
nginx['listen_port'] = 80
nginx['listen_https'] = false
letsencrypt['enable'] = false
ports:
- '80:80'
- '2222:22'
volumes:
- ./gitlab-config:/etc/gitlab
- ./gitlab-logs:/var/log/gitlab
- ./gitlab-data:/var/opt/gitlab
restart: alwaysPackage Installation
# Debian/Ubuntu
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | bash
apt install gitlab-ce
# Konfigurieren
vi /etc/gitlab/gitlab.rb
# external_url 'https://gitlab.example.com'
# Anwenden
gitlab-ctl reconfigureInitiales Passwort
# Root-Passwort anzeigen
cat /etc/gitlab/initial_root_password
# Oder bei Docker
docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_passwordSSH-Konfiguration
Server-seitig
# /etc/ssh/sshd_config
# Git-User darf nur git-shell nutzen
Match User git
AllowTcpForwarding no
X11Forwarding no
PermitTTY no
ForceCommand /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"Client-seitig
# ~/.ssh/config
Host gitserver
HostName server.example.com
User git
IdentityFile ~/.ssh/id_git
Port 22
# Nutzung
git clone gitserver:projekt.gitNginx Reverse Proxy
Für Gitea
# /etc/nginx/sites-available/gitea
server {
listen 80;
server_name git.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name git.example.com;
ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket Support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 100M;
}
}Für GitLab
server {
listen 443 ssl http2;
server_name gitlab.example.com;
ssl_certificate /etc/letsencrypt/live/gitlab.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/gitlab.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 300;
proxy_connect_timeout 300;
client_max_body_size 250M;
}
}Hooks
Server-seitige Hooks
# /srv/git/projekt.git/hooks/post-receive
#!/bin/bash
while read oldrev newrev refname; do
branch=$(echo $refname | cut -d'/' -f3)
if [ "$branch" == "main" ]; then
# Deploy ausführen
cd /var/www/html
git pull origin main
echo "Deployed to production"
fi
donePre-receive Hook
#!/bin/bash
# /srv/git/projekt.git/hooks/pre-receive
# Commit-Message prüfen
while read oldrev newrev refname; do
for commit in $(git rev-list $oldrev..$newrev); do
msg=$(git log --format=%B -n 1 $commit)
if ! [[ "$msg" =~ ^(feat|fix|docs|style|refactor|test|chore): ]]; then
echo "Commit message must start with type: $msg"
exit 1
fi
done
doneBackup
Bare Repositories
#!/bin/bash
# /usr/local/bin/git-backup.sh
BACKUP_DIR="/backup/git"
GIT_DIR="/srv/git"
DATE=$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
for repo in $GIT_DIR/*.git; do
name=$(basename $repo)
tar -czf "$BACKUP_DIR/${name%.git}_$DATE.tar.gz" -C $GIT_DIR $name
done
# Alte Backups löschen
find $BACKUP_DIR -mtime +30 -deleteGitea Backup
# Als gitea-User
sudo -u git gitea dump -c /etc/gitea/app.ini
# Erstellt gitea-dump-*.zip mit:
# - Datenbank
# - Repositories
# - KonfigurationGitLab Backup
# Backup erstellen
gitlab-backup create
# Backups finden
ls /var/opt/gitlab/backups/
# Restore
gitlab-backup restore BACKUP=11234567890_2024_01_15_16.0.0Migration
Von GitHub/GitLab zu eigenem Server
# Mirror-Clone
git clone --mirror https://github.com/user/repo.git
# Zu neuem Server pushen
cd repo.git
git push --mirror git@newserver:/srv/git/repo.gitImport in Gitea
1. Neues Repository erstellen
2. "Migration" wählen
3. URL eingeben
4. Token für private ReposZusammenfassung
| Lösung | Komplexität | Features | |--------|-------------|----------| | Bare Repository | Niedrig | Nur Git | | Git Daemon | Niedrig | Read-only | | Gitea | Mittel | Web UI, Issues, CI | | GitLab | Hoch | Enterprise, CI/CD |
| Port | Dienst | |------|--------| | 22/2222 | SSH (Git) | | 3000 | Gitea Web | | 80/443 | GitLab/Gitea Web | | 9418 | Git Daemon |
| Befehl | Funktion | |--------|----------| | git init --bare | Bare Repo erstellen | | gitea dump | Gitea Backup | | gitlab-backup create | GitLab Backup |
Fazit
Für kleine Teams reicht oft ein einfaches Bare Repository mit SSH-Zugang. Gitea bietet ein hervorragendes Preis-Leistungs-Verhältnis mit modernem Web-Interface und geringem Ressourcenverbrauch. GitLab ist die richtige Wahl für größere Teams, die Enterprise-Features wie CI/CD und Issue-Tracking benötigen. In jedem Fall ist ein durchdachtes Backup-Konzept essentiell.