diff --git a/.zuul.yaml b/.zuul.yaml index 1afb6abf6f..4ef77df7d2 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -145,6 +145,39 @@ vars: *gitea_vars files: *gitea_files +# Jitsi-meet jobs +- job: + name: system-config-build-image-jitsi-meet + description: Build jitsi-meet images + parent: system-config-build-image + provides: jitsi-meet-container-image + vars: &jitsi-meet_vars + docker_images: + - context: docker/jitsi-meet + target: web + repository: opendevorg/jitsi-meet-web + - context: docker/jitsi-meet + target: prosody + repository: opendevorg/jitsi-meet-prosody + files: &jitsi-meet_files + - docker/jitsi-meet/.* + +- job: + name: system-config-upload-image-jitsi-meet + description: Build and upload a jitsi-meet image. + parent: system-config-upload-image + requires: python-base-container-image + provides: jitsi-meet-container-image + vars: *jitsi-meet_vars + files: *jitsi-meet_files + +- job: + name: system-config-promote-image-jitsi-meet + description: Promote a previously published jitsi-meet image to latest. + parent: system-config-promote-image + vars: *jitsi-meet_vars + files: *jitsi-meet_files + # Haproxy-statsd jobs - job: name: system-config-build-image-haproxy-statsd @@ -1450,6 +1483,7 @@ - name: system-config-build-image-jinja-init soft: true - system-config-build-image-gitea + - system-config-build-image-jitsi-meet - system-config-build-image-haproxy-statsd: dependencies: - name: opendev-buildset-registry @@ -1500,6 +1534,7 @@ - name: system-config-upload-image-jinja-init soft: true - system-config-upload-image-gitea + - system-config-upload-image-jitsi-meet - system-config-upload-image-haproxy-statsd: dependencies: - name: opendev-buildset-registry @@ -1512,6 +1547,7 @@ - system-config-promote-image-jinja-init - system-config-promote-image-gitea-init - system-config-promote-image-gitea + - system-config-promote-image-jitsi-meet - system-config-promote-image-haproxy-statsd - system-config-promote-image-python-base - system-config-promote-image-python-builder diff --git a/docker/jitsi-meet/Dockerfile b/docker/jitsi-meet/Dockerfile new file mode 100644 index 0000000000..6a48e0a2d0 --- /dev/null +++ b/docker/jitsi-meet/Dockerfile @@ -0,0 +1,132 @@ +# Based on https://github.com/jitsi/docker-jitsi-meet/ +# Licensed under the ASL v2. + +FROM docker.io/library/debian:stretch-slim as build +ENV DEBIAN_FRONTEND=noninteractive + +RUN \ + mkdir -p /usr/share/man/man1/ && \ + apt-get update && \ + apt-get dist-upgrade -y && \ + apt-get install -y apt-transport-https \ + apt-utils ca-certificates gnupg git build-essential fakeroot \ + devscripts openjdk-8-jre-headless openjdk-8-jdk-headless maven && \ + curl -sS https://deb.nodesource.com/gpgkey/nodesource.gpg.key | \ + apt-key add - && \ + echo "deb https://deb.nodesource.com/node_10.x stretch main" | \ + tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update && \ + apt-get install -y nodejs npm && \ + echo "deb http://ftp.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/backports.list && \ + apt-get update && \ + apt-get install -y -t stretch-backports debhelper && \ + rm -rf /var/lib/apt/lists/ + +RUN git clone https://github.com/jitsi/jitsi-meet + +RUN \ + cd jitsi-meet && \ + npm install && \ + make && \ + debuild -b -uc -us + +###################################################################### +FROM docker.io/library/debian:stretch-slim as base + +ADD https://github.com/just-containers/s6-overlay/releases/download/v1.21.4.0/s6-overlay-amd64.tar.gz /tmp/s6-overlay.tar.gz +ADD https://github.com/subchen/frep/releases/download/v1.3.5/frep-1.3.5-linux-amd64 /usr/bin/frep + +COPY base/rootfs / + +RUN \ + tar xfz /tmp/s6-overlay.tar.gz -C / && \ + rm -f /tmp/*.tar.gz && \ + apt-dpkg-wrap apt-get update && \ + apt-dpkg-wrap apt-get install -y apt-transport-https apt-utils ca-certificates gnupg && \ + echo "deb http://ftp.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/backports.list && \ + apt-dpkg-wrap apt-get dist-upgrade -y && \ + apt-cleanup && \ + chmod +x /usr/bin/frep + +RUN \ + [ "$JITSI_RELEASE" = "unstable" ] && \ + apt-dpkg-wrap apt-get update && \ + apt-dpkg-wrap apt-get install -y jq procps curl vim iputils-ping net-tools && \ + apt-cleanup || \ + true + +ENTRYPOINT [ "/init" ] + +###################################################################### +FROM base as web + +COPY --from=build /*.deb /output/ + +RUN \ + apt-dpkg-wrap apt-get update && \ + apt-dpkg-wrap apt-get install -y cron nginx-extras && \ + dpkg -i /output/jitsi-meet-web*.deb &&\ + apt-dpkg-wrap apt-get install -y -t stretch-backports certbot && \ + apt-cleanup && \ + rm -fr /output && \ + rm -f /etc/nginx/conf.d/default.conf && \ + rm -f /usr/share/jitsi-meet/interface_config.js + +COPY web/rootfs/ / + +EXPOSE 80 443 + +VOLUME ["/config", "/etc/letsencrypt"] + +###################################################################### +FROM base as prosody + +COPY --from=build /*.deb /output/ + +RUN \ + apt-dpkg-wrap apt-get update \ + && apt-dpkg-wrap apt-get install -t stretch-backports -y \ + prosody \ + liblua5.2-dev \ + sasl2-bin \ + libsasl2-modules-ldap \ + libsasl2-dev \ + libssl1.0-dev \ + lua-basexx \ + lua-ldap \ + luarocks \ + git \ + gcc \ + patch \ + && luarocks install cyrussasl 1.1.0-1 \ + && luarocks install lua-cjson 2.1.0-1 \ + && luarocks install luajwtjitsi 1.3-7 \ + && luarocks install net-url 0.9-1 \ + && apt-dpkg-wrap apt-get remove -t stretch-backports -y \ + git \ + gcc \ + luarocks \ + libsasl2-dev \ + libssl1.0-dev \ + liblua5.2-dev \ + && apt-cleanup \ + && rm -rf /etc/prosody /var/cache/apt + +RUN \ + apt-dpkg-wrap apt-get update \ + && apt-dpkg-wrap apt-get install -y libssl-dev \ + && dpkg -x /output/jitsi-meet-prosody*.deb /tmp \ + && mv /tmp/usr/share/jitsi-meet/prosody-plugins /prosody-plugins \ + && apt-cleanup \ + && rm -fr /output \ + && rm -rf /tmp/usr /var/cache/apt + +RUN \ + sed -i s/hook/hook_global/g /prosody-plugins/mod_auth_token.lua \ + && patch -d /usr/lib/prosody/modules/muc -p0 < /prosody-plugins/muc_owner_allow_kick.patch + +COPY prosody/rootfs/ / + +EXPOSE 5222 5269 5347 5280 + +VOLUME ["/config", "/prosody-plugins-custom"] diff --git a/docker/jitsi-meet/README b/docker/jitsi-meet/README new file mode 100644 index 0000000000..08c0971629 --- /dev/null +++ b/docker/jitsi-meet/README @@ -0,0 +1,3 @@ +All files in and below this directory are from +https://github.com/jitsi/docker-jitsi-meet/ +Licensed under the ASL v2. diff --git a/docker/jitsi-meet/base/rootfs/etc/apt/apt.conf.d/99local b/docker/jitsi-meet/base/rootfs/etc/apt/apt.conf.d/99local new file mode 100644 index 0000000000..a2fba33091 --- /dev/null +++ b/docker/jitsi-meet/base/rootfs/etc/apt/apt.conf.d/99local @@ -0,0 +1,2 @@ +APT::Install-Recommends "false"; +APT::Install-Suggests "false"; diff --git a/docker/jitsi-meet/base/rootfs/etc/cont-finish.d/.gitkeep b/docker/jitsi-meet/base/rootfs/etc/cont-finish.d/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker/jitsi-meet/base/rootfs/etc/cont-init.d/.gitkeep b/docker/jitsi-meet/base/rootfs/etc/cont-init.d/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker/jitsi-meet/base/rootfs/etc/cont-init.d/01-set-timezone b/docker/jitsi-meet/base/rootfs/etc/cont-init.d/01-set-timezone new file mode 100644 index 0000000000..957a7b6d48 --- /dev/null +++ b/docker/jitsi-meet/base/rootfs/etc/cont-init.d/01-set-timezone @@ -0,0 +1,6 @@ +#!/usr/bin/with-contenv sh + +if [ $TZ ]; then + [ -f /usr/share/zoneinfo/$TZ ] && cp /usr/share/zoneinfo/$TZ /etc/localtime || echo "WARNING: $TZ is not a valid time zone." + [ -f /usr/share/zoneinfo/$TZ ] && echo "$TZ" > /etc/timezone +fi diff --git a/docker/jitsi-meet/base/rootfs/etc/fix-attrs.d/.gitkeep b/docker/jitsi-meet/base/rootfs/etc/fix-attrs.d/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker/jitsi-meet/base/rootfs/etc/services.d/.gitkeep b/docker/jitsi-meet/base/rootfs/etc/services.d/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker/jitsi-meet/base/rootfs/usr/bin/apt-cleanup b/docker/jitsi-meet/base/rootfs/usr/bin/apt-cleanup new file mode 100755 index 0000000000..1d3d61b58a --- /dev/null +++ b/docker/jitsi-meet/base/rootfs/usr/bin/apt-cleanup @@ -0,0 +1,3 @@ +#!/bin/sh + +rm -rf /var/lib/apt/lists/ diff --git a/docker/jitsi-meet/base/rootfs/usr/bin/apt-dpkg-wrap b/docker/jitsi-meet/base/rootfs/usr/bin/apt-dpkg-wrap new file mode 100755 index 0000000000..84ab0e2785 --- /dev/null +++ b/docker/jitsi-meet/base/rootfs/usr/bin/apt-dpkg-wrap @@ -0,0 +1,8 @@ +#!/bin/sh + +export LC_ALL=C +export DEBIAN_FRONTEND=noninteractive + +bin=$1 +shift +exec "$bin" "$@" diff --git a/docker/jitsi-meet/base/rootfs/usr/bin/tpl b/docker/jitsi-meet/base/rootfs/usr/bin/tpl new file mode 100755 index 0000000000..c18fb0e5e5 --- /dev/null +++ b/docker/jitsi-meet/base/rootfs/usr/bin/tpl @@ -0,0 +1,4 @@ +#!/bin/bash + +exec frep $1:- + diff --git a/docker/jitsi-meet/prosody/rootfs/defaults/conf.d/jitsi-meet.cfg.lua b/docker/jitsi-meet/prosody/rootfs/defaults/conf.d/jitsi-meet.cfg.lua new file mode 100644 index 0000000000..ea55fc629b --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/defaults/conf.d/jitsi-meet.cfg.lua @@ -0,0 +1,103 @@ +admins = { "{{ .Env.JICOFO_AUTH_USER }}@{{ .Env.XMPP_AUTH_DOMAIN }}" } +plugin_paths = { "/prosody-plugins/", "/prosody-plugins-custom" } +http_default_host = "{{ .Env.XMPP_DOMAIN }}" + +{{ $ENABLE_AUTH := .Env.ENABLE_AUTH | default "0" | toBool }} +{{ $AUTH_TYPE := .Env.AUTH_TYPE | default "internal" }} +{{ $JWT_ASAP_KEYSERVER := .Env.JWT_ASAP_KEYSERVER | default "" }} +{{ $JWT_ALLOW_EMPTY := .Env.JWT_ALLOW_EMPTY | default "0" | toBool }} +{{ $JWT_AUTH_TYPE := .Env.JWT_AUTH_TYPE | default "token" }} +{{ $JWT_TOKEN_AUTH_MODULE := .Env.JWT_TOKEN_AUTH_MODULE | default "token_verification" }} + +{{ if and $ENABLE_AUTH (eq $AUTH_TYPE "jwt") .Env.JWT_ACCEPTED_ISSUERS }} +asap_accepted_issuers = { "{{ join "\",\"" (splitList "," .Env.JWT_ACCEPTED_ISSUERS) }}" } +{{ end }} + +{{ if and $ENABLE_AUTH (eq $AUTH_TYPE "jwt") .Env.JWT_ACCEPTED_AUDIENCES }} +asap_accepted_audiences = { "{{ join "\",\"" (splitList "," .Env.JWT_ACCEPTED_AUDIENCES) }}" } +{{ end }} + +VirtualHost "{{ .Env.XMPP_DOMAIN }}" +{{ if $ENABLE_AUTH }} + {{ if eq $AUTH_TYPE "jwt" }} + authentication = "{{ $JWT_AUTH_TYPE }}" + app_id = "{{ .Env.JWT_APP_ID }}" + app_secret = "{{ .Env.JWT_APP_SECRET }}" + allow_empty_token = {{ if $JWT_ALLOW_EMPTY }}true{{ else }}false{{ end }} + {{ if $JWT_ASAP_KEYSERVER }} + asap_key_server = "{{ .Env.JWT_ASAP_KEYSERVER }}" + {{ end }} + + {{ else if eq $AUTH_TYPE "ldap" }} + authentication = "cyrus" + cyrus_application_name = "xmpp" + allow_unencrypted_plain_auth = true + {{ else if eq $AUTH_TYPE "internal" }} + authentication = "internal_plain" + {{ end }} +{{ else }} + authentication = "anonymous" +{{ end }} + ssl = { + key = "/config/certs/{{ .Env.XMPP_DOMAIN }}.key"; + certificate = "/config/certs/{{ .Env.XMPP_DOMAIN }}.crt"; + } + modules_enabled = { + "bosh"; + "pubsub"; + "ping"; + {{ if .Env.XMPP_MODULES }} + "{{ join "\";\n\"" (splitList "," .Env.XMPP_MODULES) }}"; + {{ end }} + {{ if and $ENABLE_AUTH (eq $AUTH_TYPE "ldap") }} + "auth_cyrus"; + {{end}} + } + + c2s_require_encryption = false + +{{ if and $ENABLE_AUTH (.Env.ENABLE_GUESTS | default "0" | toBool) }} +VirtualHost "{{ .Env.XMPP_GUEST_DOMAIN }}" + authentication = "anonymous" + c2s_require_encryption = false +{{ end }} + +VirtualHost "{{ .Env.XMPP_AUTH_DOMAIN }}" + ssl = { + key = "/config/certs/{{ .Env.XMPP_AUTH_DOMAIN }}.key"; + certificate = "/config/certs/{{ .Env.XMPP_AUTH_DOMAIN }}.crt"; + } + authentication = "internal_plain" + +{{ if .Env.XMPP_RECORDER_DOMAIN }} +VirtualHost "{{ .Env.XMPP_RECORDER_DOMAIN }}" + modules_enabled = { + "ping"; + } + authentication = "internal_plain" +{{ end }} + +Component "{{ .Env.XMPP_INTERNAL_MUC_DOMAIN }}" "muc" + modules_enabled = { + "ping"; + {{ if .Env.XMPP_INTERNAL_MUC_MODULES }} + "{{ join "\";\n\"" (splitList "," .Env.XMPP_INTERNAL_MUC_MODULES) }}"; + {{ end }} + } + storage = "memory" + muc_room_cache_size = 1000 + +Component "{{ .Env.XMPP_MUC_DOMAIN }}" "muc" + storage = "memory" + modules_enabled = { + {{ if .Env.XMPP_MUC_MODULES }} + "{{ join "\";\n\"" (splitList "," .Env.XMPP_MUC_MODULES) }}"; + {{ end }} + {{ if eq $AUTH_TYPE "jwt" }} + "{{ $JWT_TOKEN_AUTH_MODULE }}"; + {{ end }} + } + +Component "focus.{{ .Env.XMPP_DOMAIN }}" + component_secret = "{{ .Env.JICOFO_COMPONENT_SECRET }}" + diff --git a/docker/jitsi-meet/prosody/rootfs/defaults/prosody.cfg.lua b/docker/jitsi-meet/prosody/rootfs/defaults/prosody.cfg.lua new file mode 100644 index 0000000000..eb1038fc1d --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/defaults/prosody.cfg.lua @@ -0,0 +1,162 @@ +{{ $LOG_LEVEL := .Env.LOG_LEVEL | default "info" }} + +-- Prosody Example Configuration File +-- +-- Information on configuring Prosody can be found on our +-- website at http://prosody.im/doc/configure +-- +-- Tip: You can check that the syntax of this file is correct +-- when you have finished by running: luac -p prosody.cfg.lua +-- If there are any errors, it will let you know what and where +-- they are, otherwise it will keep quiet. +-- +-- The only thing left to do is rename this file to remove the .dist ending, and fill in the +-- blanks. Good luck, and happy Jabbering! + + +---------- Server-wide settings ---------- +-- Settings in this section apply to the whole server and are the default settings +-- for any virtual hosts + +-- This is a (by default, empty) list of accounts that are admins +-- for the server. Note that you must create the accounts separately +-- (see http://prosody.im/doc/creating_accounts for info) +-- Example: admins = { "user1@example.com", "user2@example.net" } +admins = { } + +-- Enable use of libevent for better performance under high load +-- For more information see: http://prosody.im/doc/libevent +--use_libevent = true; + +-- This is the list of modules Prosody will load on startup. +-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. +-- Documentation on modules can be found at: http://prosody.im/doc/modules +modules_enabled = { + + -- Generally required + "roster"; -- Allow users to have a roster. Recommended ;) + "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. + "tls"; -- Add support for secure TLS on c2s/s2s connections + "dialback"; -- s2s dialback support + "disco"; -- Service discovery + + -- Not essential, but recommended + "private"; -- Private XML storage (for room bookmarks, etc.) + "vcard"; -- Allow users to set vCards + + -- These are commented by default as they have a performance impact + --"privacy"; -- Support privacy lists + --"compression"; -- Stream compression (Debian: requires lua-zlib module to work) + + -- Nice to have + "version"; -- Replies to server version requests + "uptime"; -- Report how long server has been running + "time"; -- Let others know the time here on this server + "ping"; -- Replies to XMPP pings with pongs + "pep"; -- Enables users to publish their mood, activity, playing music and more + "register"; -- Allow users to register on this server using a client and change passwords + + -- Admin interfaces + "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands + --"admin_telnet"; -- Opens telnet console interface on localhost port 5582 + + -- HTTP modules + --"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" + --"http_files"; -- Serve static files from a directory over HTTP + + -- Other specific functionality + "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. + --"groups"; -- Shared roster support + --"announce"; -- Send announcement to all online users + --"welcome"; -- Welcome users who register accounts + --"watchregistrations"; -- Alert admins of registrations + --"motd"; -- Send a message to users when they log in + --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. + {{ if .Env.GLOBAL_MODULES }} + "{{ join "\";\n\"" (splitList "," .Env.GLOBAL_MODULES) }}"; + {{ end }} +}; + +https_ports = { } + +-- These modules are auto-loaded, but should you want +-- to disable them then uncomment them here: +modules_disabled = { + -- "offline"; -- Store offline messages + -- "c2s"; -- Handle client connections + -- "s2s"; -- Handle server-to-server connections +}; + +-- Disable account creation by default, for security +-- For more information see http://prosody.im/doc/creating_accounts +allow_registration = false; + +daemonize = false; + +pidfile = "/config/data/prosody.pid"; + +-- Force clients to use encrypted connections? This option will +-- prevent clients from authenticating unless they are using encryption. + +c2s_require_encryption = false + +-- Force certificate authentication for server-to-server connections? +-- This provides ideal security, but requires servers you communicate +-- with to support encryption AND present valid, trusted certificates. +-- NOTE: Your version of LuaSec must support certificate verification! +-- For more information see http://prosody.im/doc/s2s#security + +s2s_secure_auth = false + +-- Many servers don't support encryption or have invalid or self-signed +-- certificates. You can list domains here that will not be required to +-- authenticate using certificates. They will be authenticated using DNS. + +--s2s_insecure_domains = { "gmail.com" } + +-- Even if you leave s2s_secure_auth disabled, you can still require valid +-- certificates for some domains by specifying a list here. + +--s2s_secure_domains = { "jabber.org" } + +-- Select the authentication backend to use. The 'internal' providers +-- use Prosody's configured data storage to store the authentication data. +-- To allow Prosody to offer secure authentication mechanisms to clients, the +-- default provider stores passwords in plaintext. If you do not trust your +-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed +-- for information about using the hashed backend. + +authentication = "internal_plain" + +-- Select the storage backend to use. By default Prosody uses flat files +-- in its configured data directory, but it also supports more backends +-- through modules. An "sql" backend is included by default, but requires +-- additional dependencies. See http://prosody.im/doc/storage for more info. + +--storage = "sql" -- Default is "internal" (Debian: "sql" requires one of the +-- lua-dbi-sqlite3, lua-dbi-mysql or lua-dbi-postgresql packages to work) + +-- For the "sql" backend, you can uncomment *one* of the below to configure: +--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename. +--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } +--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } + +-- Logging configuration +-- For advanced logging see http://prosody.im/doc/logging +-- +-- Debian: +-- Logs info and higher to /var/log +-- Logs errors to syslog also +log = { + { levels = {min = "{{ $LOG_LEVEL }}"}, to = "console"}; +} + +{{ if .Env.GLOBAL_CONFIG }} +{{ join "\n" (splitList "\\n" .Env.GLOBAL_CONFIG) }} +{{ end }} + +component_interface = { "*" } + +data_path = "/config/data" + +Include "conf.d/*.cfg.lua" diff --git a/docker/jitsi-meet/prosody/rootfs/defaults/saslauthd.conf b/docker/jitsi-meet/prosody/rootfs/defaults/saslauthd.conf new file mode 100644 index 0000000000..ffcc211cfa --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/defaults/saslauthd.conf @@ -0,0 +1,26 @@ +{{ if eq (.Env.AUTH_TYPE | default "internal") "ldap" }} +ldap_servers: {{ .Env.LDAP_URL }} +ldap_search_base: {{ .Env.LDAP_BASE }} +{{ if .Env.LDAP_BINDDN }} +ldap_bind_dn: {{ .Env.LDAP_BINDDN }} +ldap_bind_pw: {{ .Env.LDAP_BINDPW }} +{{ end }} +ldap_filter: {{ .Env.LDAP_FILTER | default "uid=%u" }} +ldap_version: {{ .Env.LDAP_VERSION | default "3" }} +ldap_auth_method: {{ .Env.LDAP_AUTH_METHOD | default "bind" }} + {{ if .Env.LDAP_USE_TLS | default "0" | toBool }} +ldap_tls_key: /config/certs/{{ .Env.XMPP_DOMAIN }}.key +ldap_tls_cert: /config/certs/{{ .Env.XMPP_DOMAIN }}.crt + {{ if .Env.LDAP_TLS_CHECK_PEER | default "0" | toBool }} +ldap_tls_check_peer: yes +ldap_tls_cacert_file: {{ .Env.LDAP_TLS_CACERT_FILE | default "/etc/ssl/certs/ca-certificates.crt" }} +ldap_tls_cacert_dir: {{ .Env.LDAP_TLS_CACERT_DIR | default "/etc/ssl/certs" }} + {{ end }} + {{ if .Env.LDAP_TLS_CIPHERS }} +ldap_tls_ciphers: {{ .Env.LDAP_TLS_CIPHERS }} + {{ end }} + {{ end }} +{{ end }} +{{ if .Env.LDAP_START_TLS | default "0" | toBool }} +ldap_start_tls: yes +{{ end }} diff --git a/docker/jitsi-meet/prosody/rootfs/etc/cont-init.d/10-config b/docker/jitsi-meet/prosody/rootfs/etc/cont-init.d/10-config new file mode 100644 index 0000000000..701efcdd93 --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/etc/cont-init.d/10-config @@ -0,0 +1,67 @@ +#!/usr/bin/with-contenv bash + +if [[ ! -f /config/saslauthd.conf ]]; then + cp /defaults/saslauthd.conf /config/ +fi + +if [[ ! -f /etc/saslauthd.conf ]]; then + tpl /config/saslauthd.conf > /etc/saslauthd.conf + mkdir -pm777 /var/run/saslauthd + adduser prosody sasl + echo >> /etc/ldap/ldap.conf "TLS_REQCERT allow" +fi + +PROSODY_CFG="/config/prosody.cfg.lua" + +if [[ ! -d /config/data ]]; then + mkdir -pm 750 /config/data +fi + +if [[ "$(stat -c %U /config)" != "prosody" ]]; then + chown -R prosody /config +fi + +if [[ "$(stat -c %U /prosody-plugins)" != "prosody" ]]; then + chown -R prosody /prosody-plugins +fi + +if [[ "$(stat -c %U /prosody-plugins-custom)" != "prosody" ]]; then + chown -R prosody /prosody-plugins-custom +fi + +if [[ ! -f $PROSODY_CFG ]]; then + cp -r /defaults/* /config + tpl /defaults/prosody.cfg.lua > $PROSODY_CFG + tpl /defaults/conf.d/jitsi-meet.cfg.lua > /config/conf.d/jitsi-meet.cfg.lua + + prosodyctl --config $PROSODY_CFG register $JICOFO_AUTH_USER $XMPP_AUTH_DOMAIN $JICOFO_AUTH_PASSWORD + prosodyctl --config $PROSODY_CFG register $JVB_AUTH_USER $XMPP_AUTH_DOMAIN $JVB_AUTH_PASSWORD + + if [[ ! -z $JIBRI_XMPP_USER ]] && [[ ! -z $JIBRI_XMPP_PASSWORD ]]; then + prosodyctl --config $PROSODY_CFG register $JIBRI_XMPP_USER $XMPP_AUTH_DOMAIN $JIBRI_XMPP_PASSWORD + fi + + if [[ ! -z $JIBRI_RECORDER_USER ]] && [[ ! -z $JIBRI_RECORDER_PASSWORD ]]; then + prosodyctl --config $PROSODY_CFG register $JIBRI_RECORDER_USER $XMPP_RECORDER_DOMAIN $JIBRI_RECORDER_PASSWORD + fi + + if [[ ! -z $JIGASI_XMPP_USER ]] && [[ ! -z $JIGASI_XMPP_PASSWORD ]]; then + prosodyctl --config $PROSODY_CFG register $JIGASI_XMPP_USER $XMPP_AUTH_DOMAIN $JIGASI_XMPP_PASSWORD + fi +fi + +mkdir -p /config/certs + +if [[ ! -f /config/certs/$XMPP_DOMAIN.crt ]]; then + # echo for using all default values + echo | prosodyctl --config $PROSODY_CFG cert generate $XMPP_DOMAIN +fi + +if [[ ! -f /config/certs/$XMPP_AUTH_DOMAIN.crt ]]; then + # echo for using all default values + echo | prosodyctl --config $PROSODY_CFG cert generate $XMPP_AUTH_DOMAIN +fi + +# certs will be created in /config/data +mv /config/data/*.{crt,key} /config/certs/ || true +rm -f /config/data/*.cnf diff --git a/docker/jitsi-meet/prosody/rootfs/etc/sasl/xmpp.conf b/docker/jitsi-meet/prosody/rootfs/etc/sasl/xmpp.conf new file mode 100644 index 0000000000..c91a0c7ca5 --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/etc/sasl/xmpp.conf @@ -0,0 +1,2 @@ +pwcheck_method: saslauthd +mech_list: PLAIN diff --git a/docker/jitsi-meet/prosody/rootfs/etc/services.d/10-saslauthd/run b/docker/jitsi-meet/prosody/rootfs/etc/services.d/10-saslauthd/run new file mode 100644 index 0000000000..75199bb59c --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/etc/services.d/10-saslauthd/run @@ -0,0 +1,2 @@ +#!/usr/bin/with-contenv bash +exec s6-setuidgid root saslauthd -a ldap -O /etc/saslauthd.conf -c -m /var/run/saslauthd -n 5 -d diff --git a/docker/jitsi-meet/prosody/rootfs/etc/services.d/prosody/run b/docker/jitsi-meet/prosody/rootfs/etc/services.d/prosody/run new file mode 100644 index 0000000000..e1e3ab65d4 --- /dev/null +++ b/docker/jitsi-meet/prosody/rootfs/etc/services.d/prosody/run @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv bash +exec s6-setuidgid prosody prosody --config /config/prosody.cfg.lua + diff --git a/docker/jitsi-meet/web/rootfs/defaults/config.js b/docker/jitsi-meet/web/rootfs/defaults/config.js new file mode 100644 index 0000000000..17f0ad545d --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/config.js @@ -0,0 +1,481 @@ +/* eslint-disable no-unused-vars, no-var */ + +var config = { + // Configuration + // + + // Alternative location for the configuration. + // configLocation: './config.json', + + // Custom function which given the URL path should return a room name. + // getroomnode: function (path) { return 'someprefixpossiblybasedonpath'; }, + + + // Connection + // + + hosts: { + // XMPP domain. + domain: 'jitsi-meet.example.com', + + // When using authentication, domain for guest users. + // anonymousdomain: 'guest.example.com', + + // Domain for authenticated users. Defaults to . + // authdomain: 'jitsi-meet.example.com', + + // Jirecon recording component domain. + // jirecon: 'jirecon.jitsi-meet.example.com', + + // Call control component (Jigasi). + // call_control: 'callcontrol.jitsi-meet.example.com', + + // Focus component domain. Defaults to focus.. + // focus: 'focus.jitsi-meet.example.com', + + // XMPP MUC domain. FIXME: use XEP-0030 to discover it. + muc: 'conference.jitsi-meet.example.com' + }, + + // BOSH URL. FIXME: use XEP-0156 to discover it. + bosh: '//jitsi-meet.example.com/http-bind', + + // The name of client node advertised in XEP-0115 'c' stanza + clientNode: 'http://jitsi.org/jitsimeet', + + // The real JID of focus participant - can be overridden here + // focusUserJid: 'focus@auth.jitsi-meet.example.com', + + + // Testing / experimental features. + // + + testing: { + // Enables experimental simulcast support on Firefox. + enableFirefoxSimulcast: false, + + // P2P test mode disables automatic switching to P2P when there are 2 + // participants in the conference. + p2pTestMode: false + + // Enables the test specific features consumed by jitsi-meet-torture + // testMode: false + }, + + // Disables ICE/UDP by filtering out local and remote UDP candidates in + // signalling. + // webrtcIceUdpDisable: false, + + // Disables ICE/TCP by filtering out local and remote TCP candidates in + // signalling. + // webrtcIceTcpDisable: false, + + + // Media + // + + // Audio + + // Disable measuring of audio levels. + // disableAudioLevels: false, + + // Start the conference in audio only mode (no video is being received nor + // sent). + // startAudioOnly: false, + + // Every participant after the Nth will start audio muted. + // startAudioMuted: 10, + + // Start calls with audio muted. Unlike the option above, this one is only + // applied locally. FIXME: having these 2 options is confusing. + // startWithAudioMuted: false, + + // Enabling it (with #params) will disable local audio output of remote + // participants and to enable it back a reload is needed. + // startSilent: false + + // Video + + // Sets the preferred resolution (height) for local video. Defaults to 720. + // resolution: 720, + + // w3c spec-compliant video constraints to use for video capture. Currently + // used by browsers that return true from lib-jitsi-meet's + // util#browser#usesNewGumFlow. The constraints are independency from + // this config's resolution value. Defaults to requesting an ideal aspect + // ratio of 16:9 with an ideal resolution of 720. + // constraints: { + // video: { + // aspectRatio: 16 / 9, + // height: { + // ideal: 720, + // max: 720, + // min: 240 + // } + // } + // }, + + // Enable / disable simulcast support. + // disableSimulcast: false, + + // Enable / disable layer suspension. If enabled, endpoints whose HD + // layers are not in use will be suspended (no longer sent) until they + // are requested again. + // enableLayerSuspension: false, + + // Suspend sending video if bandwidth estimation is too low. This may cause + // problems with audio playback. Disabled until these are fixed. + disableSuspendVideo: true, + + // Every participant after the Nth will start video muted. + // startVideoMuted: 10, + + // Start calls with video muted. Unlike the option above, this one is only + // applied locally. FIXME: having these 2 options is confusing. + // startWithVideoMuted: false, + + // If set to true, prefer to use the H.264 video codec (if supported). + // Note that it's not recommended to do this because simulcast is not + // supported when using H.264. For 1-to-1 calls this setting is enabled by + // default and can be toggled in the p2p section. + // preferH264: true, + + // If set to true, disable H.264 video codec by stripping it out of the + // SDP. + // disableH264: false, + + // Desktop sharing + + // The ID of the jidesha extension for Chrome. + desktopSharingChromeExtId: null, + + // Whether desktop sharing should be disabled on Chrome. + // desktopSharingChromeDisabled: false, + + // The media sources to use when using screen sharing with the Chrome + // extension. + desktopSharingChromeSources: [ 'screen', 'window', 'tab' ], + + // Required version of Chrome extension + desktopSharingChromeMinExtVersion: '0.1', + + // Whether desktop sharing should be disabled on Firefox. + // desktopSharingFirefoxDisabled: false, + + // Optional desktop sharing frame rate options. Default value: min:5, max:5. + // desktopSharingFrameRate: { + // min: 5, + // max: 5 + // }, + + // Try to start calls with screen-sharing instead of camera video. + // startScreenSharing: false, + + // Recording + + // Whether to enable file recording or not. + // fileRecordingsEnabled: false, + // Enable the dropbox integration. + // dropbox: { + // appKey: '' // Specify your app key here. + // // A URL to redirect the user to, after authenticating + // // by default uses: + // // 'https://jitsi-meet.example.com/static/oauth.html' + // redirectURI: + // 'https://jitsi-meet.example.com/subfolder/static/oauth.html' + // }, + // When integrations like dropbox are enabled only that will be shown, + // by enabling fileRecordingsServiceEnabled, we show both the integrations + // and the generic recording service (its configuration and storage type + // depends on jibri configuration) + // fileRecordingsServiceEnabled: false, + // Whether to show the possibility to share file recording with other people + // (e.g. meeting participants), based on the actual implementation + // on the backend. + // fileRecordingsServiceSharingEnabled: false, + + // Whether to enable live streaming or not. + // liveStreamingEnabled: false, + + // Transcription (in interface_config, + // subtitles and buttons can be configured) + // transcribingEnabled: false, + + // Misc + + // Default value for the channel "last N" attribute. -1 for unlimited. + channelLastN: -1, + + // Disables or enables RTX (RFC 4588) (defaults to false). + // disableRtx: false, + + // Disables or enables TCC (the default is in Jicofo and set to true) + // (draft-holmer-rmcat-transport-wide-cc-extensions-01). This setting + // affects congestion control, it practically enables send-side bandwidth + // estimations. + // enableTcc: true, + + // Disables or enables REMB (the default is in Jicofo and set to false) + // (draft-alvestrand-rmcat-remb-03). This setting affects congestion + // control, it practically enables recv-side bandwidth estimations. When + // both TCC and REMB are enabled, TCC takes precedence. When both are + // disabled, then bandwidth estimations are disabled. + // enableRemb: false, + + // Defines the minimum number of participants to start a call (the default + // is set in Jicofo and set to 2). + // minParticipants: 2, + + // Use XEP-0215 to fetch STUN and TURN servers. + // useStunTurn: true, + + // Enable IPv6 support. + // useIPv6: true, + + // Enables / disables a data communication channel with the Videobridge. + // Values can be 'datachannel', 'websocket', true (treat it as + // 'datachannel'), undefined (treat it as 'datachannel') and false (don't + // open any channel). + // openBridgeChannel: true, + + + // UI + // + + // Use display name as XMPP nickname. + // useNicks: false, + + // Require users to always specify a display name. + // requireDisplayName: true, + + // Whether to use a welcome page or not. In case it's false a random room + // will be joined when no room is specified. + enableWelcomePage: true, + + // Enabling the close page will ignore the welcome page redirection when + // a call is hangup. + // enableClosePage: false, + + // Disable hiding of remote thumbnails when in a 1-on-1 conference call. + // disable1On1Mode: false, + + // Default language for the user interface. + // defaultLanguage: 'en', + + // If true all users without a token will be considered guests and all users + // with token will be considered non-guests. Only guests will be allowed to + // edit their profile. + enableUserRolesBasedOnToken: false, + + // Whether or not some features are checked based on token. + // enableFeaturesBasedOnToken: false, + + // Enable lock room for all moderators, even when userRolesBasedOnToken is enabled and participants are guests. + // lockRoomGuestEnabled: false, + + // When enabled the password used for locking a room is restricted to up to the number of digits specified + // roomPasswordNumberOfDigits: 10, + // default: roomPasswordNumberOfDigits: false, + + // Message to show the users. Example: 'The service will be down for + // maintenance at 01:00 AM GMT, + // noticeMessage: '', + + // Enables calendar integration, depends on googleApiApplicationClientID + // and microsoftApiApplicationClientID + // enableCalendarIntegration: false, + + // Stats + // + + // Whether to enable stats collection or not in the TraceablePeerConnection. + // This can be useful for debugging purposes (post-processing/analysis of + // the webrtc stats) as it is done in the jitsi-meet-torture bandwidth + // estimation tests. + // gatherStats: false, + + // To enable sending statistics to callstats.io you must provide the + // Application ID and Secret. + // callStatsID: '', + // callStatsSecret: '', + + // enables callstatsUsername to be reported as statsId and used + // by callstats as repoted remote id + // enableStatsID: false + + // enables sending participants display name to callstats + // enableDisplayNameInStats: false + + + // Privacy + // + + // If third party requests are disabled, no other server will be contacted. + // This means avatars will be locally generated and callstats integration + // will not function. + // disableThirdPartyRequests: false, + + + // Peer-To-Peer mode: used (if enabled) when there are just 2 participants. + // + + p2p: { + // Enables peer to peer mode. When enabled the system will try to + // establish a direct connection when there are exactly 2 participants + // in the room. If that succeeds the conference will stop sending data + // through the JVB and use the peer to peer connection instead. When a + // 3rd participant joins the conference will be moved back to the JVB + // connection. + enabled: true, + + // Use XEP-0215 to fetch STUN and TURN servers. + // useStunTurn: true, + + // The STUN servers that will be used in the peer to peer connections + stunServers: [ + { urls: 'stun:stun.l.google.com:19302' }, + { urls: 'stun:stun1.l.google.com:19302' }, + { urls: 'stun:stun2.l.google.com:19302' } + ], + + // Sets the ICE transport policy for the p2p connection. At the time + // of this writing the list of possible values are 'all' and 'relay', + // but that is subject to change in the future. The enum is defined in + // the WebRTC standard: + // https://www.w3.org/TR/webrtc/#rtcicetransportpolicy-enum. + // If not set, the effective value is 'all'. + // iceTransportPolicy: 'all', + + // If set to true, it will prefer to use H.264 for P2P calls (if H.264 + // is supported). + preferH264: true + + // If set to true, disable H.264 video codec by stripping it out of the + // SDP. + // disableH264: false, + + // How long we're going to wait, before going back to P2P after the 3rd + // participant has left the conference (to filter out page reload). + // backToP2PDelay: 5 + }, + + analytics: { + // The Google Analytics Tracking ID: + // googleAnalyticsTrackingId: 'your-tracking-id-UA-123456-1' + + // The Amplitude APP Key: + // amplitudeAPPKey: '' + + // Array of script URLs to load as lib-jitsi-meet "analytics handlers". + // scriptURLs: [ + // "libs/analytics-ga.min.js", // google-analytics + // "https://example.com/my-custom-analytics.js" + // ], + }, + + // Information about the jitsi-meet instance we are connecting to, including + // the user region as seen by the server. + deploymentInfo: { + // shard: "shard1", + // region: "europe", + // userRegion: "asia" + } + + // Local Recording + // + + // localRecording: { + // Enables local recording. + // Additionally, 'localrecording' (all lowercase) needs to be added to + // TOOLBAR_BUTTONS in interface_config.js for the Local Recording + // button to show up on the toolbar. + // + // enabled: true, + // + + // The recording format, can be one of 'ogg', 'flac' or 'wav'. + // format: 'flac' + // + + // } + + // Options related to end-to-end (participant to participant) ping. + // e2eping: { + // // The interval in milliseconds at which pings will be sent. + // // Defaults to 10000, set to <= 0 to disable. + // pingInterval: 10000, + // + // // The interval in milliseconds at which analytics events + // // with the measured RTT will be sent. Defaults to 60000, set + // // to <= 0 to disable. + // analyticsInterval: 60000, + // } + + // If set, will attempt to use the provided video input device label when + // triggering a screenshare, instead of proceeding through the normal flow + // for obtaining a desktop stream. + // NOTE: This option is experimental and is currently intended for internal + // use only. + // _desktopSharingSourceDevice: 'sample-id-or-label' + + // If true, any checks to handoff to another application will be prevented + // and instead the app will continue to display in the current browser. + // disableDeepLinking: false + + // A property to disable the right click context menu for localVideo + // the menu has option to flip the locally seen video for local presentations + // disableLocalVideoFlip: false + + // List of undocumented settings used in jitsi-meet + /** + _immediateReloadThreshold + autoRecord + autoRecordToken + debug + debugAudioLevels + deploymentInfo + dialInConfCodeUrl + dialInNumbersUrl + dialOutAuthUrl + dialOutCodesUrl + disableRemoteControl + displayJids + etherpad_base + externalConnectUrl + firefox_fake_device + googleApiApplicationClientID + iAmRecorder + iAmSipGateway + microsoftApiApplicationClientID + peopleSearchQueryTypes + peopleSearchUrl + requireDisplayName + tokenAuthUrl + */ + + // List of undocumented settings used in lib-jitsi-meet + /** + _peerConnStatusOutOfLastNTimeout + _peerConnStatusRtcMuteTimeout + abTesting + avgRtpStatsN + callStatsConfIDNamespace + callStatsCustomScriptUrl + desktopSharingSources + disableAEC + disableAGC + disableAP + disableHPF + disableNS + enableLipSync + enableTalkWhileMuted + forceJVB121Ratio + hiddenDomain + ignoreStartMuted + nick + startBitrate + */ + +}; + +/* eslint-enable no-unused-vars, no-var */ diff --git a/docker/jitsi-meet/web/rootfs/defaults/default b/docker/jitsi-meet/web/rootfs/defaults/default new file mode 100644 index 0000000000..d5775321d8 --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/default @@ -0,0 +1,18 @@ +server { + listen 80 default_server; + + {{ if .Env.ENABLE_HTTP_REDIRECT | default "0" | toBool }} + return 301 https://$host$request_uri; + {{ else }} + include /config/nginx/meet.conf; + {{ end }} +} + +{{ if not (.Env.DISABLE_HTTPS | default "0" | toBool) }} +server { + listen 443 ssl; + + include /config/nginx/ssl.conf; + include /config/nginx/meet.conf; +} +{{ end }} diff --git a/docker/jitsi-meet/web/rootfs/defaults/interface_config.js b/docker/jitsi-meet/web/rootfs/defaults/interface_config.js new file mode 100644 index 0000000000..dcea2a7e95 --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/interface_config.js @@ -0,0 +1,226 @@ +/* eslint-disable no-unused-vars, no-var, max-len */ + +var interfaceConfig = { + // TO FIX: this needs to be handled from SASS variables. There are some + // methods allowing to use variables both in css and js. + DEFAULT_BACKGROUND: '#474747', + + /** + * Whether or not the blurred video background for large video should be + * displayed on browsers that can support it. + */ + DISABLE_VIDEO_BACKGROUND: false, + + INITIAL_TOOLBAR_TIMEOUT: 20000, + TOOLBAR_TIMEOUT: 4000, + TOOLBAR_ALWAYS_VISIBLE: false, + DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster', + DEFAULT_LOCAL_DISPLAY_NAME: 'me', + SHOW_JITSI_WATERMARK: true, + JITSI_WATERMARK_LINK: 'https://jitsi.org', + + // if watermark is disabled by default, it can be shown only for guests + SHOW_WATERMARK_FOR_GUESTS: true, + SHOW_BRAND_WATERMARK: false, + BRAND_WATERMARK_LINK: '', + SHOW_POWERED_BY: false, + SHOW_DEEP_LINKING_IMAGE: false, + GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true, + DISPLAY_WELCOME_PAGE_CONTENT: true, + APP_NAME: 'Jitsi Meet', + NATIVE_APP_NAME: 'Jitsi Meet', + PROVIDER_NAME: 'Jitsi', + LANG_DETECTION: false, // Allow i18n to detect the system language + INVITATION_POWERED_BY: true, + + /** + * If we should show authentication block in profile + */ + AUTHENTICATION_ENABLE: true, + + /** + * The name of the toolbar buttons to display in the toolbar. If present, + * the button will display. Exceptions are "livestreaming" and "recording" + * which also require being a moderator and some values in config.js to be + * enabled. Also, the "profile" button will not display for user's with a + * jwt. + */ + TOOLBAR_BUTTONS: [ + 'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen', + 'fodeviceselection', 'hangup', 'profile', 'info', 'chat', 'recording', + 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand', + 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts', + 'tileview', 'videobackgroundblur' + ], + + SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ], + + // Determines how the video would fit the screen. 'both' would fit the whole + // screen, 'height' would fit the original video height to the height of the + // screen, 'width' would fit the original video width to the width of the + // screen respecting ratio. + VIDEO_LAYOUT_FIT: 'both', + + /** + * Whether to only show the filmstrip (and hide the toolbar). + */ + filmStripOnly: false, + + /** + * Whether to show thumbnails in filmstrip as a column instead of as a row. + */ + VERTICAL_FILMSTRIP: true, + + // A html text to be shown to guests on the close page, false disables it + CLOSE_PAGE_GUEST_HINT: false, + RANDOM_AVATAR_URL_PREFIX: false, + RANDOM_AVATAR_URL_SUFFIX: false, + FILM_STRIP_MAX_HEIGHT: 120, + + // Enables feedback star animation. + ENABLE_FEEDBACK_ANIMATION: false, + DISABLE_FOCUS_INDICATOR: false, + DISABLE_DOMINANT_SPEAKER_INDICATOR: false, + + /** + * Whether the speech to text transcription subtitles panel is disabled. + * If {@code undefined}, defaults to {@code false}. + * + * @type {boolean} + */ + DISABLE_TRANSCRIPTION_SUBTITLES: false, + + /** + * Whether the ringing sound in the call/ring overlay is disabled. If + * {@code undefined}, defaults to {@code false}. + * + * @type {boolean} + */ + DISABLE_RINGING: false, + AUDIO_LEVEL_PRIMARY_COLOR: 'rgba(255,255,255,0.4)', + AUDIO_LEVEL_SECONDARY_COLOR: 'rgba(255,255,255,0.2)', + POLICY_LOGO: null, + LOCAL_THUMBNAIL_RATIO: 16 / 9, // 16:9 + REMOTE_THUMBNAIL_RATIO: 1, // 1:1 + // Documentation reference for the live streaming feature. + LIVE_STREAMING_HELP_LINK: 'https://jitsi.org/live', + + /** + * Whether the mobile app Jitsi Meet is to be promoted to participants + * attempting to join a conference in a mobile Web browser. If + * {@code undefined}, defaults to {@code true}. + * + * @type {boolean} + */ + MOBILE_APP_PROMO: true, + + /** + * Maximum coeficient of the ratio of the large video to the visible area + * after the large video is scaled to fit the window. + * + * @type {number} + */ + MAXIMUM_ZOOMING_COEFFICIENT: 1.3, + + /* + * If indicated some of the error dialogs may point to the support URL for + * help. + */ + SUPPORT_URL: 'https://github.com/jitsi/jitsi-meet/issues/new', + + /** + * Whether the connection indicator icon should hide itself based on + * connection strength. If true, the connection indicator will remain + * displayed while the participant has a weak connection and will hide + * itself after the CONNECTION_INDICATOR_HIDE_TIMEOUT when the connection is + * strong. + * + * @type {boolean} + */ + CONNECTION_INDICATOR_AUTO_HIDE_ENABLED: true, + + /** + * How long the connection indicator should remain displayed before hiding. + * Used in conjunction with CONNECTION_INDICATOR_AUTOHIDE_ENABLED. + * + * @type {number} + */ + CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT: 5000, + + /** + * If true, hides the connection indicators completely. + * + * @type {boolean} + */ + CONNECTION_INDICATOR_DISABLED: false, + + /** + * If true, hides the video quality label indicating the resolution status + * of the current large video. + * + * @type {boolean} + */ + VIDEO_QUALITY_LABEL_DISABLED: false, + + /** + * If true, will display recent list + * + * @type {boolean} + */ + RECENT_LIST_ENABLED: true, + + // Names of browsers which should show a warning stating the current browser + // has a suboptimal experience. Browsers which are not listed as optimal or + // unsupported are considered suboptimal. Valid values are: + // chrome, chromium, edge, electron, firefox, nwjs, opera, safari + OPTIMAL_BROWSERS: [ 'chrome', 'chromium', 'firefox', 'nwjs', 'electron' ], + + // Browsers, in addition to those which do not fully support WebRTC, that + // are not supported and should show the unsupported browser page. + UNSUPPORTED_BROWSERS: [], + + /** + * A UX mode where the last screen share participant is automatically + * pinned. Valid values are the string "remote-only" so remote participants + * get pinned but not local, otherwise any truthy value for all participants, + * and any falsy value to disable the feature. + * + * Note: this mode is experimental and subject to breakage. + */ + AUTO_PIN_LATEST_SCREEN_SHARE: 'remote-only' + + /** + * How many columns the tile view can expand to. The respected range is + * between 1 and 5. + */ + // TILE_VIEW_MAX_COLUMNS: 5, + + /** + * Specify custom URL for downloading android mobile app. + */ + // MOBILE_DOWNLOAD_LINK_ANDROID: 'https://play.google.com/store/apps/details?id=org.jitsi.meet', + + /** + * Specify URL for downloading ios mobile app. + */ + // MOBILE_DOWNLOAD_LINK_IOS: 'https://itunes.apple.com/us/app/jitsi-meet/id1165103905', + + /** + * Specify mobile app scheme for opening the app from the mobile browser. + */ + // APP_SCHEME: 'org.jitsi.meet', + + /** + * Specify the Android app package name. + */ + // ANDROID_APP_PACKAGE: 'org.jitsi.meet', + + /** + * Override the behavior of some notifications to remain displayed until + * explicitly dismissed through a user action. The value is how long, in + * milliseconds, those notifications should remain displayed. + */ + // ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT: 15000, +}; + +/* eslint-enable no-unused-vars, no-var, max-len */ diff --git a/docker/jitsi-meet/web/rootfs/defaults/letsencrypt-renew b/docker/jitsi-meet/web/rootfs/defaults/letsencrypt-renew new file mode 100755 index 0000000000..348cf4dd5f --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/letsencrypt-renew @@ -0,0 +1,10 @@ +#!/bin/bash + +# stop nginx +s6-svc -d /var/run/s6/services/nginx + +# renew cert +certbot -n renew >> /config/le-renew.log + +# start nginx +s6-svc -u /var/run/s6/services/nginx diff --git a/docker/jitsi-meet/web/rootfs/defaults/meet.conf b/docker/jitsi-meet/web/rootfs/defaults/meet.conf new file mode 100644 index 0000000000..c8331ed9e4 --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/meet.conf @@ -0,0 +1,50 @@ +server_name _; + +client_max_body_size 0; + +root /usr/share/jitsi-meet; +index index.html +error_page 404 /static/404.html; + +location ~ ^/([a-zA-Z0-9=\?]+)$ { + rewrite ^/(.*)$ / break; +} + +location /config.js { + alias /config/config.js; +} + +location /interface_config.js { + alias /config/interface_config.js; +} + +location /external_api.js { + alias /usr/share/jitsi-meet/libs/external_api.min.js; +} + +location / { + ssi on; +} + +# BOSH +location /http-bind { + proxy_pass {{ .Env.XMPP_BOSH_URL_BASE }}/http-bind; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host {{ .Env.XMPP_DOMAIN }}; +} + +{{ if .Env.ETHERPAD_URL_BASE }} +# Etherpad-lite +location /etherpad/ { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + + proxy_pass {{ .Env.ETHERPAD_URL_BASE }}/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_buffering off; + proxy_set_header Host {{ .Env.XMPP_DOMAIN }}; +} +{{ end }} diff --git a/docker/jitsi-meet/web/rootfs/defaults/nginx.conf b/docker/jitsi-meet/web/rootfs/defaults/nginx.conf new file mode 100644 index 0000000000..fa1a78e325 --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/nginx.conf @@ -0,0 +1,60 @@ +user www-data; +worker_processes 4; +pid /run/nginx.pid; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + client_max_body_size 0; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # Logging Settings + ## + + access_log /dev/stdout; + error_log /dev/stderr; + + ## + # Gzip Settings + ## + + 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/x-javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # Virtual Host Configs + ## + include /config/nginx/site-confs/*; +} + + +daemon off; diff --git a/docker/jitsi-meet/web/rootfs/defaults/ssl.conf b/docker/jitsi-meet/web/rootfs/defaults/ssl.conf new file mode 100644 index 0000000000..60e3c6c375 --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/defaults/ssl.conf @@ -0,0 +1,27 @@ +# session settings +ssl_session_timeout 1d; +ssl_session_cache shared:SSL:50m; +ssl_session_tickets off; + +# Diffie-Hellman parameter for DHE cipher suites +ssl_dhparam /config/nginx/dhparams.pem; + +# ssl certs +{{ if .Env.ENABLE_LETSENCRYPT | default "0" | toBool }} +ssl_certificate /etc/letsencrypt/live/{{ .Env.LETSENCRYPT_DOMAIN }}/fullchain.pem; +ssl_certificate_key /etc/letsencrypt/live/{{ .Env.LETSENCRYPT_DOMAIN }}/privkey.pem; +{{ else }} +ssl_certificate /config/keys/cert.crt; +ssl_certificate_key /config/keys/cert.key; +{{ end }} + +# protocols +ssl_protocols TLSv1.2; +ssl_prefer_server_ciphers on; +ssl_ecdh_curve secp384r1; +ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDH+CHACHA20:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK; + +# headers +add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; diff --git a/docker/jitsi-meet/web/rootfs/etc/cont-init.d/10-config b/docker/jitsi-meet/web/rootfs/etc/cont-init.d/10-config new file mode 100644 index 0000000000..075ad4b16f --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/etc/cont-init.d/10-config @@ -0,0 +1,118 @@ +#!/usr/bin/with-contenv bash + +# make our folders +mkdir -p \ + /config/{nginx/site-confs,keys} \ + /run \ + /var/lib/nginx/tmp/client_body \ + /var/tmp/nginx + +# generate keys (maybe) +if [[ $DISABLE_HTTPS -ne 1 ]]; then + if [[ $ENABLE_LETSENCRYPT -eq 1 ]]; then + if [[ ! -f /etc/letsencrypt/live/$LETSENCRYPT_DOMAIN/fullchain.pem ]]; then + certbot certonly \ + --noninteractive \ + --standalone \ + --preferred-challenges http \ + -d $LETSENCRYPT_DOMAIN \ + --agree-tos \ + --email $LETSENCRYPT_EMAIL + fi + + # remove default certbot renewal + if [[ -f /etc/cron.d/certbot ]]; then + rm /etc/cron.d/certbot + fi + + # setup certbot renewal script + if [[ ! -f /etc/cron.daily/letencrypt-renew ]]; then + cp /defaults/letsencrypt-renew /etc/cron.daily/ + fi + else + # use self-signed certs + if [[ -f /config/keys/cert.key && -f /config/keys/cert.crt ]]; then + echo "using keys found in /config/keys" + else + echo "generating self-signed keys in /config/keys, you can replace these with your own keys if required" + SUBJECT="/C=US/ST=TX/L=Austin/O=jitsi.org/OU=Jitsi Server/CN=*" + openssl req -new -x509 -days 3650 -nodes -out /config/keys/cert.crt -keyout /config/keys/cert.key -subj "$SUBJECT" + fi + fi + if [[ ! -f /config/nginx/dhparams.pem ]]; then + openssl dhparam -out /config/nginx/dhparams.pem 2048 + fi +fi + +# copy config files +if [[ ! -f /config/nginx/nginx.conf ]]; then + cp /defaults/nginx.conf /config/nginx/nginx.conf +fi + +if [[ ! -f /config/nginx/meet.conf ]]; then + tpl /defaults/meet.conf > /config/nginx/meet.conf +fi + +if [[ ! -f /config/nginx/ssl.conf ]]; then + tpl /defaults/ssl.conf > /config/nginx/ssl.conf +fi + +if [[ ! -f /config/nginx/site-confs/default ]]; then + tpl /defaults/default > /config/nginx/site-confs/default +fi + +if [[ ! -f /config/config.js ]]; then + cp /defaults/config.js /config/config.js + sed -i \ + -e "s#jitsi-meet.example.com#$XMPP_DOMAIN#g" \ + -e "s#bosh:.*#bosh: '/http-bind',#" \ + -e "s#muc:.*#muc: '${XMPP_MUC_DOMAIN}',#" \ + -e "s#// focusUserJid:.*#focusUserJid: '${JICOFO_AUTH_USER}@${XMPP_AUTH_DOMAIN}',#" \ + /config/config.js + + if [[ $ENABLE_RECORDING -eq 1 || x$ENABLE_RECORDING == xtrue ]]; then + sed -i \ + -e "/\/\/ Recording.*/a hiddenDomain: '$XMPP_RECORDER_DOMAIN'," \ + -e "s#// fileRecordingsEnabled:.*#fileRecordingsEnabled: true,#" \ + -e "s#// liveStreamingEnabled:.*#liveStreamingEnabled: true,#" \ + /config/config.js + fi + + if [[ $ENABLE_AUTH -eq 1 ]]; then + if [[ $ENABLE_GUESTS -eq 1 ]]; then + sed -i \ + -e "s#// anonymousdomain:.*#anonymousdomain: '${XMPP_GUEST_DOMAIN}',#" \ + /config/config.js + fi + + sed -i \ + -e "s#// authdomain:.*#authdomain: '${XMPP_DOMAIN}',#" \ + /config/config.js + fi + + if [[ ! -z "${ETHERPAD_URL_BASE}" && -z "$(grep -om1 'etherpad_base:' /config/config.js)" ]]; then + sed -i \ + -e "/enableWelcomePage/a\ etherpad_base: '/etherpad/p/'," \ + /config/config.js + fi + + if [[ $ENABLE_TRANSCRIPTIONS -eq 1 || "$ENABLE_TRANSCRIPTIONS" == "true" ]]; then + sed -i \ + -e "s#// transcribingEnabled:.*#transcribingEnabled: true,#" \ + /config/config.js + fi +fi + +if [[ ! -f /config/interface_config.js ]]; then + cp /defaults/interface_config.js /config/interface_config.js + + # It will remove parameter 'closedcaptions' from TOOLBAR_BUTTONS if ENABLE_TRANSCRIPTIONS is false, + # because it enabled by default, but not supported out of the box. + if [[ $ENABLE_TRANSCRIPTIONS -ne 1 || "$ENABLE_TRANSCRIPTIONS" != "true" ]]; then + sed -i \ + -e "s#'closedcaptions', ##" \ + /config/interface_config.js + fi + +fi + diff --git a/docker/jitsi-meet/web/rootfs/etc/services.d/cron/run b/docker/jitsi-meet/web/rootfs/etc/services.d/cron/run new file mode 100755 index 0000000000..636376b98e --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/etc/services.d/cron/run @@ -0,0 +1,7 @@ +#!/usr/bin/with-contenv bash + +if [[ $DISABLE_HTTPS -ne 1 ]]; then + if [[ $ENABLE_LETSENCRYPT -eq 1 ]]; then + exec cron -f + fi +fi diff --git a/docker/jitsi-meet/web/rootfs/etc/services.d/nginx/run b/docker/jitsi-meet/web/rootfs/etc/services.d/nginx/run new file mode 100644 index 0000000000..884aeb9a77 --- /dev/null +++ b/docker/jitsi-meet/web/rootfs/etc/services.d/nginx/run @@ -0,0 +1,3 @@ +#!/usr/bin/with-contenv bash + +exec nginx -c /config/nginx/nginx.conf