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.

Gitea mit Docker installieren: Dein eigener Git-Server (Schritt-für-Schritt-Anleitung) hero image

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:

  1. 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.
  2. Docker und Docker Compose: Müssen auf dem Server installierbar sein. Wir gehen die Installation gemeinsam durch.
  3. 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.
  4. 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.
  5. (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 (wie 1.24) anstelle von latest zu verwenden. Das verhindert unerwartete Breaking Changes bei Updates. Wenn ihr docker compose pull ausführt, erhaltet ihr immer noch Patch-Updates (z.B. von 1.24.7 auf 1.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 Befehl id im Terminal heraus.
  • volumes: - ./data:/data: Wir mappen den lokalen data-Ordner in den Container. Hier speichert Gitea alle seine Konfigurationen, Datenbanken (falls SQLite) und Repositories.
  • ports: Wir leiten den Web-Port 3000 und den SSH-Port 22 aus dem Container auf die Host-Ports 3000 und 2222 um. Der SSH-Port wird auf 2222 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 einen postgres-Ordner für dessen Daten erstellt (mkdir postgres).
  • Die environment-Variablen im server-Service konfigurieren Gitea für die Verbindung zur db. Wichtig: HOST ist db, der Service-Name des Datenbankcontainers.
  • depends_on mit condition: service_healthy sorgt dafür, dass Gitea erst startet, wenn die Datenbank bereit ist.
  • Wir haben die ports entfernt und den Gitea-Container einem externen proxy-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 (dessen container_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:

  1. Setzt beim Erstellen eines Repositories den Haken bei “Dieses Repository ist privat”.
  2. Deaktiviert die Registrierung und setzt die Option REQUIRE_SIGNIN_VIEW = true in der data/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 eurer data/gitea/conf/app.ini und startet Gitea neu.
  • Berechtigungsprobleme: Stellt sicher, dass die USER_UID und USER_GID in der docker-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!

Diesen Beitrag teilen:

Diese Website verwendet Cookies. Diese sind notwendig, um die Funktionalität der Website zu gewährleisten. Weitere Informationen finden Sie in der Datenschutzerklärung