Jitsi Meet mit Docker installieren: Browser-Videokonferenz selbst hosten (DSGVO-konform)
Jitsi Meet selbst hosten: quelloffenes Videokonferenzsystem per Docker Compose, ohne Account, alle Daten auf dem eigenen Server. Anleitung mit .env, Passwort-Generierung, Verzeichnisrechten und Let's Encrypt.
Geprüft am 29.09.2026 · für docker-jitsi-meet stable-11248
WerbelinksMit * 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

Bei Zoom oder Microsoft Teams fließen die Daten durch fremde Rechenzentren, oft außerhalb der EU. Jitsi Meet ist ein quelloffenes Videokonferenzsystem (Apache 2.0, 29.000+ GitHub-Stars), das per Docker Compose auf einem Linux-Server läuft. Teilnehmer treten per URL im Browser bei, ohne App, Konto oder Gebühren; Audio, Video und Chat bleiben auf Ihrem Server.
Voraussetzungen
- Linux-Server oder VM (Ubuntu 22.04/24.04 empfohlen) mit mindestens 2 CPU-Kernen und 4 GB RAM für bis zu 20 Teilnehmer
- Docker Engine >= 20.10 und Docker Compose Plugin v2 (Befehl:
docker composeohne Bindestrich) – siehe Docker und Docker Compose auf Linux installieren - Öffentliche IP-Adresse (statisch empfohlen) und ein Domainname mit DNS-A-Record auf den Server – Pflicht für Let's Encrypt und mobile Apps
- Firewall-Freigaben: Port 80/tcp, 443/tcp und 10000/udp müssen zum Server durchgeleitet werden
- Root- oder sudo-Zugriff auf den Host sowie Internetzugang für Image-Download und ACME-Challenge
Schritt 1: Projektverzeichnis und Konfigurationsordner anlegen
Legen Sie das Projektverzeichnis an und laden Sie das offizielle Release-Archiv von GitHub; es enthält docker-compose.yml, env.example und gen-passwords.sh.
sudo mkdir -p /opt/jitsi-meet
sudo chown $USER: /opt/jitsi-meet
cd /opt/jitsi-meet
# Aktuelles Stable-Release herunterladen (Stand: stable-11248)
wget -q https://github.com/jitsi/docker-jitsi-meet/archive/refs/tags/stable-11248.tar.gz
tar xzf stable-11248.tar.gz --strip-components=1
rm stable-11248.tar.gzSeit Release stable-11146 laufen die Container ohne Root-Rechte (UID/GID 1000) mit schreibgeschütztem Dateisystem. Die Verzeichnisse storage und tmp müssen Sie vor dem ersten Start anlegen und beschreibbar machen, sonst verweigert der Container den Start mit einer Meldung, die das Verzeichnis nennt.
mkdir -p ~/.jitsi-meet-cfg/{web,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri,transcriber}
mkdir -p ~/.jitsi-meet-cfg/storage/{jibri,prosody,transcripts,web}
mkdir -p ~/.jitsi-meet-cfg/tmp/{web-crontabs,web-load-test}
chmod 777 ~/.jitsi-meet-cfg/storage/{jibri,prosody,transcripts,web}
chmod 777 ~/.jitsi-meet-cfg/tmp/{web-crontabs,web-load-test}Verifizieren: Prüfen Sie, ob alle Verzeichnisse angelegt wurden:
ls ~/.jitsi-meet-cfg/
# Erwartete Ausgabe: jibri jicofo jigasi jvb prosody storage tmp transcriber webSchritt 2: .env-Datei anlegen und Passwörter generieren
Kopieren Sie die Beispiel-Konfiguration und passen Sie die wichtigsten Werte an. Danach erzeugt gen-passwords.sh sichere Passwörter für die internen XMPP-Verbindungen und schreibt sie in die .env. Das ist Pflicht: Leere Passwörter führen zu Startfehlern oder unsicheren Verbindungen.
cp env.example .envPassen Sie in .env mindestens diese Werte an; in env.example sind die meisten auskommentiert (# entfernen):
# Öffentliche URL – MUSS korrekt gesetzt sein, sonst funktionieren mobile Apps nicht
PUBLIC_URL=https://meet.example.com
# HTTP/HTTPS-Ports (Defaults 8000/8443 – bei Let's Encrypt auf 80/443 ändern)
HTTP_PORT=80
HTTPS_PORT=443
# Zeitzone
TZ=Europe/Berlin
# Image-Tag: ohne Angabe gilt die Version des heruntergeladenen Releases
# JITSI_IMAGE_VERSION=stable-11248
# Restart-Policy
RESTART_POLICY=unless-stopped
# Konfigurationsverzeichnis
CONFIG=~/.jitsi-meet-cfg
# Öffentliche IP des Docker-Hosts – PFLICHT bei NAT/Router!
JVB_ADVERTISE_IPS=1.2.3.4
# HTTP auf HTTPS umleiten
ENABLE_HTTP_REDIRECT=1
# Let's Encrypt aktivieren (ohne LETSENCRYPT_ACME_SERVER nutzt acme.sh ZeroSSL)
ENABLE_LETSENCRYPT=1
LETSENCRYPT_DOMAIN=meet.example.com
LETSENCRYPT_EMAIL=admin@example.com
LETSENCRYPT_ACME_SERVER="letsencrypt"
# Passwörter – werden gleich von gen-passwords.sh gefüllt
JICOFO_AUTH_PASSWORD=
JVB_AUTH_PASSWORD=Jetzt Passwörter generieren:
chmod +x gen-passwords.sh
./gen-passwords.shDas Skript nutzt openssl rand -hex 16, setzt alle Passwörter (auch für optionale Dienste wie Jibri und Jigasi) und legt ein Backup unter .env.bak an.
Verifizieren: Kontrollieren Sie, dass die Passwörter nicht mehr leer sind:
grep -E "JICOFO_AUTH_PASSWORD|JVB_AUTH_PASSWORD" .env
# Erwartet: beide Werte mit zufälligem Hex-String gefüllt, z. B.:
# JICOFO_AUTH_PASSWORD=a3f7c9d2e1b04f8a...Schritt 3: docker-compose.yml prüfen
Die mitgelieferte docker-compose.yml enthält alle vier Pflicht-Services; die Images kommen seit stable-11146 aus der GitHub Container Registry (ghcr.io/jitsi):
| Service | Image | Funktion | Port |
|---|---|---|---|
| web | ghcr.io/jitsi/web | Nginx + Meet-UI (Frontend) | 80/tcp, 443/tcp |
| prosody | ghcr.io/jitsi/prosody | XMPP-Server (intern) | – |
| jicofo | ghcr.io/jitsi/jicofo | Konferenz-Koordinator (Focus) | – |
| jvb | ghcr.io/jitsi/jvb | Videobridge, Medien-Router | 10000/udp |
| Umgebungsvariable | Zweck | Pflicht? |
|---|---|---|
| PUBLIC_URL | Öffentliche URL des Servers | Ja (Produktion) |
| JVB_ADVERTISE_IPS | Öffentliche IP bei NAT | Ja (bei NAT) |
| JICOFO_AUTH_PASSWORD | XMPP-Auth für Jicofo | Ja |
| JVB_AUTH_PASSWORD | XMPP-Auth für Videobridge | Ja |
| ENABLE_LETSENCRYPT | Let's-Encrypt-Integration | Empfohlen |
| DISABLE_HTTPS | Hinter externem Reverse Proxy | Situativ |
Die docker-compose.yml liest alle Werte aus der .env und verwendet das interne Docker-Netzwerk meet.jitsi. Prosody ist nach außen nicht erreichbar und kommuniziert ausschließlich mit den anderen Containern im internen Bridge-Netzwerk – sicheres Default-Design. Für den Einstieg reicht die mitgelieferte Datei unverändert. Die Grundlagen zu Docker Compose erklärt in der Anleitung Docker Compose: Multi-Container-Stacks aufbauen.
Verifizieren: Prüfen Sie, ob die Syntax der docker-compose.yml gültig ist:
docker compose config --quiet && echo "OK"
# Erwartete Ausgabe: OKSchritt 4: Stack starten
Starten Sie die Container im Hintergrund; der erste Image-Download kann einige Minuten dauern.
docker compose up -dBeobachten Sie anschließend den Start-Prozess:
docker compose logs -fSobald keine neuen Zeilen erscheinen, mit Strg+C abbrechen.
Verifizieren: Alle vier Container müssen den Status Up haben:
docker compose ps
# Erwartete Ausgabe (gekürzt):
# NAME STATUS PORTS
# jitsi-meet-web-1 Up 0.0.0.0:80->8000/tcp, 0.0.0.0:443->8443/tcp
# jitsi-meet-prosody-1 Up
# jitsi-meet-jicofo-1 Up
# jitsi-meet-jvb-1 Up 0.0.0.0:10000->10000/udpPrüfen Sie zusätzlich, ob der web-Container antwortet:
curl -I http://localhost:80
# Erwartet: HTTP/1.1 301 Moved Permanently (Weiterleitung auf HTTPS, dank ENABLE_HTTP_REDIRECT=1)Schritt 5: HTTPS und erstes Meeting im Browser testen
Rufen Sie https://meet.example.com mit Ihrer Domain auf. Der ACME-Client im web-Container hat beim ersten Start ein TLS-Zertifikat angefordert, sofern DNS-A-Record und Ports 80/443 stimmen.
Auf der Startseite geben Sie einen Raumnamen ein, starten das Meeting und erteilen die Kamera- und Mikrofonberechtigung. Zum Funktionstest öffnen Sie denselben Link in einem zweiten Tab oder auf einem anderen Gerät.
Hinweis zu WebRTC: Kamera- und Mikrofon-APIs funktionieren nur über HTTPS. Per http:// erscheint „Your browser does not support WebRTC“ oder der Kamerazugriff wird verweigert.
Verifizieren: Testen Sie das TLS-Zertifikat:
curl -sv https://meet.example.com 2>&1 | grep -E "SSL|subject|issuer"
# Erwartet: Aussteller Let's Encrypt, kein ZertifikatsfehlerTesten Sie mit drei Teilnehmern: Ab dem dritten schaltet Jitsi vom Peer-to-Peer-Modus auf die Videobridge (jvb) um. Fehlen dann Audio/Video, ist JVB_ADVERTISE_IPS falsch oder Port 10000/UDP blockiert.
Schritt 6: Betrieb hinter einem Reverse Proxy
Wenn Sie bereits einen Nginx Proxy Manager, Traefik oder Caddy als Reverse Proxy betreiben (empfehlenswert für Multidienst-Server), sind einige Anpassungen notwendig. Siehe dazu auch Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten.
Setzen Sie in der .env folgende Werte. Der Proxy muss WebSocket-Verbindungen für den Pfad /xmpp-websocket weiterreichen.
# HTTPS-Terminierung übernimmt der Reverse Proxy
DISABLE_HTTPS=1
ENABLE_HTTP_REDIRECT=0
# Internen HTTP-Port auf einen freien Wert legen (kein Konflikt mit Proxy)
HTTP_PORT=8000
HTTPS_PORT=8443
# Let's Encrypt im Container deaktivieren (Proxy übernimmt Zertifikate)
ENABLE_LETSENCRYPT=0Kritisch: Port 10000/UDP lässt sich nicht über einen HTTP-Reverse-Proxy leiten. Er muss direkt am Docker-Host exponiert und zur jvb weitergeleitet sein; der Proxy übernimmt nur HTTPS auf Port 443.
Starten Sie den Stack nach der Änderung neu:
docker compose up -d --force-recreateVerifizieren:
docker compose ps
# web-Container zeigt jetzt 0.0.0.0:8000->8000/tcp und 0.0.0.0:8443->8443/tcp
# jvb-Container muss weiterhin Port 10000/udp exponieren
curl -I http://localhost:8000
# Erwartet: HTTP/1.1 200 OKSchritt 7: Authentifizierung aktivieren (optional)
Standardmäßig kann jeder mit der URL einen Raum eröffnen. Mit interner Authentifizierung eröffnen nur registrierte Nutzer Räume, Gäste treten per Einladungslink bei.
# In .env ergänzen:
ENABLE_AUTH=1
ENABLE_GUESTS=1
AUTH_TYPE=internalNach einem Neustart (docker compose up -d) legen Sie Nutzer mit folgendem Befehl im prosody-Container an (der Befehl gibt nichts aus):
docker compose exec prosody prosodyctl --config /run/prosody/config/prosody.cfg.lua register nutzer meet.jitsi geheimespasswortVerifizieren: Rufen Sie die Meeting-URL auf. Ohne Anmeldung sollte die Konferenz nicht startbar sein. Nach dem Login mit den Zugangsdaten öffnet sich der Raum normal.
Schritt 8: Update und Backup
Für ein Update laden Sie das neue Release-Archiv wie in Schritt 1 und entpacken es über die vorhandenen Dateien; die .env bleibt erhalten, die neue docker-compose.yml bringt den passenden Image-Tag mit. Lesen Sie vorher die Release Notes, größere Releases ändern mitunter die Verzeichnisstruktur (wie stable-11146). Danach:
docker compose pull
docker compose up -dSichern Sie vor jedem Update die .env (enthält alle Passwörter) und das Konfigurationsverzeichnis:
cp .env .env.backup-$(date +%Y%m%d)
tar czf ~/jitsi-cfg-backup-$(date +%Y%m%d).tar.gz ~/.jitsi-meet-cfg/Eine systematische Backup-Strategie für Self-Hosted-Dienste beschreibt die Anleitung 3-2-1-Backup-Strategie umsetzen. Wie Sie Docker Compose Stacks zusätzlich mit Secrets und Healthchecks absichern, zeigt Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only.
Verifizieren:
docker compose ps
# Alle Container zeigen Up – ggf. mit neuem Image-Digest
docker compose images
# Zeigt die aktuell verwendeten Image-TagsTroubleshooting / Typische Fehler
- Audio/Video funktioniert nur bei 2 Teilnehmern, bricht bei 3+ ab:
JVB_ADVERTISE_IPSfehlt oder zeigt auf die Docker-interne statt die öffentliche IP, oder Port 10000/UDP ist in Firewall/Router gesperrt. Lösung:JVB_ADVERTISE_IPS=x.x.x.xsetzen, danndocker compose up -d --force-recreate jvb. - „Your browser does not support WebRTC“ / Kamerazugriff verweigert: Aufruf per HTTP statt HTTPS. Lösung:
ENABLE_LETSENCRYPT=1setzen oder eigenes Zertifikat einbinden. - „Meeting Has Been Oops'd“ / Konferenz lässt sich nicht betreten: Prosody startet nicht korrekt wegen leerer XMPP-Passwörter. Lösung:
./gen-passwords.sherneut ausführen, danndocker compose down && docker compose up -d. - Let's-Encrypt-Zertifikat schlägt fehl: Port 80 oder 443 belegt oder
LETSENCRYPT_DOMAINpasst nicht zum DNS-A-Record. Lösung: DNS prüfen, Port-Konflikt lösen. Rate-Limit beachten (höchstens 5 identische Zertifikate pro Woche); zum TestenLETSENCRYPT_USE_STAGING=1. - Seite nach
docker compose upnicht erreichbar, Container startet nicht: Verzeichnisse unter~/.jitsi-meet-cfg/storageoder~/.jitsi-meet-cfg/tmpfehlen oder sind für UID 1000 nicht beschreibbar;docker compose logsnennt das Verzeichnis. Lösung: diemkdir- undchmod-Befehle aus Schritt 1 ausführen, dann Stack neu starten. - Konfigurationsänderungen werden nicht übernommen: Seit stable-11146 erzeugen die Container ihre Konfiguration bei jedem Start aus der
.env. Änderungen wirken erst nachdocker compose up -d; ein bloßesrestartliest die.envnicht neu. Eigene Web-Einstellungen gehören in~/.jitsi-meet-cfg/web/custom-config.js. - Mobile Apps können keine Verbindung aufbauen:
PUBLIC_URLzeigt auflocalhostoder eine interne IP; Apps brauchen eine öffentliche URL mit gültigem Zertifikat (kein Self-Signed). Lösung:PUBLIC_URL=https://meet.example.comsetzen. - SELinux-Fehler auf RHEL/Fedora/Rocky Linux: Volume-Mounts ohne
:Z-Flag – SELinux blockiert Schreibzugriff. Lösung: alle Volume-Mounts mit:Zversehen (in der offiziellendocker-compose.ymlbereits so vorgesehen).
Häufige Fragen
Brauche ich eine Datenbank wie PostgreSQL oder MySQL?
Nein. Prosody, der XMPP-Server, verwaltet den Konferenzzustand in Dateien. Redis braucht es nur in Hochverfügbarkeitsszenarien mit mehreren Videobridges.
Kann ich Jitsi hinter meinem bestehenden Nginx oder Traefik betreiben?
Ja: DISABLE_HTTPS=1 setzen und HTTP_PORT auf einen freien internen Port legen; der Proxy muss WebSocket-Verbindungen durchreichen (Schritt 5). Port 10000/UDP bleibt direkt am Docker-Host exponiert.
Wie sichere ich das Meeting ab, damit nicht jeder beitreten kann?
ENABLE_AUTH=1 und AUTH_TYPE=internal setzen (Schritt 6). Mit ENABLE_GUESTS=1 dürfen Gäste ohne Account beitreten, sobald ein authentifizierter Nutzer den Raum geöffnet hat.
Werden Gespräche aufgezeichnet?
Nicht standardmäßig. Aufzeichnung und Livestreaming erfordern den optionalen Jibri-Container (jibri.yml-Erweiterung) und das Kernel-Modul snd-aloop auf dem Host (modprobe snd-aloop).
Wie aktualisiere ich auf eine neue Version?
Wie in Schritt 7: Release-Archiv über die vorhandenen Dateien entpacken, dann docker compose pull && docker compose up -d. Vorher ~/.jitsi-meet-cfg und .env sichern.
Läuft Jitsi Meet auf ARM-Servern (Raspberry Pi, Apple M-Chip)?
Ja, die Images gibt es für amd64 und arm64. Ein Raspberry Pi 4 oder 5 mit 4 GB RAM reicht für bis zu zehn Teilnehmer; für größere Gruppen ist ein VPS empfehlenswert.
Was ist der Unterschied zwischen „stable“ und einem versionierten Tag wie „stable-11248“?
stable zeigt auf das aktuellste stabile Release und zieht bei docker compose pull Updates. stable-11248 ist eingefroren: reproduzierbar, aber manuelle Updates. Die mitgelieferte docker-compose.yml nutzt den versionierten Tag ihres Releases. latest gibt es in der GitHub Container Registry nicht.
Fazit
Der Vier-Container-Stack läuft ohne externe Datenbank, bringt Let's Encrypt mit und hält alle Daten auf dem eigenen Server. Häufigster Stolperstein ist die Videobridge: Port 10000/udp muss direkt zum jvb-Container, und JVB_ADVERTISE_IPS muss die öffentliche IP enthalten.
Weiterführende Anleitungen und Quellen
- Docker und Docker Compose auf Linux installieren (Ubuntu/Debian): die Self-Hosting-Grundlage
- Traefik als Docker-Reverse-Proxy mit automatischem HTTPS einrichten
- Docker Compose absichern: Secrets, Healthchecks, Non-Root und Read-Only für den Produktivbetrieb
- VPS absichern und härten: Anleitung mit UFW, SSH-Keys und Fail2Ban
Offizielle Dokumentation: Jitsi Meet Handbook – Self-Hosting Guide Docker · Quellcode und Releases: github.com/jitsi/docker-jitsi-meet


