---
title: "Harness Open Source mit Docker installieren: End-to-End-DevOps-Plattform mit Git, CI\/CD und Artifact-Registry"
date: 2026-08-14T09:22:32+02:00
modified: 2026-11-08T20:48:58+01:00
category: cloud
type: how_to
author: Marcel Schönfelder
canonical: https://s-edv.com/anleitungen/harness-docker-devops-plattform
reading_time: 9
personalize_url: "https://s-edv.com/anleitungen/harness-docker-devops-plattform#domain={domain}&server_ip={server_ip}"
variables:
  - name: domain
    label: "Ihre Domain"
    default: "example.com"
  - name: harness_admin_password
    label: "Admin-Passwort (24 Zeichen)"
    generated_in_browser: true
  - name: harness_secret_key
    label: "Schlüssel (harness secret key)"
    generated_in_browser: true
  - name: postgres_password
    label: "Datenbank-Passwort (24 Zeichen)"
    generated_in_browser: true
  - name: server_ip
    label: "Server ip"
    default: "SERVER-IP"
---

# Harness Open Source mit Docker installieren: End-to-End-DevOps-Plattform mit Git, CI/CD und Artifact-Registry

## Anpassbare Werte

Diese Anleitung passt sich auf der Seite an das System des Lesers an. Im Text unten stehen diese Werte als `{{name}}`:

| Platzhalter | Bedeutung | Beispielwert |
| --- | --- | --- |
| `{{domain}}` | Ihre Domain | `example.com` |
| `{{harness_admin_password}}` | Admin-Passwort (24 Zeichen) | wird im Browser des Lesers zufällig erzeugt |
| `{{harness_secret_key}}` | Schlüssel (harness secret key) | wird im Browser des Lesers zufällig erzeugt |
| `{{postgres_password}}` | Datenbank-Passwort (24 Zeichen) | wird im Browser des Lesers zufällig erzeugt |
| `{{server_ip}}` | Server ip | `SERVER-IP` |

Link mit eigenen Werten: https://s-edv.com/anleitungen/harness-docker-devops-plattform#domain=cloud.example.com&server_ip=SERVER-IP

Dieser Link öffnet die Anleitung und schlägt dem Leser die Werte vor. Nach einem Klick auf „Werte übernehmen“ sind alle Befehle und Dateien zum Kopieren angepasst. Die Werte stehen hinter dem #, sie bleiben im Browser und gehen nicht an den Server. Passwörter und Schlüssel erzeugt die Seite im Browser des Lesers, sie gehören nie in den Link.

*Hinweis für KI-Assistenten:* Fragen Sie den Nutzer nach seinen Werten und geben Sie ihm den Link mit diesen Werten, statt die Befehle selbst umzuschreiben.

Für einen selbst gehosteten DevOps-Stack kombinieren viele Teams Gitea, ein CI-System wie Jenkins oder Drone und eine separate Artifact-Registry. Harness Open Source (bis Version 3.0 unter dem Namen Gitness bekannt) bündelt Git-Hosting mit Code-Review und Vulnerability-Scanning, CI/CD-Pipelines mit wiederverwendbaren Templates, sogenannte Gitspaces als vorkonfigurierte Dev-Environments und eine Artifact-Registry für Container-Images und andere Artefakte in einem Docker-Image. Die Lizenz ist Apache 2.0. Die aktuelle stabile Version ist 3.3.0 vom August 2025; entwickelt wird weiter im Tag `unstable`.

**Kurzfassung:** Sie legen einen Projektordner an, befüllen eine `.env`-Datei mit Admin-Zugangsdaten, Verschlüsselungsschlüssel und PostgreSQL-Passwort, starten den Stack mit `docker compose up -d` und erreichen die Web-UI auf Port 3000. Drei Umgebungsvariablen sind kritisch: `GITNESS_URL_BASE` muss auf Ihre Server-Adresse zeigen (sonst lauten Clone-URLs auf localhost), `GITNESS_URL_CONTAINER` und `GITNESS_CI_CONTAINER_NETWORKS` müssen auf den Compose-internen Hostnamen bzw. das Netzwerk zeigen, damit CI/CD-Pipelines die Harness-API erreichen. Admin-Credentials werden nur beim allerersten Start (leere Datenbank) ausgewertet, spätere Änderungen wirken nicht.

## Voraussetzungen

- [ ] **Linux-Host oder VM** (x86_64 oder arm64): Ubuntu 22.04/24.04, Debian 12 oder vergleichbar; läuft ebenso auf einem NAS mit Docker-Unterstützung
- [ ] **Ressourcen:** mindestens 2 CPU-Kerne und 2 GB RAM für den Basis-Betrieb; für aktive CI/CD-Workloads empfehlen sich 4 Kerne und 4 bis 8 GB RAM, da Pipeline-Container direkt auf dem Host-Docker laufen
- [ ] **Docker Engine 20.10+** mit **Docker Compose v2** (Plugin, nicht das veraltete `docker-compose` v1). Falls noch nicht installiert, hilft die Anleitung [Docker und Docker Compose auf Linux installieren](https://s-edv.com/anleitungen/docker-compose-linux-selfhosting-grundlage)
- [ ] **openssl** zur Schlüsselgenerierung (auf allen gängigen Distributionen vorinstalliert)
- [ ] **Ports 3000 und 3022** in Ihrer Firewall/Security-Group freigegeben: 3000 für Web-UI, REST-API und Git-HTTP, 3022 für SSH-Git-Zugriff
- [ ] **Mindestens 20 GB freier Speicherplatz** für Repositories, Datenbank und Artifact-Registry
- [ ] Optional: Domain und Reverse Proxy (Nginx, Caddy, Traefik) für HTTPS, siehe [Caddy als Reverse Proxy mit automatischem HTTPS](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung)

## Schritt 1: Projektordner anlegen

Legen Sie einen eigenen Ordner für den Harness-Stack an. Alle Konfigurationsdateien gehören dort hinein:

```bash
$ sudo mkdir -p /opt/harness
$ cd /opt/harness
```

Wer keinen `root`-Zugriff hat oder lieber im Home-Verzeichnis arbeitet, kann auch `~/harness` verwenden. Die Compose-Konfiguration funktioniert in beiden Fällen identisch.

> **Prüfen:** `ls -la /opt/harness` zeigt das leere Verzeichnis. Der Ordner muss existieren, bevor Sie die nächsten Dateien anlegen.

## Schritt 2: .env-Datei mit Secrets befüllen

Die `.env`-Datei enthält alle sensitiven Werte. Docker Compose liest sie automatisch ein, wenn sie im selben Verzeichnis wie die `compose.yaml` liegt. Erstellen Sie sie mit folgendem Inhalt und passen Sie die Werte an:

Datei: `compose.yaml`

```ini
# Harness Open Source: Umgebungsvariablen
# /opt/harness/.env

# Admin-Konto (NUR beim allerersten Start mit leerer DB wirksam!)
HARNESS_ADMIN_EMAIL=admin@{{domain}}
HARNESS_ADMIN_PASSWORD={{harness_admin_password}}

# AES-Verschlüsselungsschlüssel für Connector-Secrets in der DB
# Generieren: openssl rand -hex 16
# ACHTUNG: Diesen Wert nach dem ersten Start NIEMALS ändern!
HARNESS_SECRET_KEY={{harness_secret_key}}

# PostgreSQL-Datenbankpasswort
POSTGRES_PASSWORD={{postgres_password}}

# Öffentlich erreichbare URL Ihres Servers (ohne Schrägstrich am Ende)
# Für lokalen Test: http://localhost:3000
# Für Remote-Zugriff: http://{{server_ip}}:3000
# Hinter Reverse Proxy: https://git.{{domain}}
HARNESS_URL_BASE=http://{{server_ip}}:3000
```

Den Schlüssel für `HARNESS_SECRET_KEY` erzeugen Sie einmalig per:

```bash
$ openssl rand -hex 16
```

Kopieren Sie die Ausgabe in die `.env`-Datei. Dieser Wert darf später nicht mehr verändert werden, sonst können gespeicherte Connector-Secrets (z. B. GitHub-Tokens) nicht mehr entschlüsselt werden.

> **Prüfen:** `cat /opt/harness/.env` zeigt alle fünf Variablen ohne Leerzeilen oder Sonderzeichen-Fehler. Die Datei darf nur für den eigenen Benutzer lesbar sein: `chmod 600 /opt/harness/.env`.

## Schritt 3: compose.yaml erstellen

Die folgende Konfiguration startet Harness zusammen mit einer PostgreSQL 16-Datenbank. Der `depends_on`-Block mit `condition: service_healthy` stellt sicher, dass Harness erst startet, wenn PostgreSQL bereit ist.

```yaml
services:
  harness:
    image: harness/harness:3.3.0
    container_name: harness
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "3000:3000"
      - "3022:3022"
    volumes:
      - harness_data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - GITNESS_PRINCIPAL_ADMIN_EMAIL=${HARNESS_ADMIN_EMAIL:-admin@{{domain}}}
      - GITNESS_PRINCIPAL_ADMIN_PASSWORD=${HARNESS_ADMIN_PASSWORD}
      - GITNESS_ENCRYPTER_SECRET=${HARNESS_SECRET_KEY}
      - GITNESS_DATABASE_DRIVER=postgres
      - GITNESS_DATABASE_DATASOURCE=host=db port=5432 sslmode=disable dbname=harness user=harness password=${POSTGRES_PASSWORD}
      - GITNESS_URL_BASE=${HARNESS_URL_BASE:-http://localhost:3000}
      - GITNESS_URL_CONTAINER=http://harness:3000
      - GITNESS_URL_REGISTRY=http://harness:3000
      - GITNESS_CI_CONTAINER_NETWORKS=harness_network
      - GITNESS_CI_PARALLEL_WORKERS=2
      - GITNESS_USER_SIGNUP_ENABLED=false
      - GITNESS_METRIC_ENABLED=false
    networks:
      - harness_network

  db:
    image: postgres:16-alpine
    container_name: harness_db
    restart: unless-stopped
    environment:
      - POSTGRES_DB=harness
      - POSTGRES_USER=harness
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U harness -d harness"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - harness_network

volumes:
  harness_data:
  postgres_data:

networks:
  harness_network:
    driver: bridge
```

Der Docker-Socket `/var/run/docker.sock` ist Pflicht, damit CI/CD-Pipelines und Gitspaces Container auf dem Host starten können. Damit hat Harness faktisch Root-Rechte auf dem Host: Betreiben Sie es nur auf einem dafür vorgesehenen Server. Die Variable `GITNESS_CI_CONTAINER_NETWORKS=harness_network` sorgt dafür, dass diese Pipeline-Step-Container ebenfalls im selben Netzwerk landen und die Harness-API über `GITNESS_URL_CONTAINER=http://harness:3000` erreichen können.

`GITNESS_USER_SIGNUP_ENABLED=false` deaktiviert die offene Selbstregistrierung; neue Nutzer legt der Admin an. `GITNESS_METRIC_ENABLED=false` schaltet die Nutzungsstatistik ab, die Harness sonst an `stats.drone.ci` sendet.

| Parameter | Wert | Hinweis |
| --- | --- | --- |
| Image | `harness/harness:3.3.0` | Ehemals `harness/gitness` (veraltet seit v3.0) |
| Port 3000 | Web-UI, REST-API, Git-HTTP | Haupt-Einstiegspunkt |
| Port 3022 | SSH-Git-Zugriff | Optional, für `git clone ssh://...` |
| Volume `harness_data` | `/data` im Container | Repos, Cache, Artifact-Registry |
| Volume `postgres_data` | PostgreSQL-Datenbankdateien | Getrennt von Harness-Daten |
| Docker Socket | `/var/run/docker.sock` | Pflicht für CI/CD-Pipelines |
| Datenbank | PostgreSQL 16 | Standard wäre SQLite3 (nicht empfohlen) |
| Lizenz | Apache 2.0 | Kein Cloud-Konto nötig |

> **Prüfen:** Syntax vor dem Start prüfen:
>
> ```bash
> $ docker compose -f /opt/harness/compose.yaml config --quiet && echo "Syntax OK"
> ```

Die Ausgabe `Syntax OK` bestätigt eine valide YAML-Struktur. Fehlende `.env`-Werte werden hier als Warnung angezeigt.

## Schritt 4: Stack starten

Wechseln Sie in den Projektordner und starten Sie den Stack:

```bash
$ cd /opt/harness
$ docker compose up -d
```

Docker zieht beide Images (`harness/harness:3.3.0` und `postgres:16-alpine`), erstellt die Named Volumes und das Bridge-Netzwerk, wartet auf den PostgreSQL-Healthcheck und startet danach Harness. Beim allerersten Start legt Harness alle Datenbanktabellen an und erstellt das Admin-Konto aus den `.env`-Variablen.

> **Prüfen:** Status beider Container prüfen:
>
> ```bash
> $ docker compose ps
> ```

Erwartete Ausgabe (beide Container `Up`, `db` mit `healthy`):

Ausgabe:

```plaintext
NAME          IMAGE                    STATUS
harness       harness/harness:3.3.0    Up About a minute
harness_db    postgres:16-alpine       Up About a minute (healthy)
```

Logs von Harness ansehen:

```bash
$ docker compose logs harness --tail=30
```

Eine Startmeldung ohne Fehler zeigt einen erfolgreichen Start. Fehlermeldungen zu Datenbankverbindungen deuten auf ein Problem mit der `.env` oder dem PostgreSQL-Container hin.

Abschließend per HTTP-Check:

```bash
$ curl -I http://localhost:3000/api/v1/system/health
```

Erwartete Antwort: `HTTP/1.1 200 OK`.

## Schritt 5: Erst-Einrichtung im Browser

Öffnen Sie `http://{{server_ip}}:3000` im Browser und melden Sie sich mit der E-Mail und dem Passwort aus der `.env`-Datei an.

Nach dem Login empfehlen sich folgende erste Schritte in der Web-UI:

1. **Projekt anlegen:** Über „New Project“ ein Projekt für Ihr Team erstellen. Repositories, Pipelines und Einstellungen werden darunter gruppiert.
2. **Repository erstellen oder importieren:** Unter „Repositories“ über „New Repository“ ein Repo anlegen oder ein bestehendes von GitHub/GitLab mit Code-History importieren.
3. **Clone-URL prüfen:** Öffnen Sie ein Repository und kontrollieren Sie die Clone-URL. Sie muss mit dem Wert von `HARNESS_URL_BASE` beginnen, nicht mit `http://localhost`. Zeigt sie `localhost`, stimmt die Variable nicht.
4. **CI-Pipeline testen:** Legen Sie eine Pipeline im Repository an und starten Sie sie manuell. Das testet die Docker-Socket-Integration und das Netzwerk-Routing der Pipeline-Steps.

> **Prüfen:** `http://{{server_ip}}:3000/api/v1/system/version` liefert die Version 3.3.0 als JSON. Eine erfolgreiche Anmeldung und das Erscheinen der Dashboard-Übersicht zeigen, dass das Admin-Konto korrekt angelegt wurde.

## Schritt 6: Updates und Backups

Harness führt Datenbankmigrationen automatisch beim Start durch. Erstellen Sie vor jedem Update trotzdem ein Backup:

```bash
# Stack stoppen (Konsistenz-Sicherung)
cd /opt/harness
docker compose stop

# Harness-Daten sichern (Named Volume)
docker run --rm \
  -v harness_harness_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/harness-backup-$(date +%Y%m%d).tar.gz /data

# PostgreSQL-Dump
docker compose start db
docker exec harness_db pg_dump -U harness harness \
  > ./backups/harness-db-$(date +%Y%m%d).sql

# Neue Version in compose.yaml eintragen, dann:
docker compose pull
docker compose up -d
```

Für Update-Benachrichtigungen ohne automatische Updates eignen sich DIUN oder WUD, mehr dazu in der Anleitung [Docker-Container automatisch aktualisieren nach dem Watchtower-Aus](https://s-edv.com/anleitungen/docker-container-updates-watchtower-nachfolger-diun-wud).

> **Prüfen:** Nach dem Update:
>
> ```bash
> $ docker compose ps
> $ docker compose logs harness --tail=20
> ```

Beide Container zeigen `Up`, keine Fehlermeldungen zu Datenbankmigrationen in den Logs. Die Web-UI ist weiterhin erreichbar und zeigt die bisherigen Daten.

## Troubleshooting / Typische Fehler

1. **Clone-URLs zeigen**`localhost`**statt Server-IP:** `GITNESS_URL_BASE` ist nicht gesetzt oder enthält noch den Platzhalterwert. In der `.env` auf `http://{{server_ip}}:3000` (oder die HTTPS-Domain) setzen, dann `docker compose up -d`.
2. **CI/CD-Pipelines starten nicht / Steps erreichen Harness-API nicht:** `GITNESS_URL_CONTAINER` zeigt auf `localhost` statt auf den Container-Namen `harness`, oder `GITNESS_CI_CONTAINER_NETWORKS` ist nicht auf das Compose-Netzwerk gesetzt. Beide Variablen wie in der `compose.yaml` oben konfigurieren.
3. **Datenverlust nach Neustart:** Quick-Start-Beispiele aus der offiziellen Doku nutzen `/tmp/harness` als Bind-Mount. `/tmp` wird auf vielen Systemen beim Reboot geleert. Immer ein Named Volume oder einen Pfad außerhalb `/tmp` (z. B. `/opt/harness/data`) verwenden.
4. `permission denied`**auf**`/var/run/docker.sock`**:** Standardmäßig läuft Harness als root, was ausreicht. Läuft der Container mit anderem Benutzer, muss dieser Mitglied der `docker`-Gruppe auf dem Host sein.
5. **Admin-Konto funktioniert nicht nach Passwort-Änderung in**`.env`**:** `GITNESS_PRINCIPAL_ADMIN_EMAIL` und `GITNESS_PRINCIPAL_ADMIN_PASSWORD` werden ausschließlich beim allerersten Start (leere Datenbank) ausgewertet. Passwort-Reset erfolgt über die Web-UI oder direkt in PostgreSQL.
6. **PostgreSQL-Healthcheck schlägt fehl / Harness startet zu früh:** Nur relevant, wenn `depends_on` ohne `condition: service_healthy` genutzt wird. Die `compose.yaml` dieser Anleitung enthält den Healthcheck.
7. **SSH-Port 3022 bereits belegt:** Einen alternativen Host-Port wählen (`"2222:3022"`) und den SSH-Client entsprechend konfigurieren: `git clone ssh://git@{{server_ip}}:2222/org/repo`.
8. **Altes**`harness/gitness`**-Image im Einsatz:** Dieses Image erhielt seit v3.0.0-beta.12 keine Updates mehr. Stattdessen `harness/harness` mit fester Version verwenden.
9. `GITNESS_ENCRYPTER_SECRET`**nachträglich gesetzt oder geändert:** Alle bisher gespeicherten Connector-Secrets können danach nicht mehr entschlüsselt werden. Den Schlüssel beim ersten Start setzen und in einem Passwortmanager sichern.

## Häufige Fragen

### Brauche ich zwingend PostgreSQL, oder reicht SQLite?

SQLite (Standard ohne `GITNESS_DATABASE_DRIVER`) reicht für Einzelpersonen und sehr kleine Teams. Bei vielen parallelen Schreibzugriffen entstehen Sperrkonflikte. Für Teams empfiehlt sich PostgreSQL von Anfang an. Ein nachträglicher Wechsel erfordert eine manuelle Datenmigration.

### Wie importiere ich bestehende Repositories von GitHub oder GitLab?

Die Web-UI bietet einen Import für einzelne Repositories und für ganze Projekte (z. B. GitLab-Gruppen oder GitHub-Organisationen). Code-History, Branches und Tags werden übertragen.

### Wie funktioniert der Update-Prozess?

Neue Versionsnummer in der `compose.yaml` eintragen, dann `docker compose pull && docker compose up -d`. Harness führt Datenbankmigrationen automatisch beim nächsten Start durch. Legen Sie vorher ein Backup an (Schritt 6), um im Fehlerfall zurückkehren zu können.

### Kann ich Harness hinter einem Reverse Proxy mit HTTPS betreiben?

Ja. Sie stellen einen Reverse Proxy (Nginx, Caddy, Traefik) bereit, der Port 443 auf Port 3000 weiterleitet, und setzen `HARNESS_URL_BASE=https://git.{{domain}}` in der `.env`. Für SSH-Git-Zugriff muss Port 3022 separat erreichbar sein. Anleitung für Caddy: [Caddy als Reverse Proxy mit automatischem HTTPS](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung).

### Wie viele Ressourcen benötigt Harness im laufenden Betrieb?

Im Leerlauf ohne aktive Pipelines genügen 2 CPU-Kerne und 2 GB RAM. Sobald CI/CD-Pipelines laufen, starten die Steps als eigenständige Docker-Container direkt auf dem Host, deren Ressourcenbedarf sich zum Harness-Prozess selbst addiert. Für Teams mit mehreren gleichzeitigen Pipeline-Runs empfehlen sich 4 Kerne und 4 bis 8 GB RAM. `GITNESS_CI_PARALLEL_WORKERS` (Standard: 2) lässt sich passend zu den verfügbaren Kernen erhöhen.

### Gibt es Telemetrie oder Cloud-Pflichtkomponenten?

Cloud-Pflichtkomponenten gibt es nicht, ein Harness-Konto ist nicht nötig. Standardmäßig sendet Harness Nutzungsstatistiken an `stats.drone.ci`; `GITNESS_METRIC_ENABLED=false` schaltet das ab.

## Fazit

Harness Open Source ersetzt mit einem Docker-Stack Git-Server, CI-System und Artifact-Registry. Entscheidend sind `GITNESS_URL_BASE`, `GITNESS_URL_CONTAINER` und `GITNESS_ENCRYPTER_SECRET` sowie PostgreSQL für Teams. Die letzte stabile Version stammt vom August 2025; prüfen Sie vor dem Einsatz den Projektstand auf GitHub. Wer eine sichere Docker-Compose-Umgebung aufbauen möchte, findet weitere Hinweise zu Secrets-Handling und Healthchecks in der Anleitung [Docker Compose absichern: Secrets, Healthchecks, Non-Root](https://s-edv.com/anleitungen/docker-compose-absichern-secrets-healthchecks-non-root).

## Weiterführende Anleitungen und Quellen

1. [Docker und Docker Compose auf Linux installieren: die Self-Hosting-Grundlage](https://s-edv.com/anleitungen/docker-compose-linux-selfhosting-grundlage)
2. [Caddy als Reverse Proxy mit automatischem HTTPS einrichten](https://s-edv.com/anleitungen/caddy-reverse-proxy-automatisches-https-anleitung)
3. [Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only](https://s-edv.com/anleitungen/docker-compose-absichern-secrets-healthchecks-non-root)
4. [3-2-1-Backup-Strategie umsetzen mit Restic, USB-Disk und S3-Cloud](https://s-edv.com/anleitungen/3-2-1-backup-strategie-praktisch-umsetzen)
5. [Docker-Container automatisch aktualisieren: Diun, WUD und Renovate im Vergleich](https://s-edv.com/anleitungen/docker-container-updates-watchtower-nachfolger-diun-wud)
6. [Gitea mit Docker: eigener Git-Server als GitHub-Alternative](https://s-edv.com/anleitungen/gitea-self-hosted-git-server-docker)

Quellen: [Harness Open Source auf GitHub (harness/harness)](https://github.com/harness/harness): offizielle Codebasis, Dockerfile, Releases; [Harness Developer Hub: Quick Start](https://developer.harness.io/docs/open-source/installation/quick-start); [Harness Developer Hub: Konfigurationsreferenz (Settings)](https://developer.harness.io/docs/open-source/installation/settings/); [Docker Hub: harness/harness](https://hub.docker.com/r/harness/harness).
