Diese Anleitung richtet OpenWhistle mit Docker Compose ein. Am Ende läuft der digitale Meldekanal Ihrer internen Meldestelle auf Ihrem eigenen Server. Die maßgebliche Referenz bleibt die Installationsanleitung in der Dokumentation.

Voraussetzungen

  • Ein Linux-Server mit 1 vCPU, mindestens 512 MB RAM (1 GB empfohlen) und 5 GB Speicher
  • Docker 24 oder neuer mit dem Plugin docker compose (v2)
  • Eine Domain, die auf den Server zeigt, etwa meldestelle.ihr-unternehmen.de
  • Offene Ports 80 und 443
  • Root- oder sudo-Zugriff und etwas Übung im Terminal

Automatisch statt von Hand

Das Repository enthält eine Ansible-Rolle unter ansible/. Sie installiert Docker, legt einen Systemdienst an und holt ein Let's-Encrypt-Zertifikat. Diese Anleitung zeigt den Weg von Hand.

Schritt 1: Server bereitstellen

VPS auswählen

Ein kleiner VPS genügt. Wählen Sie einen Anbieter mit Rechenzentrum in der EU, der einen Auftragsverarbeitungsvertrag nach Art. 28 DSGVO anbietet.

Legen Sie einen Benutzer mit sudo-Rechten an und melden Sie sich per SSH-Schlüssel an.

Schritt 2: Docker installieren

Docker Engine und Compose-Plugin

Folgen Sie der offiziellen Installationsanleitung von Docker für Ihre Distribution. Prüfen Sie danach beide Versionen:

docker --version          # 24.0 oder neuer
docker compose version    # v2.x

Schritt 3: OpenWhistle konfigurieren

Repository klonen und .env anlegen

Klonen Sie das Repository und kopieren Sie die Beispielkonfiguration:

git clone https://github.com/openwhistle/OpenWhistle.git
cd OpenWhistle
cp .env.example .env

Tragen Sie in .env mindestens diese Werte ein. Zufällige Schlüssel erzeugt openssl rand -hex 32.

# Produktions-Stack mit nginx und TLS für jeden docker-compose-Befehl
COMPOSE_FILE=docker-compose.prod.yml

# Mindestens 32 Zeichen
SECRET_KEY=<openssl rand -hex 32>
# Empfohlen: eigener Schlüssel für die Verschlüsselung der Meldungen
ENCRYPTION_KEY=<openssl rand -hex 32>

# Passwörter für Datenbank und Redis, dieselben in den URLs
POSTGRES_PASSWORD=starkes-passwort
REDIS_PASSWORD=zweites-starkes-passwort
DATABASE_URL=postgresql+asyncpg://openwhistle:starkes-passwort@db:5432/openwhistle
REDIS_URL=redis://:zweites-starkes-passwort@redis:6379/0

# Ihre Domain, für Links in E-Mails und das Ersatzzertifikat
APP_PUBLIC_URL=https://meldestelle.ihr-unternehmen.de
TLS_HOSTNAME=meldestelle.ihr-unternehmen.de

# Optional: E-Mail an die Meldestelle und Fristerinnerungen
# NOTIFY_EMAIL_ENABLED=true
# NOTIFY_EMAIL_TO=meldestelle@ihr-unternehmen.de
# NOTIFY_SMTP_HOST=smtp.ihr-mailserver.de
# NOTIFY_SMTP_PORT=587
# NOTIFY_SMTP_USER=meldestelle@ihr-unternehmen.de
# NOTIFY_SMTP_PASSWORD=mail-passwort
# REMINDER_ENABLED=true

Schlüssel sichern

Mit ENCRYPTION_KEY werden die Meldungen verschlüsselt, ohne ihn mit SECRET_KEY. Geht der Schlüssel verloren, sind die Meldungen nicht mehr lesbar. Bewahren Sie ihn in einem Passwortmanager oder Secret-Store auf.

Alle weiteren Einstellungen stehen in der Konfigurationstabelle.

Schritt 4: HTTPS-Zertifikat hinterlegen

Let's-Encrypt-Zertifikat nach nginx/certs/

Der Stack liefert HTTPS von Anfang an. Ohne eigenes Zertifikat erzeugt der Dienst tls-init ein selbstsigniertes für TLS_HOSTNAME. Das genügt zum Testen, nicht für den Betrieb.

Holen Sie ein Zertifikat, solange Port 80 noch frei ist, und kopieren Sie es. Ein Symlink nach /etc/letsencrypt/live zeigt im Container ins Leere.

sudo certbot certonly --standalone -d meldestelle.ihr-unternehmen.de
sudo cp /etc/letsencrypt/live/meldestelle.ihr-unternehmen.de/fullchain.pem nginx/certs/
sudo cp /etc/letsencrypt/live/meldestelle.ihr-unternehmen.de/privkey.pem nginx/certs/
sudo chmod 600 nginx/certs/privkey.pem

Zum Erneuern kopieren Sie die neuen Dateien und starten docker compose up -d tls-init nginx. Ein Neustart von nginx allein behält das alte Zertifikat.

Schritt 5: OpenWhistle starten

Alle Dienste starten

Ein Befehl startet App, PostgreSQL, Redis und nginx. Die Datenbankmigrationen laufen beim Start automatisch.

docker compose up -d
docker compose ps

# Health-Check
curl -s https://meldestelle.ihr-unternehmen.de/health
# {"status":"ok","version":"2.1.0","components":{"database":"ok","redis":"ok"}}

Schritt 6: Den ersten Admin anlegen

Einrichtungsassistent mit Einmal-Token

Der Assistent verlangt ein Einmal-Token. Ohne eigenes SETUP_TOKEN steht es im Log:

docker compose logs app | grep "Setup token"

Öffnen Sie dann https://meldestelle.ihr-unternehmen.de/setup:

  1. Token eingeben.
  2. Benutzername mit 3 bis 64 Zeichen und ein Passwort mit mindestens 12 Zeichen wählen.
  3. QR-Code mit einer Authenticator-App scannen und den sechsstelligen Code eingeben. Dieser Schritt ist Pflicht.
  4. Optional zustimmen, dass die Installation einmal täglich gezählt wird. Vorgabe ist nein.

Das erste Konto ist ein Superadmin. Notieren Sie das TOTP-Geheimnis offline: Backup-Codes gibt es nicht.

Schritt 7: Grundkonfiguration im Admin-Bereich

Melden Sie sich unter /admin/login an. Diese Seiten richten Sie zuerst ein:

Seite Wofür
/admin/categoriesKategorien der Meldungen, etwa Finanzen, Arbeitssicherheit, Diskriminierung
/admin/locationsStandorte; sind welche aktiv, fragt der Assistent danach
/admin/usersweitere Konten; neue Konten sind Fallbearbeiter, jedes braucht TOTP
/admin/telephone-channelLeitfaden für den mündlichen Kanal nach § 16 Abs. 3 HinSchG
/admin/systeminstallierte Version und Dateiprüfung

Schicken Sie danach eine Testmeldung über das Formular. Prüfen Sie, ob sie im Dashboard erscheint und die E-Mail ankommt.

Fristerinnerungen

Mit REMINDER_ENABLED=true erinnert OpenWhistle per E-Mail, bevor die 7-Tage- oder die 3-Monats-Frist nach § 17 HinSchG abläuft. Die Prüfung läuft alle 30 Minuten.

Schritt 8: Die Meldestelle bekannt machen

Beschäftigte brauchen klare Informationen über das interne Verfahren und über externe Meldestellen (§ 7 Abs. 3, § 13 Abs. 2 HinSchG). Bewährte Wege:

  • Rundmail mit dem Link zum Meldeformular
  • Eintrag im Intranet oder Wiki
  • Hinweis im Verhaltenskodex
  • Aushang für Beschäftigte ohne Computerarbeitsplatz, mit Telefonnummer

Updates einspielen

Das Image ist über OPENWHISTLE_VERSION in .env auf eine Version festgelegt. So aktualisieren Sie:

# Zuerst sichern: ein Rollback braucht das Backup
docker compose exec db pg_dump -U openwhistle openwhistle > backup.sql
# Compose-Datei und nginx-Konfiguration ändern sich mit den Releases
git pull
# OPENWHISTLE_VERSION in .env auf die neue Version setzen, dann
docker compose pull
docker compose up -d

Lesen Sie vorher den Eintrag im Änderungsprotokoll. Sicherheitskorrekturen erscheinen als Patch-Versionen; auf GitHub können Sie die Releases abonnieren.

Was Sie sichern müssen

Was Warum
Datenbank (pg_dump)Meldungen, Nachrichten und standardmäßig auch die Anhänge
.enventhält die Schlüssel; ohne sie ist das Backup nicht lesbar
S3-Bucketnur wenn Anhänge dort liegen (STORAGE_BACKEND=s3)

Erst ansehen, dann installieren

Die Live-Demo zeigt Meldeformular und Admin-Bereich. Kein Konto nötig, Zurücksetzen alle 6 Stunden.

Live-Demo öffnen →

Häufige Probleme

„port is already allocated“ beim Start

Port 80, 443 oder 8080 ist belegt. Den Onion-Zugang auf 127.0.0.1:8080 veröffentlicht nginx immer. sudo ss -tlnp zeigt, welcher Prozess den Port hält.

nginx startet nicht, tls-init meldet einen Fehler

Meist ist der Schlüssel falsch berechtigt oder ein Symlink. Kopieren Sie die Dateien, und geben Sie privkey.pem root mit 0600 oder 0644. Die Meldung von tls-init nennt Pfad und Grund.

Der Einrichtungsassistent lehnt das Token ab

Nehmen Sie das jüngste Token aus dem Log. Redis speichert es nur im Arbeitsspeicher: startet Redis neu, entsteht ein neues. Ein selbst gesetztes SETUP_TOKEN gilt immer.

Weitere Ressourcen: Vollständige Dokumentation · HinSchG-Compliance-Leitfaden · Was ein kostenloses Hinweisgebersystem kostet · GitHub Issues