> ## Content Index
> Fetch the complete content index at: https://sakis.tech/llms.txt
> Use this file to discover other available public pages before exploring further.

# Gitea Docker Compose: eigener Git-Server fürs Homelab
- URL: https://sakis.tech/gitea-docker-compose/
- Published: 2026-10-07T12:41:28.000Z
- Updated: 2026-10-07T12:41:28.000Z
- Description: Gitea ist GitHub für dein Heimnetz: Compose-Datei anlegen, Installer einmal durchklicken, erstes Repository pushen. Mit den drei Entscheidungen, die du später nur noch in der app.ini korrigieren kannst.
- Author: Sakis
- Tags: homelab, docker

Ende August hieß die aktuelle Gitea-Version noch 1.27.3\. Gut fünf Wochen später heißt sie 28.1.0\. Dazwischen liegt kein Sprung in der Software, sondern eine Entscheidung: Das Projekt streicht die führende „1.", die seit zehn Jahren vor jeder Versionsnummer stand. Mir gefällt das. Die Eins hat nie etwas bedeutet, und wer sie wegnimmt, nimmt auch die Ausrede weg, es sei noch nicht fertig. Gitea ist fertig, seit Jahren. Es ist ein Git-Server mit Weboberfläche, der auf einem alten Büro-PC läuft und in einer Minute installiert ist. Genau das machen wir jetzt.

**Kurz gesagt:** Am Ende läuft dein eigener Git-Server im Heimnetz: Weboberfläche auf Port 3000, Git über SSH auf Port 222, alle Daten in einem Ordner, Registrierung geschlossen, erstes Repository gepusht. Dauer rund 20 Minuten, Stufe Standard. Stand: Gitea 28.1.0, geprüft am 07-10-2026.

![Gitea in drei Schritten: Compose anlegen, Installer durchklicken, erstes Repo pushen](https://sakis.tech/content/images/2026/10/grafik-5.png)

Der ganze Weg auf einen Blick: Schritt 2 ist der, den du nur einmal siehst.

## Was Gitea ist und warum es ins Homelab gehört

Git ist das Werkzeug, das jede Änderung an einer Datei festhält, mit Datum, Urheber und der Möglichkeit, zurückzuspringen. Es läuft auf deinem PC, ganz ohne Server. GitHub ist die Website, auf der Leute ihre Git-Projekte ablegen, damit sie von überall erreichbar sind und andere mitarbeiten können. Gitea ist dieselbe Idee als Programm für deinen eigenen Server: Repositories, Issues, Pull Requests, eine Weboberfläche zum Stöbern im Code. Geschrieben in Go, eine einzige ausführbare Datei, und das Docker-Image bringt Git und SSH-Server gleich mit.

Für ein Homelab ist das die richtige Größe. Deine Compose-Dateien, die Konfiguration vom Pi-hole, die Skripte, die nachts das Backup anstoßen: Das alles gehört unter Versionskontrolle, und es gehört nicht zu Microsoft. Nicht, weil GitHub böse wäre, sondern weil ein privates Repository mit deinen Passwörtern in Umgebungsvariablen auf fremden Servern nichts verloren hat. Und Gitea läuft laut README überall, wo Go läuft, ARM eingeschlossen; das Docker-Image gibt es für amd64 und arm64, der Raspberry Pi ist also dabei.

Ein Wort zu Forgejo, weil die Frage sowieso kommt: Forgejo ist eine Abspaltung von Gitea mit eigener Entwicklung; die Domains liegen beim gemeinnützigen Codeberg e.V., der das Projekt mit Ressourcen unterstützt. Die Compose-Datei unten sieht dort fast genauso aus. Ich nehme hier Gitea, weil das Docker-Image, die Doku und die Release-Notes aus einer Hand kommen und weil 28.1.0 gerade acht Sicherheitslücken geschlossen hat, die in der Vorversion steckten. Wenn du Forgejo lieber magst, ändere die Image-Zeile und lies den Rest trotzdem.

So fließen die Daten, wenn alles läuft:

dein PC (git push)→ Port 222 (SSH) oder 3000 (HTTP) →Gitea-Container→ schreibt nach →\~/gitea auf dem Server

## Was du brauchst

- **Einen Linux-Server mit Docker und Docker Compose.** Ein Mini-PC, eine VM auf Proxmox oder ein Raspberry Pi 4 reichen. Wie Compose-Dateien aufgebaut sind, steht in der [Docker-Compose-Anleitung für Einsteiger](https://sakis.tech/docker-compose-grundlagen-fuer-einsteiger/); hier setze ich voraus, dass du sie kennst.
- **Zwei freie Ports:** 3000 für die Weboberfläche und 222 für Git über SSH. Port 22 ist auf dem Server schon vom normalen SSH-Zugang belegt, deshalb bekommt Gitea die 222.
- **Git auf deinem PC,** damit du am Ende etwas zu pushen hast. Unter Windows heißt das „Git for Windows", unter macOS kommt es mit den Xcode-Werkzeugen, unter Linux aus der Paketverwaltung.

Die drei Dinge, die sich prüfen lassen, prüfen wir. Die Befehle laufen auf dem Server:

```bash
docker compose version
sudo ss -tlnp | grep -E ':(3000|222) ' || echo "Port frei"
id -u
```

Die erste Zeile antwortet mit einer Versionsnummer, die mit „v2" beginnt oder höher. Die zweite gibt „Port frei" aus; steht dort stattdessen eine Zeile mit einem Programmnamen, ist ein Port belegt, und der [Beitrag zu belegten Ports](https://sakis.tech/port-belegt-so-findest-du-den-schuldigen-und-gibst-ihn-frei/) zeigt, wie du den Schuldigen findest. Die dritte Zeile gibt eine Zahl aus, meistens 1000\. Merk sie dir, sie taucht gleich in der Compose-Datei auf.

- IP-Adresse des Servers: `192.168.178.60`
- Ordner für Gitea auf dem Server: `~/gitea`
- Benutzer-ID deines Linux-Benutzers (`id -u`): `1000`
- Weboberfläche: Port `3000`, Git über SSH: Port `222`
- Name des Gitea-Admins: `sakis`
- Erstes Repository: `notizen`

**So liest du diese Anleitung:** Alles, was du selbst tun sollst, steht in einem farbigen Kasten. **\[ per klick \]** heißt: Das erledigst du mit der Maus in einer Web-Oberfläche, hier der Gitea-Oberfläche im Browser. **\[ über die shell \]** heißt: Den Befehl kopieren, ins Terminal einfügen, Enter. Stehen beide Kästen direkt untereinander, führen sie zum selben Ergebnis. Du gehst EINEN davon, nicht beide.

## Schritt 1: Ordner und Compose-Datei anlegen

Gitea bekommt einen eigenen Ordner im Home-Verzeichnis. Darin liegt die Compose-Datei, und darin entsteht beim ersten Start der Unterordner, in dem Gitea alles ablegt. Ordner anlegen, hineinwechseln, Editor öffnen:

```bash
mkdir -p ~/gitea
cd ~/gitea
nano docker-compose.yml
```

In den leeren Editor kommt diese Datei. Sie ist die aus der offiziellen Docker-Anleitung, Zeile für Zeile, nur mit der Versionsnummer von heute:

```yaml
networks:
  gitea:
    external: false

services:
  server:
    image: docker.gitea.com/gitea:28.1.0
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "222:22"
```

Speichern mit `Strg+O`, Enter, schließen mit `Strg+X`. Vier Zeilen verdienen einen Blick, bevor du startest:

- `**image: docker.gitea.com/gitea:28.1.0**`: Das Image kommt aus Giteas eigener Registry, nicht von Docker Hub, und es trägt die volle Versionsnummer. Es gäbe auch `:latest`. Ich pinne lieber, denn ein Git-Server, der sich beim nächsten `pull` ungefragt eine Hauptversion weiterbewegt, ist genau die Überraschung, die ich morgens um sieben nicht brauche. Das Update machst du dann bewusst, siehe unten.
- **`USER_UID=1000` und `USER_GID=1000`**: Im Container läuft Gitea als Benutzer `git`, und diese zwei Zeilen geben ihm die Nummer deines Linux-Benutzers auf dem Server. Hat `id -u` bei dir etwas anderes ausgegeben, trag es hier ein, sonst gehören die Dateien in `~/gitea/gitea` nachher jemand anderem als dir.
- `**./gitea:/data**`: die wichtigste Zeile. Alles, was Gitea je speichert, landet in `~/gitea/gitea` auf dem Server: Repositories, Datenbank, SSH-Hostschlüssel, Konfiguration. Löschst du den Container, bleibt der Ordner. Löschst du den Ordner, ist alles weg.
- **`"222:22"`**: Links steht der Port auf dem Server, rechts der im Container. Gitea bringt einen eigenen SSH-Server mit, der im Container auf 22 lauscht; außen bekommt er die 222, weil die 22 dem Server selbst gehört. Diese 222 trägst du gleich im Installer ein, damit Gitea sie in die Clone-Adressen schreibt.

## Schritt 2: Container starten

```bash
docker compose up -d
docker compose ps
```

Der erste Befehl lädt das Image und startet den Container im Hintergrund. Der zweite zeigt, was läuft:

```text
NAME      IMAGE                           COMMAND                  SERVICE   CREATED         STATUS         PORTS
gitea     docker.gitea.com/gitea:28.1.0   "/usr/bin/entrypoint…"   server    3 seconds ago   Up 2 seconds   0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp, 0.0.0.0:222->22/tcp, [::]:222->22/tcp
```

Steht dort `Up`, hat der Container überlebt. Was er beim Start getan hat, verrät das Log:

```bash
docker compose logs server | grep -i listen
```

Die Zeile, die du suchst, endet auf `Listen: http://0.0.0.0:3000`. Sie heißt: Gitea nimmt auf Port 3000 Verbindungen an, von jeder Adresse aus. Und `ls ~/gitea/gitea` zeigt, dass der Datenordner angelegt wurde, mit `git`, `gitea` und `ssh` darin. Im Sandkasten war der Container nach zehn Sekunden erreichbar. Das ging so schnell, dass ich zweimal hingesehen habe.

## Schritt 3: Den Installer durchklicken

Gitea ist jetzt da, aber noch leer: keine Datenbank, kein Admin, keine Ahnung, unter welcher Adresse es erreichbar ist. All das fragt die Seite ab, die du als Erstes siehst. Sie heißt „Erstkonfiguration", und du siehst sie genau einmal; danach schreibt Gitea die Antworten in seine Konfigurationsdatei und zeigt die Seite nie wieder. Also mit Ruhe.

Im Browser **http://192.168.178.60:3000** öffnen (Stand Gitea 28.1). Auf der Seite **Erstkonfiguration**:

- **Datenbankeinstellungen:** bei **Datenbanktyp** `SQLite3` wählen. Der **Pfad** darunter bleibt, wie er ist.
- **Allgemeine Einstellungen:** **Seitentitel** nach Geschmack, etwa „Homelab-Git". **SSH-Server-Port** auf `222` ändern. **HTTP-Server-Port** bleibt `3000`. **Gitea-Website-URL** auf `http://192.168.178.60:3000/` setzen, mit deiner Server-IP und dem Schrägstrich am Ende.
- Das Häkchen **Nur Administratoren können Benutzerkonten erstellen** setzen; im Installer von Gitea 28.1.0 ist es nicht vorbelegt. Ebenso **Anmeldung erforderlich um Seiten anzuzeigen** setzen.
- Ganz unten **Administratoreinstellungen** aufklappen: **Administrator-Benutzername** `sakis`, **E-Mail-Adresse**, **Passwort** und **Passwort bestätigen**.
- **Gitea installieren** klicken.

![Die Seite Erstkonfiguration von Gitea mit dem Datenbanktyp SQLite3 und dem Seitentitel Homelab-Git.](https://sakis.tech/content/images/2026/10/labor-gitea-docker-compose-01-2026-10-07.png)

(1) Datenbanktyp: SQLite3; (2) Seitentitel: Homelab-Git

![Die allgemeinen Einstellungen im Gitea-Installer mit SSH-Server-Port 222, der Website-URL mit der Server-IP und dem gesetzten Haken, dass nur Administratoren Benutzerkonten erstellen.](https://sakis.tech/content/images/2026/10/labor-gitea-docker-compose-02-2026-10-07.png)

(1) SSH-Server-Port: 222; (2) Gitea-Website-URL: http://192.168.178.60:3000/; (3) Haken setzen

![Die aufgeklappten Administratoreinstellungen im Gitea-Installer mit dem Benutzernamen sakis, E-Mail-Adresse und Passwort, darunter der Knopf Gitea installieren.](https://sakis.tech/content/images/2026/10/labor-gitea-docker-compose-03-2026-10-07.png)

(1) Administrator-Benutzername: sakis; (2) Passwort eintragen; (3) Hier klicken

Drei Entscheidungen stecken in diesen Klicks, und sie lassen sich später nur noch in der Konfigurationsdatei korrigieren:

- **SQLite3** ist eine Datenbank in einer einzigen Datei, ohne eigenen Dienst. Die Doku bietet auch MySQL und PostgreSQL als zweiten Container an. Für einen Server mit einem Nutzer und ein paar Dutzend Repositories ist das ein zweites Zimmer für den Rauchmelder; SQLite reicht und macht das Backup zu einem Kopierbefehl.
- **Die Website-URL** ist die Adresse, die Gitea in alle Links und Clone-Adressen schreibt. Lässt du hier `localhost` stehen, zeigt dir Gitea später Clone-Adressen, die nur auf dem Server selbst funktionieren, und die Admin-Seite meckert in einem gelben Kasten. Das ist in den Issues ein Dauergast.
- **Der SSH-Port 222** landet in derselben Clone-Adresse. Ohne ihn stünde dort Port 22, und dein `git push` würde beim SSH-Server des Linux-Systems anklopfen, der von Gitea nichts weiß.

Nach dem Klick lädt die Seite einige Sekunden, dann steht das Dashboard da, und oben rechts bist du als `sakis` angemeldet. Wer jetzt die Seite neu lädt und sich kurz freut: erlaubt.

## Schritt 4: Erstes Repository anlegen und pushen

Ein Git-Server ohne Repository ist ein Regal ohne Bücher. Das erste legst du in der Oberfläche an:

Oben rechts auf das **+** klicken, dann **Neues Repository**. Bei **Repository-Name** `notizen` eintragen, bei **Sichtbarkeit** das Häkchen **In privates Repository umwandeln** setzen, unten **Repository erstellen**.

![Das Gitea-Dashboard mit dem aufgeklappten Plus-Menü oben rechts, darin der Eintrag Neues Repository.](https://sakis.tech/content/images/2026/10/labor-gitea-docker-compose-04-2026-10-07.png)

(1) Hier klicken; (2) Neues Repository

![Das Formular Neues Repository in Gitea mit dem Namen notizen und dem gesetzten Haken für ein privates Repository.](https://sakis.tech/content/images/2026/10/labor-gitea-docker-compose-05-2026-10-07.png)

(1) Repository-Name: notizen; (2) Haken setzen

![Das untere Ende des Formulars Neues Repository mit dem Knopf Repository erstellen.](https://sakis.tech/content/images/2026/10/labor-gitea-docker-compose-06-2026-10-07.png)

Hier klicken

Gitea zeigt dir eine leere Repository-Seite mit zwei Clone-Adressen: eine für HTTP, eine für SSH. Die HTTP-Adresse lautet `http://192.168.178.60:3000/sakis/notizen.git`, und mit der geht es am schnellsten los, weil sie nur dein Passwort braucht und keinen Schlüssel. Die folgenden Befehle laufen auf deinem PC, nicht auf dem Server:

```bash
git clone http://192.168.178.60:3000/sakis/notizen.git
cd notizen
echo "# Notizen" > README.md
git add README.md
git commit -m "Erste Notiz"
git push
```

Beim `clone` warnt Git, dass du ein leeres Repository geklont hast; das ist richtig so. Beim `push` fragt es nach Benutzername und Passwort, also `sakis` und das Passwort aus dem Installer. Danach lädst du die Repository-Seite im Browser neu, und dort liegt die README mit ihrer einen Zeile. Das ist der Moment, in dem der Server zum ersten Mal etwas von dir verwahrt.

Falls `git commit` stattdessen nach deinem Namen fragt: Git kennt dich auf diesem PC noch nicht. Einmal `git config --global user.name "Dein Name"` und `git config --global user.email "du@example.org"`, dann noch einmal committen.

Für den Alltag willst du SSH statt Passwort: Du hinterlegst den öffentlichen Schlüssel deines PCs in deinen Gitea-Benutzereinstellungen, und die SSH-Clone-Adresse `ssh://git@192.168.178.60:222/sakis/notizen.git` funktioniert ab dann ohne Nachfrage. Das hat einen eigenen Beitrag verdient, weil der Schlüsselteil für alle Dienste gleich ist, und steht auf der Liste.

## Was am Ende eingestellt ist

- **Ein Admin, keine Registrierung.** Nur `sakis` kann sich anmelden, und neue Konten legt nur der Admin an, über die Seitenadministration. Gitea 28 hat die Selbstregistrierung als Standard abgeschaltet; in den Release-Notes steht das als Breaking Change, und ich finde, es war überfällig. Ein Git-Server im Heimnetz, auf dem sich jeder Gast ein Konto klicken kann, ist kein Feature.
- **Repositories sind privat, wenn du es so lässt.** Die Einstellung `DEFAULT_PRIVATE` steht laut Konfigurationsübersicht auf `last`: Gitea merkt sich, was du beim letzten Mal gewählt hast. Nach Schritt 4 ist das „privat", und das bleibt so, solange du beim Anlegen nicht umschaltest.
- **Alles liegt in `~/gitea/gitea`.** Die Datenbank ist die Datei `gitea/gitea.db` darin, die Konfiguration `gitea/conf/app.ini`, die Repositories liegen unter `git/repositories`. Willst du später die Website-URL oder den SSH-Port ändern, ist `app.ini` die Stelle, gefolgt von `docker compose restart`.
- **Backup ist ein Kopierbefehl.** Weil die Datenbank eine Datei ist, reicht es, den Container kurz anzuhalten und den Ordner zu kopieren: `docker compose stop`, dann `cp -a ~/gitea ~/gitea-backup-2026-10-07` oder besser auf eine andere Platte, dann `docker compose start`. Die Doku kennt daneben `gitea dump`, das Repositories, Datenbank und Konfiguration in eine ZIP-Datei packt; für die Wiederherstellung gibt es dort aber keinen Gegenbefehl, sondern eine Liste von Handgriffen. Für zuhause nehme ich die Ordnerkopie. Ja, der Backup-Satz. Er bleibt.
- **Updates machst du von Hand, und das ist Absicht.** In der Compose-Datei die Versionsnummer ändern, dann `docker compose pull` und `docker compose up -d`, genau wie es die Docker-Anleitung beschreibt. Vorher die Ordnerkopie von oben. Die Release-Notes zu 28.1.0 drängen auf das Update, und für die nächsten gilt dasselbe, nur eben nach dem Lesen der Notes, nicht vor dem Frühstück.
- **Unverschlüsselt, und deshalb nur im Heimnetz.** Port 3000 spricht HTTP, dein Passwort geht beim ersten Push im Klartext durchs LAN. Für zuhause hinter dem Router ist das in Ordnung; nach außen öffnest du diesen Port nicht. Soll Gitea von unterwegs erreichbar sein, geht das über ein VPN wie [wg-easy](https://sakis.tech/wg-easy-docker-compose/) oder über einen [Reverse Proxy mit Zertifikat](https://sakis.tech/nginx-proxy-manager-installieren/), und dann ändert sich auch die Website-URL in `app.ini`.

## Wo es klemmt

**Der Container startet nicht, im Log steht `permission denied` auf `/data`.** Die Doku sagt es selbst: Gibt man dem Volume nicht die richtigen Berechtigungen, startet der Container möglicherweise nicht. Die Ursache ist fast immer, dass `USER_UID` nicht zu dem Benutzer passt, dem `~/gitea/gitea` gehört. `ls -ln ~/gitea` zeigt die Nummer des Besitzers; die kommt in die Compose-Datei, dann `docker compose up -d`. Hilft das nicht, weil der Ordner noch root gehört: `sudo chown -R 1000:1000 ~/gitea/gitea`, mit deiner Nummer statt der 1000.

**Oben in der Seitenadministration steht ein gelber Kasten: „Your ROOT\_URL in app.ini is http://localhost:3000/ but you are visiting …".** Das ist die Website-URL aus Schritt 3, die nicht zu der Adresse passt, unter der du gerade im Browser bist. Diese Meldung ist in Giteas Issues einer der häufigsten Treffer, meist nach einem Port-Wechsel oder dem Umzug hinter einen Reverse Proxy; in Issue #22655 war es ein Port 3002, den Docker nach außen gab, während in der Konfiguration noch 3000 stand. Fix: auf dem Server `nano ~/gitea/gitea/conf/app.ini`, im Abschnitt `[server]` die Zeile `ROOT_URL` auf die Adresse setzen, unter der du Gitea wirklich aufrufst, speichern, dann `docker compose restart`.

**`git push` über SSH fragt nach dem Passwort des Servers oder meldet „Permission denied (publickey)".** Dann ist dein Git beim falschen SSH-Server gelandet: beim Linux-System auf Port 22 statt bei Gitea auf Port 222\. Die Clone-Adresse muss mit `ssh://git@` beginnen und `:222/` enthalten; genau so zeigt Gitea sie an, wenn im Installer der SSH-Server-Port auf 222 stand. Steht in deiner Adresse keine Portnummer, war das Feld noch auf 22, und `SSH_PORT = 222` in `app.ini` unter `[server]` holt das nach.

Mehr braucht es nicht. Gitea gehört zu den Diensten, die nach der Installation einfach dastehen und ihren Job machen, jahrelang, ohne dass man sie anfassen muss. Was du jetzt hast, ist ein Ort für alles, was im Homelab aus Text besteht, mit Verlauf. Das ist mehr wert, als es nach zwanzig Minuten aussieht; spätestens, wenn die Compose-Datei vom Nextcloud nach einer Änderung nicht mehr startet und `git diff` dir zeigt, welche Zeile du gestern angefasst hast.

Was legst du als Erstes auf deinen eigenen Git-Server: die Compose-Dateien, die Skripte oder gleich die Dotfiles vom Laptop? Schreib's in die Kommentare, ich bin neugierig, was bei euch im Homelab aus Text besteht.

Wenn Gitea bei dir der erste Dienst ist, der länger als eine Woche läuft, lohnt als Nächstes der Blick auf das [Nextcloud-Backup](https://sakis.tech/nextcloud-backup-erstellen-docker/): Die Ordnerkopie von oben ist dort dieselbe Idee, nur mit einer Datenbank, die etwas mehr Rücksicht verlangt.

sakis@homelab:\~$ echo "bleib neugierig — und mach backups" 

## Quellen

- [Gitea-Doku: Installation with Docker](https://docs.gitea.com/installation/install-with-docker?ref=sakis.tech)
- [Gitea-Doku: Config Cheat Sheet](https://docs.gitea.com/administration/config-cheat-sheet?ref=sakis.tech)
- [Gitea-Doku: Backup and Restore](https://docs.gitea.com/administration/backup-and-restore?ref=sakis.tech)
- [Gitea-Blog: Gitea 28.0.0 is released](https://blog.gitea.com/release-of-28.0.0/?ref=sakis.tech)
- [Gitea-Blog: Gitea 28.1.0 is released](https://blog.gitea.com/release-of-28.1.0/?ref=sakis.tech)
- [GitHub-Issue #22655: Your ROOT\_URL in app.ini is … but you are visiting …](https://github.com/go-gitea/gitea/issues/22655?ref=sakis.tech)
- [Docker Hub: Tags von gitea/gitea](https://hub.docker.com/r/gitea/gitea/tags?ref=sakis.tech)