Betriebssystem: Debian 12
Benötigte Ressourcen:
CPU:2 vCore
RAM:2 GB
SSD:60 GB
Benötigte Ports:
| HTTP Redirect/ SSL Certificate Renewal | TCP | 80 | Nginx | Public |
| HTTPS/Bosh/Secure Websocket | TCP | 443 | Nginx | Public |
| SSH (optional) | TCP | 22 | OS | Private |
| Media Traffic | UDP | 10000 | JVB | Public |
| Media Traffic in Restricted Firewalls | TCP | 4443 | JVB | Public |
| For XMPP components (eg: Jicofo)* | TCP | 5347 | Prosody | Private |
| For external XMPP clients (eg: JVB, Jibri)** | TCP | 5222 | Prosody | Private |
audio device installieren/hinzufügen (für recordings)
sudo modprobe snd_aloop
echo "snd_aloop" | sudo tee -a /etc/modules
docker compose installieren
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
sudo tee /etc/apt/sources.list.d/docker.sources <
git clone https://github.com/jitsi/docker-jitsi-meet
cd docker-jitsi-meet
env anlegen
nano .env
# Where configuration will be stored on the host
CONFIG=~/.jitsi-meet-cfg
# Exposed ports on the host
HTTP_PORT=80
HTTPS_PORT=443
# Timezone
TZ=Europe/Berlin
# Public URL (required)
PUBLIC_URL=https://meet.DOMAIN.com
# JVB advertised IPs (IMPORTANT: use ONLY the public IP of this host)
JVB_ADVERTISE_IPS=IP_ADDRESS
# -----------------------------------------------------------------------------
# Let's Encrypt
# -----------------------------------------------------------------------------
ENABLE_LETSENCRYPT=1
LETSENCRYPT_DOMAIN=meet.DOMAIN.com
LETSENCRYPT_EMAIL=test@DOMAIN.com
#LETSENCRYPT_USE_STAGING=1
# -----------------------------------------------------------------------------
# Security passwords (generate with ./gen-passwords.sh)
# -----------------------------------------------------------------------------
JICOFO_AUTH_PASSWORD=9d3c7e08c403ae39f3c1bea5cf9b5
JVB_AUTH_PASSWORD=c5807af4266906af245533f75f91
JIGASI_XMPP_PASSWORD=934f9dde2742773d8e7f2f7e3e12d
JIGASI_TRANSCRIBER_PASSWORD=5d939e9c217113ce07b64d8eec96b
JIBRI_RECORDER_PASSWORD=9de1d873cf112decc74e59d311c0
JIBRI_XMPP_PASSWORD=0ddcfa26b1756d3a35b9fe01e0c99
# -----------------------------------------------------------------------------
# Docker
# -----------------------------------------------------------------------------
RESTART_POLICY=unless-stopped
JITSI_IMAGE_VERSION=stable
ENABLE_PREJOIN_PAGE=1
ENABLE_WELCOME_PAGE=1
# -----------------------------------------------------------------------------
# Recording (Jibri) - only if you really need it
# -----------------------------------------------------------------------------
ENABLE_JIBRI=1
ENABLE_RECORDING=1
JIBRI_ENABLE_PROMETHEUS=0
JIBRI_FINALIZE_RECORDING_ON_EMPTY=1
JIBRI_SHM_SIZE=2gb
# -----------------------------------------------------------------------------
# Optional: Authentication (uncomment if needed)
# -----------------------------------------------------------------------------
#ENABLE_AUTH=1
#ENABLE_GUESTS=1
#AUTH_TYPE=internal
XMPP_DOMAIN=meet.jitsi
XMPP_AUTH_DOMAIN=auth.meet.jitsi
XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
XMPP_RECORDER_DOMAIN=recorder.meet.jitsi
XMPP_SERVER=xmpp.meet.jitsi
XMPP_PORT=5222
JIBRI_XMPP_USER=jibri
JIBRI_RECORDER_USER=recorder
JIBRI_BREWERY_MUC=jibribrewery
./gen-passwords.sh
Die Docker Compose muss so aussehen, änderungen sind: der jibri service und die änderungen bezogen auf die XMPP_HIDDEN_DOMAIN statt XMPP_RECORDER_DOMAIN
services:
# Frontend
web:
image: jitsi/web:${JITSI_IMAGE_VERSION:-unstable}
restart: ${RESTART_POLICY:-unless-stopped}
ports:
- '${HTTP_PORT}:80'
- '${HTTPS_PORT}:443'
volumes:
- ${CONFIG}/web:/config:Z
- ${CONFIG}/web/crontabs:/var/spool/cron/crontabs:Z
- ${CONFIG}/transcripts:/usr/share/jitsi-meet/transcripts:Z
- ${CONFIG}/web/load-test:/usr/share/jitsi-meet/load-test:Z
labels:
service: "jitsi-web"
environment:
- AMPLITUDE_ID
- ANALYTICS_SCRIPT_URLS
- ANALYTICS_WHITELISTED_EVENTS
- AUDIO_QUALITY_OPUS_BITRATE
- AUTO_CAPTION_ON_RECORD
- BRANDING_DATA_URL
- BWE_ESTIMATOR_ENGINE
- BOSH_RELATIVE
- CHROME_EXTENSION_BANNER_JSON
- CODEC_ORDER_JVB
- CODEC_ORDER_JVB_MOBILE
- CODEC_ORDER_P2P
- CODEC_ORDER_P2P_MOBILE
- COLIBRI_WEBSOCKET_PORT
- COLIBRI_WEBSOCKET_JVB_LOOKUP_NAME
- COLIBRI_WEBSOCKET_REGEX
- CONFCODE_URL
- CORS_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN
- DEFAULT_LANGUAGE
- DEPLOYMENTINFO_ENVIRONMENT
- DEPLOYMENTINFO_ENVIRONMENT_TYPE
- DEPLOYMENTINFO_REGION
- DEPLOYMENTINFO_SHARD
- DESKTOP_SHARING_FRAMERATE_AUTO
- DESKTOP_SHARING_FRAMERATE_MIN
- DESKTOP_SHARING_FRAMERATE_MAX
- DIALIN_NUMBERS_URL
- DIALOUT_AUTH_URL
- DIALOUT_CODES_URL
- DISABLE_AUDIO_LEVELS
- DISABLE_COLIBRI_WEBSOCKET_JVB_LOOKUP
- DISABLE_DEEP_LINKING
- DISABLE_GRANT_MODERATOR
- DISABLE_HTTPS
- DISABLE_KICKOUT
- DISABLE_LOCAL_RECORDING
- DISABLE_POLLS
- DISABLE_PRIVATE_CHAT
- DISABLE_PROFILE
- DISABLE_REACTIONS
- DISABLE_REMOTE_VIDEO_MENU
- DISABLE_START_FOR_ALL
- DROPBOX_APPKEY
- DROPBOX_REDIRECT_URI
- DYNAMIC_BRANDING_URL
- ENABLE_ADAPTIVE_MODE
- ENABLE_AUDIO_PROCESSING
- ENABLE_AUTOMATIC_GAIN_CONTROL
- ENABLE_AUTH
- ENABLE_AUTH_DOMAIN
- ENABLE_BREAKOUT_ROOMS
- ENABLE_CALENDAR
- ENABLE_COLIBRI_WEBSOCKET
- ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX
- ENABLE_E2EPING
- ENABLE_FILE_RECORDING_SHARING
- ENABLE_GUESTS
- ENABLE_HSTS
- ENABLE_HTTP_REDIRECT
- ENABLE_IPV6
- ENABLE_LETSENCRYPT
- ENABLE_NO_AUDIO_DETECTION
- ENABLE_NOISY_MIC_DETECTION
- ENABLE_OCTO
- ENABLE_OPUS_RED
- ENABLE_PREJOIN_PAGE
- ENABLE_P2P
- ENABLE_WELCOME_PAGE
- ENABLE_CLOSE_PAGE
- ENABLE_LIVESTREAMING
- ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK
- ENABLE_LIVESTREAMING_HELP_LINK
- ENABLE_LIVESTREAMING_TERMS_LINK
- ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING
- ENABLE_LOAD_TEST_CLIENT
- ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT
- ENABLE_LOCAL_RECORDING_SELF_START
- ENABLE_RECORDING
- ENABLE_REMB
- ENABLE_REQUIRE_DISPLAY_NAME
- ENABLE_SERVICE_RECORDING
- ENABLE_SIMULCAST
- ENABLE_STATS_ID
- ENABLE_STEREO
- ENABLE_SUBDOMAINS
- ENABLE_TALK_WHILE_MUTED
- ENABLE_TCC
- ENABLE_TRANSCRIPTIONS
- ENABLE_VLA
- ENABLE_XMPP_WEBSOCKET
- ENABLE_JAAS_COMPONENTS
- ETHERPAD_PUBLIC_URL
- ETHERPAD_URL_BASE
- E2EPING_NUM_REQUESTS
- E2EPING_MAX_CONFERENCE_SIZE
- E2EPING_MAX_MESSAGE_PER_SECOND
- GOOGLE_ANALYTICS_ID
- GOOGLE_API_APP_CLIENT_ID
- HIDE_PREMEETING_BUTTONS
- HIDE_PREJOIN_DISPLAY_NAME
- HIDE_PREJOIN_EXTRA_BUTTONS
- INVITE_SERVICE_URL
- JVB_PREFER_SCTP
- LETSENCRYPT_DOMAIN
- LETSENCRYPT_EMAIL
- LETSENCRYPT_USE_STAGING
- LETSENCRYPT_ACME_SERVER
- MATOMO_ENDPOINT
- MATOMO_SITE_ID
- MICROSOFT_API_APP_CLIENT_ID
- NGINX_KEEPALIVE_TIMEOUT
- NGINX_RESOLVER
- NGINX_WORKER_PROCESSES
- NGINX_WORKER_CONNECTIONS
- PEOPLE_SEARCH_URL
- PREFERRED_LANGUAGE
- PUBLIC_URL
- P2P_PREFERRED_CODEC
- P2P_STUN_SERVERS
- RESOLUTION
- RESOLUTION_MIN
- RESOLUTION_WIDTH
- RESOLUTION_WIDTH_MIN
- START_AUDIO_MUTED
- START_AUDIO_ONLY
- START_SILENT
- START_WITH_AUDIO_MUTED
- START_VIDEO_MUTED
- START_WITH_VIDEO_MUTED
- TOKEN_AUTH_URL
- TOOLBAR_BUTTONS
- TRANSLATION_LANGUAGES
- TRANSLATION_LANGUAGES_HEAD
- TZ
- USE_APP_LANGUAGE
- VIDEOQUALITY_BITRATE_H264_LOW
- VIDEOQUALITY_BITRATE_H264_STANDARD
- VIDEOQUALITY_BITRATE_H264_HIGH
- VIDEOQUALITY_BITRATE_H264_FULL
- VIDEOQUALITY_BITRATE_H264_ULTRA
- VIDEOQUALITY_BITRATE_H264_SS_HIGH
- VIDEOQUALITY_BITRATE_VP8_LOW
- VIDEOQUALITY_BITRATE_VP8_STANDARD
- VIDEOQUALITY_BITRATE_VP8_HIGH
- VIDEOQUALITY_BITRATE_VP8_FULL
- VIDEOQUALITY_BITRATE_VP8_ULTRA
- VIDEOQUALITY_BITRATE_VP8_SS_HIGH
- VIDEOQUALITY_BITRATE_VP9_LOW
- VIDEOQUALITY_BITRATE_VP9_STANDARD
- VIDEOQUALITY_BITRATE_VP9_HIGH
- VIDEOQUALITY_BITRATE_VP9_FULL
- VIDEOQUALITY_BITRATE_VP9_ULTRA
- VIDEOQUALITY_BITRATE_VP9_SS_HIGH
- VIDEOQUALITY_BITRATE_AV1_LOW
- VIDEOQUALITY_BITRATE_AV1_STANDARD
- VIDEOQUALITY_BITRATE_AV1_HIGH
- VIDEOQUALITY_BITRATE_AV1_FULL
- VIDEOQUALITY_BITRATE_AV1_ULTRA
- VIDEOQUALITY_BITRATE_AV1_SS_HIGH
- VIDEOQUALITY_PREFERRED_CODEC
- XMPP_AUTH_DOMAIN
- XMPP_BOSH_URL_BASE
- XMPP_DOMAIN
- XMPP_GUEST_DOMAIN
- XMPP_MUC_DOMAIN
- XMPP_HIDDEN_DOMAIN
- XMPP_PORT
#- XMPP_RECORDER_DOMAIN
- WHITEBOARD_COLLAB_SERVER_PUBLIC_URL
- WHITEBOARD_COLLAB_SERVER_URL_BASE
networks:
meet.jitsi:
depends_on:
- jvb
# XMPP server
prosody:
image: jitsi/prosody:${JITSI_IMAGE_VERSION:-unstable}
restart: ${RESTART_POLICY:-unless-stopped}
expose:
- '${XMPP_PORT:-5222}'
- '${PROSODY_S2S_PORT:-5269}'
- '5347'
- '${PROSODY_HTTP_PORT:-5280}'
labels:
service: "jitsi-prosody"
volumes:
- ${CONFIG}/prosody/config:/config:Z
- ${CONFIG}/prosody/prosody-plugins-custom:/prosody-plugins-custom:Z
environment:
- AUTH_TYPE
- DISABLE_POLLS
- ENABLE_AUTH
- ENABLE_AV_MODERATION
- ENABLE_BREAKOUT_ROOMS
- ENABLE_END_CONFERENCE
- ENABLE_GUESTS
- ENABLE_IPV6
- ENABLE_LOBBY
- ENABLE_RECORDING
- ENABLE_S2S
- ENABLE_TRANSCRIPTIONS
- ENABLE_VISITORS
- ENABLE_XMPP_WEBSOCKET
- ENABLE_JAAS_COMPONENTS
- GC_TYPE
- GC_INC_TH
- GC_INC_SPEED
- GC_INC_STEP_SIZE
- GC_GEN_MIN_TH
- GC_GEN_MAX_TH
- GLOBAL_CONFIG
- GLOBAL_MODULES
- JIBRI_RECORDER_USER
- JIBRI_RECORDER_PASSWORD
- JIBRI_SIP_BREWERY_MUC
- JIBRI_XMPP_USER
- JIBRI_XMPP_PASSWORD
- JICOFO_AUTH_PASSWORD
- JICOFO_COMPONENT_SECRET
- JIGASI_TRANSCRIBER_PASSWORD
- JIGASI_TRANSCRIBER_USER
- JIGASI_XMPP_USER
- JIGASI_XMPP_PASSWORD
- JVB_AUTH_USER
- JVB_AUTH_PASSWORD
- JWT_APP_ID
- JWT_APP_SECRET
- JWT_ACCEPTED_ISSUERS
- JWT_ACCEPTED_AUDIENCES
- JWT_ASAP_KEYSERVER
- JWT_ALLOW_EMPTY
- JWT_AUTH_TYPE
- JWT_ENABLE_DOMAIN_VERIFICATION
- JWT_SIGN_TYPE
- JWT_TOKEN_AUTH_MODULE
- MATRIX_UVS_URL
- MATRIX_UVS_ISSUER
- MATRIX_UVS_AUTH_TOKEN
- MATRIX_UVS_SYNC_POWER_LEVELS
- MATRIX_LOBBY_BYPASS
- LOG_LEVEL
- LDAP_AUTH_METHOD
- LDAP_BASE
- LDAP_BINDDN
- LDAP_BINDPW
- LDAP_FILTER
- LDAP_VERSION
- LDAP_TLS_CIPHERS
- LDAP_TLS_CHECK_PEER
- LDAP_TLS_CACERT_FILE
- LDAP_TLS_CACERT_DIR
- LDAP_START_TLS
- LDAP_URL
- LDAP_USE_TLS
- MAX_PARTICIPANTS
- PROSODY_ADMINS
- PROSODY_AUTH_TYPE
- PROSODY_C2S_LIMIT
- PROSODY_C2S_REQUIRE_ENCRYPTION
- PROSODY_RESERVATION_ENABLED
- PROSODY_RESERVATION_REST_BASE_URL
- PROSODY_DISABLE_C2S_LIMIT
- PROSODY_DISABLE_S2S_LIMIT
- PROSODY_ENABLE_FILTER_MESSAGES
- PROSODY_ENABLE_RATE_LIMITS
- PROSODY_ENABLE_RECORDING_METADATA
- PROSODY_ENABLE_STANZA_COUNTS
- PROSODY_ENABLE_S2S
- PROSODY_ENABLE_METRICS
- PROSODY_GUEST_AUTH_TYPE
- PROSODY_HTTP_PORT
- PROSODY_LOG_CONFIG
- PROSODY_METRICS_ALLOWED_CIDR
- PROSODY_MODE
- PROSODY_RATE_LIMIT_LOGIN_RATE
- PROSODY_RATE_LIMIT_SESSION_RATE
- PROSODY_RATE_LIMIT_TIMEOUT
- PROSODY_RATE_LIMIT_ALLOW_RANGES
- PROSODY_RATE_LIMIT_CACHE_SIZE
- PROSODY_S2S_LIMIT
- PROSODY_S2S_PORT
- PROSODY_TRUSTED_PROXIES
- PROSODY_VISITOR_INDEX
- PROSODY_VISITORS_MUC_PREFIX
- PROSODY_VISITORS_S2S_VHOSTS
- PUBLIC_URL
- STUN_HOST
- STUN_PORT
- TURN_CREDENTIALS
- TURN_USERNAME
- TURN_PASSWORD
- TURN_HOST
- TURNS_HOST
- TURN_PORT
- TURNS_PORT
- TURN_TRANSPORT
- TURN_TTL
- TZ
- VISITORS_MAX_VISITORS_PER_NODE
- VISITORS_XMPP_DOMAIN
- VISITORS_XMPP_SERVER
- VISITORS_XMPP_PORT
- WAIT_FOR_HOST_DISABLE_AUTO_OWNERS
- XMPP_BREAKOUT_MUC_MODULES
- XMPP_CONFIGURATION
- XMPP_DOMAIN
- XMPP_AUTH_DOMAIN
- XMPP_GUEST_DOMAIN
- XMPP_MUC_DOMAIN
- XMPP_INTERNAL_MUC_DOMAIN
- XMPP_LOBBY_MUC_MODULES
- XMPP_MODULES
- XMPP_MUC_MODULES
- XMPP_MUC_CONFIGURATION
- XMPP_INTERNAL_MUC_MODULES
- XMPP_HIDDEN_DOMAIN
- XMPP_PORT
#- XMPP_RECORDER_DOMAIN
- XMPP_SERVER_S2S_PORT
- XMPP_SPEAKERSTATS_MODULES
networks:
meet.jitsi:
aliases:
- ${XMPP_SERVER:-xmpp.meet.jitsi}
# Focus component
jicofo:
image: jitsi/jicofo:${JITSI_IMAGE_VERSION:-unstable}
restart: ${RESTART_POLICY:-unless-stopped}
ports:
- '127.0.0.1:${JICOFO_REST_PORT:-8888}:8888'
volumes:
- ${CONFIG}/jicofo:/config:Z
labels:
service: "jitsi-jicofo"
environment:
- AUTH_TYPE
- BRIDGE_AVG_PARTICIPANT_STRESS
- BRIDGE_STRESS_THRESHOLD
- ENABLE_AUTH
- ENABLE_AUTO_OWNER
- ENABLE_MODERATOR_CHECKS
- ENABLE_CODEC_VP8
- ENABLE_CODEC_VP9
- ENABLE_CODEC_AV1
- ENABLE_CODEC_H264
- ENABLE_CODEC_OPUS_RED
- ENABLE_JVB_XMPP_SERVER
- ENABLE_OCTO
- ENABLE_OCTO_SCTP
- ENABLE_RECORDING
- ENABLE_SCTP
- ENABLE_SHARED_DOCUMENT_RANDOM_NAME
- ENABLE_TRANSCRIPTIONS
- ENABLE_VISITORS
- ENABLE_AUTO_LOGIN
- JICOFO_AUTH_LIFETIME
- JICOFO_AUTH_PASSWORD
- JICOFO_AUTH_TYPE
- JICOFO_BRIDGE_REGION_GROUPS
- JICOFO_ENABLE_AUTH
- JICOFO_ENABLE_BRIDGE_HEALTH_CHECKS
- JICOFO_CONF_INITIAL_PARTICIPANT_WAIT_TIMEOUT
- JICOFO_CONF_SINGLE_PARTICIPANT_TIMEOUT
- JICOFO_CONF_SOURCE_SIGNALING_DELAYS
- JICOFO_CONF_MAX_AUDIO_SENDERS
- JICOFO_CONF_MAX_VIDEO_SENDERS
- JICOFO_CONF_STRIP_SIMULCAST
- JICOFO_CONF_SSRC_REWRITING
- JICOFO_ENABLE_HEALTH_CHECKS
- JICOFO_ENABLE_ICE_FAILURE_DETECTION
- JICOFO_ENABLE_LOAD_REDISTRIBUTION
- JICOFO_ENABLE_REST
- JICOFO_HEALTH_CHECKS_USE_PRESENCE
- JICOFO_ICE_FAILURE_INTERVAL
- JICOFO_ICE_FAILURE_MIN_ENDPOINTS
- JICOFO_ICE_FAILURE_THRESHOLD
- JICOFO_MAX_MEMORY
- JICOFO_MULTI_STREAM_BACKWARD_COMPAT
- JICOFO_OCTO_REGION
- JICOFO_RESTART_REQUEST_MAX
- JICOFO_RESTART_REQUEST_INTERVAL
- JICOFO_TRUSTED_DOMAINS
- JIBRI_BREWERY_MUC
- JIBRI_REQUEST_RETRIES
- JIBRI_PENDING_TIMEOUT
- JIGASI_BREWERY_MUC
- JIGASI_SIP_URI
- JIGASI_TRUSTED_DOMAINS
- JVB_BREWERY_MUC
- JVB_XMPP_AUTH_DOMAIN
- JVB_XMPP_INTERNAL_MUC_DOMAIN
- JVB_XMPP_PORT
- JVB_XMPP_SERVER
- MAX_BRIDGE_PARTICIPANTS
- OCTO_BRIDGE_SELECTION_STRATEGY
- PROSODY_VISITORS_MUC_PREFIX
- SENTRY_DSN="${JICOFO_SENTRY_DSN:-0}"
- SENTRY_ENVIRONMENT
- SENTRY_RELEASE
- TZ
- VISITORS_MAX_PARTICIPANTS
- VISITORS_MAX_VISITORS_PER_NODE
- VISITORS_XMPP_AUTH_DOMAIN
- VISITORS_XMPP_SERVER
- VISITORS_XMPP_DOMAIN
- XMPP_DOMAIN
- XMPP_AUTH_DOMAIN
- XMPP_INTERNAL_MUC_DOMAIN
- XMPP_MUC_DOMAIN
- XMPP_HIDDEN_DOMAIN
- XMPP_SERVER
- XMPP_PORT
#- XMPP_RECORDER_DOMAIN
- MAX_SSRCS_PER_USER
- MAX_SSRC_GROUPS_PER_USER
depends_on:
- prosody
networks:
meet.jitsi:
# Video bridge
jvb:
image: jitsi/jvb:${JITSI_IMAGE_VERSION:-unstable}
restart: ${RESTART_POLICY:-unless-stopped}
ports:
- '${JVB_PORT:-10000}:${JVB_PORT:-10000}/udp'
- '127.0.0.1:${JVB_COLIBRI_PORT:-8080}:8080'
volumes:
- ${CONFIG}/jvb:/config:Z
labels:
service: "jitsi-jvb"
environment:
- AUTOSCALER_SIDECAR_KEY_FILE
- AUTOSCALER_SIDECAR_KEY_ID
- AUTOSCALER_SIDECAR_GROUP_NAME
- AUTOSCALER_SIDECAR_HOST_ID
- AUTOSCALER_SIDECAR_INSTANCE_ID
- AUTOSCALER_SIDECAR_PORT
- AUTOSCALER_SIDECAR_REGION
- AUTOSCALER_SIDECAR_SHUTDOWN_POLLING_INTERVAL
- AUTOSCALER_SIDECAR_STATS_POLLING_INTERVAL
- DISABLE_AWS_HARVESTER
- DOCKER_HOST_ADDRESS
- ENABLE_COLIBRI_WEBSOCKET
- ENABLE_JVB_XMPP_SERVER
- ENABLE_OCTO
- ENABLE_SCTP
- JVB_ADVERTISE_IPS
- JVB_ADVERTISE_PRIVATE_CANDIDATES
- JVB_AUTH_USER
- JVB_AUTH_PASSWORD
- JVB_BREWERY_MUC
- JVB_CC_TRUST_BWE
- JVB_DISABLE_STUN
- JVB_DISABLE_XMPP
- JVB_INSTANCE_ID
- JVB_PORT
- JVB_MUC_NICKNAME
- JVB_STUN_SERVERS
- JVB_LOG_FILE
- JVB_OCTO_BIND_ADDRESS
- JVB_OCTO_REGION
- JVB_OCTO_RELAY_ID
- JVB_REQUIRE_VALID_ADDRESS
- JVB_USE_USRSCTP
- JVB_WS_DOMAIN
- JVB_WS_SERVER_ID
- JVB_WS_TLS
- JVB_XMPP_AUTH_DOMAIN
- JVB_XMPP_INTERNAL_MUC_DOMAIN
- JVB_XMPP_PORT
- JVB_XMPP_SERVER
- PUBLIC_URL
- SENTRY_DSN="${JVB_SENTRY_DSN:-0}"
- SENTRY_ENVIRONMENT
- SENTRY_RELEASE
- COLIBRI_REST_ENABLED
- SHUTDOWN_REST_ENABLED
- TZ
- VIDEOBRIDGE_MAX_MEMORY
- XMPP_AUTH_DOMAIN
- XMPP_INTERNAL_MUC_DOMAIN
- XMPP_SERVER
- XMPP_PORT
depends_on:
- prosody
networks:
meet.jitsi:
# Recording component (Jibri)
jibri:
image: jitsi/jibri:${JITSI_IMAGE_VERSION:-unstable}
restart: ${RESTART_POLICY:-unless-stopped}
privileged: true
shm_size: ${JIBRI_SHM_SIZE:-2gb}
volumes:
- ${CONFIG}/jibri:/config:Z
devices:
- /dev/snd:/dev/snd
environment:
- DISPLAY=:0
- TZ
- PUBLIC_URL
- XMPP_DOMAIN
- XMPP_AUTH_DOMAIN
- XMPP_INTERNAL_MUC_DOMAIN
- XMPP_HIDDEN_DOMAIN
#- XMPP_RECORDER_DOMAIN
- XMPP_SERVER
- XMPP_PORT
- JIBRI_BREWERY_MUC
- JIBRI_XMPP_USER
- JIBRI_XMPP_PASSWORD
- JIBRI_RECORDER_USER
- JIBRI_RECORDER_PASSWORD
- JIBRI_FINALIZE_RECORDING_ON_EMPTY
depends_on:
- prosody
networks:
meet.jitsi:
# Custom network so all services can communicate using a FQDN
networks:
meet.jitsi:
cd ~/docker-jitsi-meet/transcribe/models
# 1) unzip installieren
apt-get update
apt-get install -y unzip
# 2) ZIP liegt vermutlich schon da – prüf kurz:
ls -la
# Falls vosk-de.zip nicht mehr da ist, neu laden:
curl -L -o vosk-de.zip "https://alphacephei.com/vosk/models/vosk-model-small-de-0.15.zip"
# 3) entpacken + umbenennen
unzip -q vosk-de.zip
rm -f vosk-de.zip
rm -rf vosk-de
mv vosk-model-small-de-0.15 vosk-de
# 4) Check
ls -la vosk-de | head -n 30
cat > ./create-transcribe-files.sh <<'BASH'
#!/usr/bin/env bash
set -euo pipefail
mkdir -p ./transcribe/prompts ./transcribe/models ./transcribe/output
cat > ./docker-compose.transcribe.yml <<'YML'
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
volumes:
- ./transcribe/ollama:/root/.ollama
ports:
- "127.0.0.1:11434:11434"
transcriber:
build:
context: ./transcribe
container_name: jitsi-transcriber
restart: unless-stopped
environment:
# IN DIESEN PFAD MUSST DU DEIN JIBRI-RECORDINGS-HOST-VERZEICHNIS EINTRAGEN (siehe Schritt 1)
RECORDINGS_DIR: /recordings
OUTPUT_DIR: /output
MODEL_DIR: /models/vosk-de
# Lokaler Summarizer (Ollama)
OLLAMA_URL: http://ollama:11434/api/generate
OLLAMA_MODEL: llama3.1:8b
ENABLE_SUMMARY: "1"
volumes:
# Host-Recording-Ordner -> Container /recordings
# WICHTIG: Passe links den Host-Pfad an, der bei docker inspect angezeigt wird.
- /root/.jitsi-meet-cfg/jibri/recordings:/recordings:ro
- ./transcribe/output:/output
- ./transcribe/models:/models:rw
- ./transcribe/prompts:/prompts:ro
depends_on:
- ollama
YML
cat > ./transcribe/Dockerfile <<'DOCKER'
FROM python:3.11-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
ffmpeg inotify-tools curl jq ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir vosk
WORKDIR /app
COPY worker.sh /app/worker.sh
COPY transcribe.py /app/transcribe.py
RUN chmod +x /app/worker.sh
ENTRYPOINT ["/app/worker.sh"]
DOCKER
cat > ./transcribe/transcribe.py <<'PY'
import json, sys, wave
from vosk import Model, KaldiRecognizer
MODEL_PATH = sys.argv[1]
WAV_PATH = sys.argv[2]
wf = wave.open(WAV_PATH, "rb")
if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getframerate() != 16000:
raise RuntimeError("WAV muss mono, 16kHz, 16-bit PCM sein.")
model = Model(MODEL_PATH)
rec = KaldiRecognizer(model, wf.getframerate())
rec.SetWords(True)
results = []
while True:
data = wf.readframes(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
results.append(json.loads(rec.Result()))
results.append(json.loads(rec.FinalResult()))
text_parts = []
for r in results:
t = (r.get("text") or "").strip()
if t:
text_parts.append(t)
print("\n".join(text_parts))
PY
cat > ./transcribe/prompts/summarize_de.txt <<'TXT'
Du bist ein Meeting-Assistent. Erstelle aus dem folgenden Transkript eine strukturierte Zusammenfassung auf Deutsch im Markdown-Format.
Anforderungen:
- Kurzer Überblick (max. 5 Sätze)
- Entscheidungen
- ToDos (wenn möglich mit Verantwortlichen und Fristen; wenn nicht genannt, dann offen markieren)
- Offene Fragen / Risiken
- Wichtige Fakten / Zahlen / Links (falls vorhanden)
Transkript:
TXT
cat > ./transcribe/worker.sh <<'SH'
#!/usr/bin/env bash
set -euo pipefail
log(){ echo "[$(date -Iseconds)] $*"; }
RECORDINGS_DIR="${RECORDINGS_DIR:-/recordings}"
OUTPUT_DIR="${OUTPUT_DIR:-/output}"
MODEL_DIR="${MODEL_DIR:-/models/vosk-de}"
ENABLE_SUMMARY="${ENABLE_SUMMARY:-1}"
OLLAMA_URL="${OLLAMA_URL:-http://ollama:11434/api/generate}"
OLLAMA_MODEL="${OLLAMA_MODEL:-llama3.1:8b}"
PROMPT_FILE="/prompts/summarize_de.txt"
mkdir -p "$OUTPUT_DIR"
if [[ ! -d "$MODEL_DIR" ]]; then
log "ERROR: Vosk-Model-Ordner fehlt: $MODEL_DIR"
log "Lege ein deutsches Vosk-Modell dort ab (entpackt). Beispiel: /models/vosk-de/*"
exit 1
fi
process_mp4() {
local mp4="$1"
local base
base="$(basename "$mp4" .mp4)"
local out_dir="$OUTPUT_DIR/$base"
local done_marker="$out_dir/.done"
mkdir -p "$out_dir"
if [[ -f "$done_marker" ]]; then
log "Skip (already done): $mp4"
return 0
fi
log "Process: $mp4"
log "Output: $out_dir"
# 1) Audio extrahieren
local wav="$out_dir/audio.wav"
ffmpeg -y -hide_banner -loglevel error -i "$mp4" -vn -ac 1 -ar 16000 -c:a pcm_s16le "$wav"
# 2) Transkribieren
local transcript="$out_dir/transcript.txt"
python3 /app/transcribe.py "$MODEL_DIR" "$wav" > "$transcript"
log "Transcript written: $transcript"
# 3) Zusammenfassung
if [[ "$ENABLE_SUMMARY" == "1" ]]; then
local summary="$out_dir/summary.md"
# Prompt zusammenbauen (Prompt-Datei + Transkript)
local prompt
prompt="$(cat "$PROMPT_FILE")"$'\n'"$(cat "$transcript")"
# Ollama API (non-stream)
curl -s "$OLLAMA_URL" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg model "$OLLAMA_MODEL" --arg prompt "$prompt" '{model:$model, prompt:$prompt, stream:false}')" \
| jq -r '.response' > "$summary"
log "Summary written: $summary"
else
log "Summary disabled (ENABLE_SUMMARY=$ENABLE_SUMMARY)"
fi
touch "$done_marker"
log "Done: $mp4"
}
# 0) Existing mp4 files einmalig abarbeiten (optional sinnvoll)
log "Initial scan in $RECORDINGS_DIR ..."
find "$RECORDINGS_DIR" -type f -name "*.mp4" -print0 | while IFS= read -r -d '' f; do
process_mp4 "$f" || log "ERROR processing $f"
done
# 1) Watcher: neue MP4 erkennen
log "Watching for new recordings in $RECORDINGS_DIR ..."
inotifywait -m -r -e close_write -e moved_to --format '%w%f' "$RECORDINGS_DIR" \
| while read -r f; do
if [[ "$f" == *.mp4 ]]; then
process_mp4 "$f" || log "ERROR processing $f"
fi
done
SH
touch ./transcribe/models/.keep ./transcribe/output/.keep
chmod +x ./create-transcribe-files.sh
echo "OK: Files created. Next: edit docker-compose.transcribe.yml and replace recordings path."
BASH
chmod +x ./create-transcribe-files.sh
./create-transcribe-files.sh
- /root/.jitsi-meet-cfg/jibri/recordings:/recordings:ro
# einsetzen in docker-compose.transcribe.yml
mkdir -p ./transcribe/models/vosk-de
docker compose -f docker-compose.yml -f docker-compose.transcribe.yml up -d --build
docker exec -it ollama ollama pull llama3.1:8b
docker compose -f docker-compose.yml -f docker-compose.transcribe.yml up -d
echo "deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list.d/bookworm.list
apt update
apt install openjdk-17-jre-headless -y
rm /etc/apt/sources.list.d/bookworm.list
apt update
apt install jitsi-meet -y
sudo apt update -y && sudo apt upgrade -y
curl -fsSL https://download.jitsi.org/jitsi-key.gpg.key -o /etc/apt/keyrings/jitsi-key.gpg.key
echo "deb [signed-by=/etc/apt/keyrings/jitsi-key.gpg.key] https://download.jitsi.org stable/" | tee /etc/apt/sources.list.d/jitsi.list
echo "deb [signed-by=/etc/apt/keyrings/jitsi-key.gpg.key] https://download.jitsi.org stable/" | tee /etc/apt/sources.list.d/jitsi.list
sudo apt update -y
sudo apt install jitsi-meet -y
gib deine domain ein in die abfragemaske ein
Als nächstes kommen drei screens:
1. SSL zertifikat (erste option wählen) obwohl nichts da steht
2. mail eingeben
3. Telefonie ablehnen
sudo nano -w /etc/jitsi/meet/jitsi.deine_domain.de-config.js
authentication = internal_plain
VirtualHost "guest.jitsi.crosstalksolutions.com"
authentication = "anonymous"
c2s_require_encryption = false
anonymousdomain: 'guest.jitsi.deine_domain.de',
sudo nano /etc/jitsi/jicofo/jicofo.conf
Füge die Authentifizierungs-Einstellungen hinzu: In der Sektion [jicofo] sollte ein Block [authentication] vorhanden sein. Falls nicht, füge diesen hinzu oder ergänze die Werte:
jicofo {
authentication {
enabled = true
type = "XMPP"
login-url = "jitsi.yourdomain.com"
}
}
sudo systemctl restart prosody
sudo systemctl restart jicofo
sudo systemctl restart jitsi-videobridge2
sudo prosodyctl register john jitsi.crosstalksolutions.com 12345
Das der Nutzername ist dann: john@jitsi.deine_domain.de
Das passwort bleibt gleich
weitere configs unter: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-configuration
sudo tee /usr/share/jitsi-meet/css/no-crop.css >/dev/null <<'CSS'
/* Verhindert Cropping/Zoom überall */
.videocontainer video,
.largeVideoContainer video,
#largeVideo,
video#largeVideo {
object-fit: contain !important;
}
/* neutrale Ränder, falls Balken entstehen */
.videocontainer,
.largeVideoContainer {
background: #000 !important;
overflow: hidden;
}
CSS
CSS einbinden (Link in index.html setzen)
Backup + Link direkt nach all.css einfügen:
sudo cp /usr/share/jitsi-meet/index.html /usr/share/jitsi-meet/index.html.bak
sudo sed -i '/css\/all\.css/a \ \ \ \ ' /usr/share/jitsi-meet/index.html
Browser-Cache umgehen / neu laden
Seite neu laden (Strg+F5). Bei Bedarf ?v=2 an die URL hängen.
Hinweis: Bei künftigen Jitsi-Updates kann index.html überschrieben werden. Dann einfach die sed-Zeile erneut ausführen.