Harness Open Source mit Docker installieren: End-to-End-DevOps-Plattform mit Git, CI/CD und Artifact-Registry
Harness Open Source vereint Git-Hosting, CI/CD-Pipelines und Artifact-Registry in einem Docker-Container. Die Anleitung zeigt den Aufbau mit Docker Compose und PostgreSQL, die kritischen Variablen und typische Fehler.
Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

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.
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-composev1). Falls noch nicht installiert, hilft die Anleitung Docker und Docker Compose auf Linux installieren - 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
Schritt 1: Projektordner anlegen
Legen Sie einen eigenen Ordner für den Harness-Stack an. Alle Konfigurationsdateien gehören dort hinein:
$ sudo mkdir -p /opt/harness
$ cd /opt/harnessWer keinen root-Zugriff hat oder lieber im Home-Verzeichnis arbeitet, kann auch ~/harness verwenden. Die Compose-Konfiguration funktioniert in beiden Fällen identisch.
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:
# Harness Open Source: Umgebungsvariablen
# /opt/harness/.env
# Admin-Konto (NUR beim allerersten Start mit leerer DB wirksam!)
HARNESS_ADMIN_EMAIL=admin@example.com
HARNESS_ADMIN_PASSWORD=IHR_ADMIN_PASSWORT
# 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=IHR_HEX_SCHLUESSEL
# PostgreSQL-Datenbankpasswort
POSTGRES_PASSWORD=IHR_DB_PASSWORT
# Ö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.example.com
HARNESS_URL_BASE=http://SERVER-IP:3000Den Schlüssel für HARNESS_SECRET_KEY erzeugen Sie einmalig per:
$ openssl rand -hex 16Kopieren 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.
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.
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@example.com}
- 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: bridgeDer 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 |
Syntax vor dem Start prüfen:
$ 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:
$ cd /opt/harness
$ docker compose up -dDocker 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.
Status beider Container prüfen:
$ docker compose psErwartete Ausgabe (beide Container Up, db mit healthy):
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:
$ docker compose logs harness --tail=30Eine 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:
$ curl -I http://localhost:3000/api/v1/system/healthErwartete 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:
- Projekt anlegen: Über „New Project“ ein Projekt für Ihr Team erstellen. Repositories, Pipelines und Einstellungen werden darunter gruppiert.
- Repository erstellen oder importieren: Unter „Repositories“ über „New Repository“ ein Repo anlegen oder ein bestehendes von GitHub/GitLab mit Code-History importieren.
- Clone-URL prüfen: Öffnen Sie ein Repository und kontrollieren Sie die Clone-URL. Sie muss mit dem Wert von
HARNESS_URL_BASEbeginnen, nicht mithttp://localhost. Zeigt sielocalhost, stimmt die Variable nicht. - 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.
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:
# 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 -dFür Update-Benachrichtigungen ohne automatische Updates eignen sich DIUN oder WUD, mehr dazu in der Anleitung Docker-Container automatisch aktualisieren nach dem Watchtower-Aus.
Nach dem Update:
$ docker compose ps
$ docker compose logs harness --tail=20Beide Container zeigen Up, keine Fehlermeldungen zu Datenbankmigrationen in den Logs. Die Web-UI ist weiterhin erreichbar und zeigt die bisherigen Daten.
Troubleshooting / Typische Fehler
- Clone-URLs zeigen
localhoststatt Server-IP:GITNESS_URL_BASEist nicht gesetzt oder enthält noch den Platzhalterwert. In der.envaufhttp://SERVER-IP:3000(oder die HTTPS-Domain) setzen, danndocker compose up -d. - CI/CD-Pipelines starten nicht / Steps erreichen Harness-API nicht:
GITNESS_URL_CONTAINERzeigt auflocalhoststatt auf den Container-Namenharness, oderGITNESS_CI_CONTAINER_NETWORKSist nicht auf das Compose-Netzwerk gesetzt. Beide Variablen wie in dercompose.yamloben konfigurieren. - Datenverlust nach Neustart: Quick-Start-Beispiele aus der offiziellen Doku nutzen
/tmp/harnessals Bind-Mount./tmpwird auf vielen Systemen beim Reboot geleert. Immer ein Named Volume oder einen Pfad außerhalb/tmp(z. B./opt/harness/data) verwenden. permission deniedauf/var/run/docker.sock: Standardmäßig läuft Harness als root, was ausreicht. Läuft der Container mit anderem Benutzer, muss dieser Mitglied derdocker-Gruppe auf dem Host sein.- Admin-Konto funktioniert nicht nach Passwort-Änderung in
.env:GITNESS_PRINCIPAL_ADMIN_EMAILundGITNESS_PRINCIPAL_ADMIN_PASSWORDwerden ausschließlich beim allerersten Start (leere Datenbank) ausgewertet. Passwort-Reset erfolgt über die Web-UI oder direkt in PostgreSQL. - PostgreSQL-Healthcheck schlägt fehl / Harness startet zu früh: Nur relevant, wenn
depends_onohnecondition: service_healthygenutzt wird. Diecompose.yamldieser Anleitung enthält den Healthcheck. - 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. - Altes
harness/gitness-Image im Einsatz: Dieses Image erhielt seit v3.0.0-beta.12 keine Updates mehr. Stattdessenharness/harnessmit fester Version verwenden. GITNESS_ENCRYPTER_SECRETnachträ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.example.com 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.
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.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren: die Self-Hosting-Grundlage
- Caddy als Reverse Proxy mit automatischem HTTPS einrichten
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only
- 3-2-1-Backup-Strategie umsetzen mit Restic, USB-Disk und S3-Cloud
- Docker-Container automatisch aktualisieren: Diun, WUD und Renovate im Vergleich
- Gitea mit Docker: eigener Git-Server als GitHub-Alternative
Quellen: Harness Open Source auf GitHub (harness/harness): offizielle Codebasis, Dockerfile, Releases; Harness Developer Hub: Quick Start; Harness Developer Hub: Konfigurationsreferenz (Settings); Docker Hub: harness/harness.


