adminForge

free | no tracking | no logging | no advertising

Das ist unser Motto. Mit adminForge bieten wir kostenlose Dienste an. Unser Ziel ist es, eine freie und datensparsame Alternative zu bekannten Diensten bereitzustellen. Seit 2014 betreiben wir adminForge gemeinsam mit Spaß an der Technik und an Open-Source.

Eigene Jitsi Meet Instanz installieren (Docker / Ubuntu / Nginx)

Jitsi Meet ist eine Open Source Videokonferenz Software die durch die Corona Pandemie in aller Munde ist. Ich persönliche finde Jitsi Meet eine der besten Alternativen zu Diensten wie Zoom, Teams und Co. Warum dies so ist und wie man Jitsi Meet benutzt beschreibe ich hier im
Tutorial: Videokonferenzen mit Jitsi Meet.

Ich möchte euch in dieser Anleitung zeigen wie die adminForge Jitsi Meet Instanz aufgesetzt wurde.

Aufbau des Setups:

  • Ubuntu/Debian 11 als Betriebssystem
  • Bereits laufender NGINX Webserver. Wir verwenden diesen als Proxy.
  • Let’s Encrypt SSL Zertifikat (oder anderes)
  • Aktuelle Docker CE Version
  • Aktuelle Docker Compose Version
  • Eine (Sub)domain wird benötigt die auf die IP-Adresse des Servers verweist – wie meet.example.com oder teamjoin.de

Offene Ports in der Firewall:

  • 80/tcp
  • 443/tcp
  • 4443/tcp
  • 10000/udp

Punkt 1: Docker CE installieren

Wir installieren Docker CE nach Anleitung.

Benötigte Pakete installieren:

apt-get update && apt-get install -y ca-certificates curl gnupg lsb-release git

GPG Key herunterladen:

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Repository hinzufügen Ubuntu:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Repository hinzufügen Debian:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker CE installieren:

apt-get update && apt-get -y install docker-ce docker-ce-cli containerd.io

Die aktuellste Docker Compose Version installieren wir mit diesem Befehl:

curl -L "https://github.com/docker/compose/releases/download/$(curl -s https://github.com/docker/compose/releases/latest | cut -d "/" -f8 | cut -d "\"" -f1)/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose; chmod +x /usr/local/bin/docker-compose

Eine aktuelle Docker Compose Version, oder andere Installationsmöglichkeiten, gibt es hier: Docker Compose Anleitung

Punkt 2: Jitsi Meet Docker herunterladen

Zuerst erstellen wir uns einen Docker Ordner:

mkdir /opt/docker

Wir wechseln in den Ordner und klonen das Git Repository:

cd /opt/docker
git clone https://github.com/jitsi/docker-jitsi-meet.git

Nun wechseln wir in diesen Ordner und kopieren die .env Konfigurationsdatei:

mv docker-jitsi-meet/ jitsi-meet/
cd jitsi-meet/
cp env.example .env

Jetzt erstellen wir sichere Passwörter mit dem vorhandenen Script:

./gen-passwords.sh

Die Konfigurationsordner in unserem Verzeichnis .jitsi-meet-cfg müssen wir manuell erstellen:

mkdir -p .jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody,jicofo,jvb,jigasi,jibri}

Punkt 3: Jitsi Meet .env anpassen

Bevor es losgeht müssen wir ein paar Mindeständerungen vornehmen.

Ich habe den Konfigurationsordner von Jitsi Meet gerne im selben Docker Pfad. Darum passen wir diesen an:

# Directory where all configuration will be stored
CONFIG=.jitsi-meet-cfg

Da wir später unseren Nginx Proxy vorschalten stellen wir die HTTP Ports von Jitsi Meet auf localhost um:

# Exposed HTTP port
HTTP_PORT=127.0.0.1:180

# Exposed HTTPS port
HTTPS_PORT=127.0.0.1:1443

Nun estellt die Timezone in Deutschland auf Europe/Berlin:

# System time zone
TZ=Europe/Berlin

Nun tragen wir die (Sub)domain die wir für diese Jitsi Meet Instanz verwenden möchten ein:

# Public URL for the web service
PUBLIC_URL=https://meet.example.com

Einschalten von ein paar nützlichen Funktionen:

# Control whether the lobby feature should be enabled or not
ENABLE_LOBBY=1

# Show a prejoin page before entering a conference
ENABLE_PREJOIN_PAGE=1

# Enable breakout rooms
ENABLE_BREAKOUT_ROOMS=1

Etherpad URL setzen, um gemeinsam an Dokumenten arbeiten zu können:

# Set etherpad-lite public URL (uncomment to enable)
ETHERPAD_PUBLIC_URL=https://pad.adminforge.de/p/

Damit alles reibungslos läuft, tragen wir die Docker Host IP-Adresse ein:

# Public IP address
JVB_ADVERTISE_IPS=< PUBLIC-IP-ADDRESS >

Einen STUN Server für P2P Videokonferenzen (max. 2 Personen) hinterlegen wir ebenfalls. Damit werden nicht die von jitsi.net oder damals Google verwendet. Ihr dürft gerne die adminForge STUN Server verwenden:

# STUN servers used to discover the server's public IP
JVB_STUN_SERVERS=relay.adminforge.de:443,relay2.adminforge.de:443

Damit nicht die unstable Version genutzt wird forcieren wir stable:

JITSI_IMAGE_VERSION=stable

Punkt 4: Nginx Port 80 vHost erstellen

Nginx installieren.

apt install nginx

Wir wechseln in den Nginx vHost Ordner.

cd /etc/nginx/sites-available/

Nun erstellen wir einen Port 80 vHost für Let’s Encrypt und zur Weiterleitung an HTTPS.

server {
  listen 80;
  listen [::]:80;
  server_name meet.example.com;
  location /.well-known/acme-challenge {
    root /var/www/letsencrypt;
    default_type "text/plain";
    try_files $uri =404;
  }
  location / {
    return 301 https://$host$request_uri;
  }
}

Wir aktivieren die Konfiguration.

ln -s /etc/nginx/sites-available/meet.example.com.conf /etc/nginx/sites-enabled/meet.example.com.conf

Nun laden wir die Konfiguration.

systemctl reload nginx.service

Wir erstellen uns ein kostenloses Let’s Encrypt SSL-Zertifikat. Ich beschreibe ausführlich wie dies funktioniert hier.

Eure Domain meet.example.com muss vor diesem Schritt bereits auf die Server IP-Adresse auflösen!

Let’s Encrypt Kurzanleitung:

apt install -y socat
curl https://get.acme.sh | sh
source .bashrc
acme.sh --set-default-ca --server letsencrypt
acme.sh --set-default-chain --preferred-chain "ISRG" --server letsencrypt

...
CERT_HOME="/etc/ssl/private"
...

mkdir /etc/nginx/global
mkdir /var/www/letsencrypt
chown www-data. /var/www/letsencrypt -R

acme.sh --issue -k ec-384 -w /var/www/letsencrypt -d meet.example.com --reloadcmd "systemctl reload nginx.service"

openssl dhparam -out /etc/nginx/dhparams.pem 4096

Punkt 5: Nginx Port 443 vHost erstellen

Nun erstellen wir einen vHost für SSL, bsp. meet.example.com_ssl.conf. Bitte passt nach eurem Bedarf alles an.

WICHTIG: Damit der Jitsi Meet Desktop Client funktioniert, darf der Security Header X-Frame-Options nicht gesetzt werden und Content-Security-Policy nur abgeschwächt!

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name meet.example.com;
  access_log off;
  error_log /var/log/nginx/meet.example.com.error.log;
  ssl_certificate /etc/ssl/private/meet.example.com_ecc/fullchain.cer;
  ssl_certificate_key /etc/ssl/private/meet.example.com_ecc/meet.example.com.key;

  ssl_dhparam /etc/nginx/dhparams.pem;
  ssl_buffer_size 1400;
  ssl_session_timeout 1d;
  ssl_session_cache shared:SSL:50m;
  ssl_session_tickets off;
  ssl_protocols TLSv1.2 TLSv1.3;
  # Ab Nginx 1.15.4
  # ssl_early_data on;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers on;
  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_ecdh_curve X25519:P-384:P-256:P-521;
  resolver 176.9.93.198 176.9.1.117 valid=300s;
  resolver_timeout 5s;

  add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
  add_header X-Xss-Protection "1; mode=block";
  add_header X-Content-Type-Options nosniff;
  add_header Referrer-Policy same-origin;
  proxy_cookie_path / "/; HTTPOnly; Secure";
  add_header Expect-CT "enforce, max-age=21600";
  add_header Feature-Policy "payment none";

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

   location / {
        log_not_found off;
        proxy_cache_valid 200 120m;
        proxy_set_header        Host    $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Scheme $scheme;
        proxy_pass http://127.0.0.1:180/;
        }

   location ~ ^/colibri-ws/([a-zA-Z0-9-\.]+)/(.*) {
        tcp_nodelay on;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://127.0.0.1:180/colibri-ws/$1/$2$is_args$args;
        }

   location /xmpp-websocket {
        tcp_nodelay on;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:180/xmpp-websocket;
        }
}

Wenn alles angepasst ist erstellen wir den Symlink, ersetzt hier auch wieder meet.example.com:

ln -s /etc/nginx/sites-available/meet.example.com_ssl.conf /etc/nginx/sites-enabled/meet.example.com_ssl.conf

Jetzt prüfen wir ob alles korrekt ist un laden Nginx Konfigurationen neu:

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

systemctl reload nginx.service

Punkt 6: Docker Container starten

Die Docker Container können nun gestartet werden. Wir verwenden dazu den sehr praktischen docker-compose Befehl, der uns gleich alle 4 Container korrekt startet:

docker-compose up -d

Ob alles läuft prüfen wir mit diesem Befehl:

docker-compose ps
NAME                   COMMAND             SERVICE             STATUS              PORTS
jitsi-meet-jicofo-1    "/init"             jicofo              running
jitsi-meet-jvb-1       "/init"             jvb                 running             0.0.0.0:4443->4443/tcp, 0.0.0.0:10000->10000/udp, :::4443->4443/tcp, :::10000->10000/udp
jitsi-meet-prosody-1   "/init"             prosody             running             5347/tcp
jitsi-meet-web-1       "/init"             web                 running             127.0.0.1:180->80/tcp, 127.0.0.1:1443->443/tcp

Stoppen könnt ihr alles mit docker-compose down.

WICHTIG: Wenn Anpassungen an der .env gemacht wurden, muss der Config-Ordner .jitsi-meet-cfg gelöscht werden um die Änderungen wirksam zu machen!

docker-compose down
rm -r .jitsi-meet-cfg
mkdir -p .jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody,jicofo,jvb,jigasi,jibri}
docker-compose up -d

Fertig! Unter https://meet.example.com ist eure eigene Jitsi Meet Instanz nun erreichbar.

Als nächstes: Jitsi Meet Docker Instanz anpassen

Euer adminForge Team

UnterstützenDas Betreiben der Dienste, Webseite und Server machen wir gerne, kostet aber leider auch Geld.
Unterstütze unsere Arbeit mit einer Spende.