Gitea mit Docker installieren: Dein eigener Git-Server (Schritt-für-Schritt-Anleitung)
Installiere Gitea mit Docker und Caddy als Reverse Proxy. Eine anfängerfreundliche Schritt-für-Schritt-Anleitung für deinen eigenen, leichtgewichtigen Git-Server.

Inhaltsverzeichnis
- Was du benötigst
- Schritt 1: Server-Vorbereitung und Docker-Installation
- Schritt 2: Gitea mit Docker Compose einrichten
- Schritt 3: Gitea-Erstkonfiguration (mit SQLite)
- Schritt 4: Robuste Installation mit PostgreSQL und Caddy Reverse Proxy
- Schritt 5: Backups einrichten
- Praktische Nutzung und Tipps
- Fazit
Habt ihr euch jemals gewünscht, eure Git-Repositories selbst zu hosten – ähnlich wie bei GitHub oder GitLab, aber vielleicht etwas leichtgewichtiger und mit voller Kontrolle auf eurem eigenen Server? In diesem Artikel zeige ich euch Schritt für Schritt, wie ihr Gitea, einen selbstgehosteten Open-Source-Git-Dienst, mit Docker auf eurem eigenen Server installiert. Gitea ist in Go geschrieben, was es performant und ressourcenschonend macht – perfekt für den Heimserver, kleine Teams oder den einzelnen Entwickler, der die Kontrolle über seinen Code behalten möchte.
Wir gehen den kompletten Weg gemeinsam durch: von der Docker-Einrichtung mit Docker Compose über die Konfiguration eines Reverse Proxies (ich nutze hier Caddy) bis hin zur ersten Einrichtung von Gitea selbst und wichtigen Überlegungen zum Backup.
Was du benötigst
Bevor wir starten, hier eine kurze Checkliste der Voraussetzungen:
- Ein Server: Das kann ein VPS bei einem Hoster wie Hetzner oder Netcup sein, oder aber auch euer Raspberry Pi oder ein anderer Server zu Hause. Wichtig ist, dass ihr SSH-Zugriff habt.
- Docker und Docker Compose: Müssen auf dem Server installierbar sein. Wir gehen die Installation gemeinsam durch.
- Eine Domain: Oder zumindest eine Subdomain, die auf die IP-Adresse eures Servers zeigt. Ohne Domain wird es schwierig, Gitea vernünftig und sicher zu erreichen.
- Ein Reverse Proxy: Ich zeige hier die Einrichtung mit Caddy. Wenn ihr aber bereits Nginx Proxy Manager oder Traefik nutzt, könnt ihr das natürlich auch verwenden. Das Prinzip bleibt dasselbe.
- (Optional) Homeserver ohne öffentliche IP: Falls ihr einen Homeserver benutzt, der nicht direkt aus dem Internet erreichbar ist, schaut euch meinen Blogpost zu Pangolin an.
Schritt 1: Server-Vorbereitung und Docker-Installation
Als Erstes verbinden wir uns mit unserem Server und bringen ihn auf den neuesten Stand. Ich nutze dafür VS Code mit der “Remote - SSH”-Erweiterung, aber jedes andere SSH-Terminal funktioniert genauso gut.
DNS-Check und SSH-Verbindung
Stellt sicher, dass eure Domain korrekt auf die IP-Adresse eures Servers zeigt. Ein einfacher ping
-Befehl im Terminal hilft dabei:
ping gitea.domain.de
Wenn die richtige IP-Adresse antwortet, ist alles bereit. Verbindet euch nun per SSH mit eurem Server.
ssh benutzername@DEINE_SERVER_IP
System-Update und Docker-Installation
Einmal auf dem Server eingeloggt, aktualisieren wir die Paketlisten und installierten Pakete:
sudo apt update
sudo apt upgrade -y
Obwohl Docker über die Standard-Paketquellen installiert werden kann, empfehle ich, das offizielle Installationsskript zu verwenden, um sicherzustellen, dass ihr die neueste Version erhaltet. Die offizielle Anleitung findet ihr auf der Docker-Website.
Hier sind die Befehle, um Docker und Docker Compose schnell einzurichten:
# Alte Docker-Versionen entfernen
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
# Installationspakete für Docker vorbereiten:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Füge das Docker-Repository hinzu:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# Docker-Pakete installieren:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
Überprüft die Installation mit:
docker -v
# Docker version 28.0.3, build ...
docker compose version
# Docker Compose version v2.32.0
Schritt 2: Gitea mit Docker Compose einrichten
Jetzt, da Docker läuft, können wir Gitea aufsetzen. Wir erstellen zuerst die nötige Ordnerstruktur.
# Erstellt einen Ordner für Gitea und wechselt hinein
mkdir gitea
cd gitea
# Erstellt einen Unterordner für persistente Daten
mkdir data
Erstellt nun eine docker-compose.yml
-Datei:
touch docker-compose.yml
Öffnet diese Datei und fügt den folgenden Inhalt ein. Wir orientieren uns an der offiziellen Docker-Anleitung von Gitea.
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:1.24
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: unless-stopped
networks:
- gitea
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:22"
Ein paar wichtige Anmerkungen zu dieser Konfiguration:
image: gitea/gitea:1.24
: Es ist eine bewährte Praxis, eine spezifische Hauptversion (wie1.24
) anstelle vonlatest
zu verwenden. Das verhindert unerwartete Breaking Changes bei Updates. Wenn ihrdocker compose pull
ausführt, erhaltet ihr immer noch Patch-Updates (z.B. von1.24.7
auf1.24.8
).USER_UID
&USER_GID
: Diese sollten mit der ID eures Benutzers auf dem Host-System übereinstimmen, um Berechtigungsprobleme mit den Volumes zu vermeiden. Findet eure IDs mit dem Befehlid
im Terminal heraus.volumes: - ./data:/data
: Wir mappen den lokalendata
-Ordner in den Container. Hier speichert Gitea alle seine Konfigurationen, Datenbanken (falls SQLite) und Repositories.ports
: Wir leiten den Web-Port3000
und den SSH-Port22
aus dem Container auf die Host-Ports3000
und2222
um. Der SSH-Port wird auf2222
gelegt, um Konflikte mit dem SSH-Dienst des Host-Systems zu vermeiden.
Startet nun den Container:
sudo docker compose up -d
Der Befehl lädt das Gitea-Image herunter und startet den Container im Hintergrund. Mit sudo docker stats
könnt ihr die Ressourcennutzung beobachten.
Schritt 3: Gitea-Erstkonfiguration (mit SQLite)
Öffnet nun euren Browser und navigiert zu http://DEINE_SERVER_IP:3000
. Ihr werdet von der Gitea-Installationsseite begrüßt.
Für ein einfaches Setup wählen wir SQLite3 als Datenbanktyp. Achtet darauf, den Pfad so anzupassen, dass er in unser gemapptes Volume schreibt:
- Datenbankpfad:
/data/gitea/gitea.db
Weitere wichtige Einstellungen:
- Seitentitel: Gebt eurer Instanz einen Namen, z.B. “Mein Gitserver”.
- Repository-Verzeichnis: Lasst es bei
/data/git/gitea-repositories
, damit es persistent gespeichert wird. - Basis-URL der Anwendung: Diese sollte
http://DEINE_SERVER_IP:3000/
sein. - Optionale Einstellungen: Deaktiviert die Benutzerregistrierung, wenn ihr die Instanz nur für euch nutzen wollt.
- Administratorkonto: Erstellt euer Admin-Konto ganz unten auf der Seite.
Klickt auf “Gitea installieren”. Nach einem kurzen Moment solltet ihr auf eurem brandneuen Gitea-Dashboard landen!
Ihr könnt jetzt euer erstes Repository erstellen und es wie von GitHub oder GitLab gewohnt nutzen.
Schritt 4: Robuste Installation mit PostgreSQL und Caddy Reverse Proxy
Die SQLite-Einrichtung ist einfach, aber für eine robustere und skalierbarere Lösung, besonders wenn mehrere Benutzer geplant sind, ist eine Datenbank wie PostgreSQL die bessere Wahl. Gleichzeitig möchten wir Gitea über eine sichere HTTPS-Domain erreichbar machen, anstatt über IP und Port.
Dazu fahren wir unsere jetzige Installation herunter und löschen die alten Daten, um sauber neu zu beginnen.
# Im gitea-Ordner
sudo docker compose down
# Alten Datenordner löschen und neu erstellen für einen sauberen Start
sudo rm -rf ./data
mkdir data
# Wir erstellen einen Ordner für die Datenbank
mkdir postgres
Docker Compose mit PostgreSQL anpassen
Wir erweitern unsere docker-compose.yml
, um einen PostgreSQL-Container hinzuzufügen.
networks:
gitea:
external: false
proxy:
external: true
services:
server:
image: gitea/gitea:1.24
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=ein_sicheres_passwort
restart: unless-stopped
networks:
- gitea
- proxy
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
depends_on:
db:
condition: service_healthy
db:
image: postgres:17
container_name: gitea-db
restart: unless-stopped
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=ein_sicheres_passwort
- POSTGRES_DB=gitea
networks:
- gitea
volumes:
- ./postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gitea -d gitea"]
interval: 10s
timeout: 5s
retries: 5
Wichtige Änderungen:
- Wir haben einen
db
-Service für PostgreSQL hinzugefügt und einenpostgres
-Ordner für dessen Daten erstellt (mkdir postgres
). - Die
environment
-Variablen imserver
-Service konfigurieren Gitea für die Verbindung zurdb
. Wichtig:HOST
istdb
, der Service-Name des Datenbankcontainers. depends_on
mitcondition: service_healthy
sorgt dafür, dass Gitea erst startet, wenn die Datenbank bereit ist.- Wir haben die
ports
entfernt und den Gitea-Container einem externenproxy
-Netzwerk hinzugefügt.
Caddy als Reverse Proxy einrichten
Caddy ist ein moderner Webserver, der automatisch HTTPS-Zertifikate von Let’s Encrypt bezieht und erneuert.
Erstellt zuerst das externe Docker-Netzwerk:
sudo docker network create proxy
Jetzt erstellen wir eine separate Ordnerstruktur für Caddy:
cd .. # Aus dem gitea-Ordner zurück
mkdir caddy
cd caddy
mkdir data config
touch docker-compose.yml Caddyfile
Fügt Folgendes in die caddy/docker-compose.yml
ein:
networks:
proxy:
external: true
services:
caddy:
image: caddy:latest
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data:/data
- ./config:/config
networks:
- proxy
Und in die Caddyfile
kommt die Konfiguration für den Reverse Proxy:
gitea.domain.de {
encode zstd gzip
reverse_proxy gitea:3000
}
- Ersetzt
gitea.domain.de
durch eure Domain. reverse_proxy gitea:3000
leitet alle Anfragen für diese Domain an den Gitea-Container (dessencontainer_name
gitea
ist) auf Port 3000 weiter.
Startet Caddy:
# Im caddy-Ordner
sudo docker compose up -d
Gitea mit der neuen Konfiguration starten
Wechselt zurück in den gitea
-Ordner und startet die Gitea- und Datenbank-Container:
# Im gitea-Ordner
sudo docker compose up -d
Navigiert jetzt zu eurer Domain (z.B. https://gitea.domain.de
). Ihr seht wieder die Installationsseite. Die Datenbankeinstellungen sollten bereits korrekt für PostgreSQL ausgefüllt sein. Passt die Server-Domain und die Gitea-Basis-URL an eure Domain an:
- Server-Domain:
gitea.domain.de
- Gitea-Basis-URL:
https://gitea.domain.de/
Schließt die Installation wie zuvor ab.
Schritt 5: Backups einrichten
Ein selbstgehosteter Dienst ist nur so gut wie sein Backup. Wir sichern zwei Dinge: die Gitea-Daten (Repositories, Konfiguration) und die PostgreSQL-Datenbank.
Den gitea/data
-Ordner könnt ihr mit einem Tool wie Duplicati sichern. Für die Datenbank fügen wir einen weiteren Service zu unserer gitea/docker-compose.yml
hinzu, der tägliche Dumps erstellt.
Fügt diesen Service am Ende eurer gitea/docker-compose.yml
hinzu:
# ... (innerhalb von services:)
backup:
image: postgres:17
container_name: gitea-db-backup
restart: unless-stopped
volumes:
- ./backup-db:/backup
networks:
- gitea
environment:
- PGHOST=db
- PGUSER=gitea
- PGPASSWORD=ein_sicheres_passwort
- PGDATABASE=gitea
- SLEEP_TIME=86400 # 24 Stunden in Sekunden
entrypoint: |
bash -c '
while true; do
echo "Erstelle Datenbank-Backup..."
pg_dump -Fc > /backup/gitea_dump_$(date +%Y-%m-%d_%H-%M-%S).dump
echo "Backup erstellt. Schlafe für $$SLEEP_TIME Sekunden."
sleep $$SLEEP_TIME
done
'
depends_on:
db:
condition: service_healthy
Erstellt auch den Ordner für die Backups: mkdir backup-db
. Nach einem Neustart mit sudo docker compose down
gefolgt von sudo docker compose up -d
wird dieser Container täglich ein Backup der Datenbank im backup-db
-Ordner ablegen. Diesen Ordner solltet ihr dann ebenfalls mit Duplicati oder einem anderen Tool extern sichern.
Wichtig: Testet eure Backups regelmäßig!
Praktische Nutzung und Tipps
Repository pushen und migrieren
Ihr könnt nun lokale Projekte zu eurem Gitea-Server pushen:
# In einem lokalen Git-Repository
git remote add gitea https://gitea.domain.de/DEIN_BENUTZER/PROJEKT.git
git push gitea main
Oder ihr nutzt die Migrationsfunktion, um Repositories direkt von GitHub, GitLab oder anderen Git-Diensten zu importieren. Klickt dazu auf das +
-Symbol oben rechts und wählt “Neue Migration”.
Private vs. Öffentliche Repositories
Standardmäßig sind neu erstellte Repositories öffentlich, wenn eure Gitea-Instanz öffentlich erreichbar ist. Wenn ihr das nicht wollt, habt ihr zwei Möglichkeiten:
- Setzt beim Erstellen eines Repositories den Haken bei “Dieses Repository ist privat”.
- Deaktiviert die Registrierung und setzt die Option
REQUIRE_SIGNIN_VIEW = true
in derdata/gitea/conf/app.ini
, um zu erzwingen, dass Benutzer eingeloggt sein müssen, um irgendetwas zu sehen.
Troubleshooting
- Links oder Klon-URLs sind falsch: Überprüft
ROOT_URL
in eurerdata/gitea/conf/app.ini
und startet Gitea neu. - Berechtigungsprobleme: Stellt sicher, dass die
USER_UID
undUSER_GID
in derdocker-compose.yml
korrekt sind und der Benutzer Schreibrechte auf die gemappten Ordner (data
,postgres
,backup-db
) hat. - Probleme nach dem Start: Schaut in die Logs mit
sudo docker compose logs
. Dort finden sich oft hilfreiche Fehlermeldungen.
Fazit
Glückwunsch! Ihr habt erfolgreich Gitea mit Docker installiert, es über einen Reverse Proxy sicher erreichbar gemacht und wisst, wie ihr eure wertvollen Repositories sichern könnt. Ihr habt jetzt euren eigenen schnellen und privaten Git-Server unter eurer vollen Kontrolle.
Ich hoffe, dieses Tutorial hat euch gefallen und weitergeholfen. Nutzt ihr schon Gitea oder einen anderen selbstgehosteten Git-Server? Welche Features sind euch am wichtigsten? Vielen Dank fürs Lesen und viel Spaß mit eurem eigenen Gitea!