diff --git a/.env.sample b/.env.sample
index 31d6c9a..1037f0c 100644
--- a/.env.sample
+++ b/.env.sample
@@ -16,6 +16,7 @@ SECRET_SHARED_SECRET_VERSION=v1
SECRET_RAILS_SECRET_VERSION=v1
SECRET_TURN_SECRET_VERSION=v1
SECRET_FSESL_PASSWORD_VERSION=v1
+SECRET_HASURA_ADMIN_SECRET_VERSION=v1
ETHERPAD_API_KEY_VERSION=v1
ENTRYPOINT_GREENLIGHT_VERSION=v1
@@ -25,12 +26,20 @@ BBBHTML5_CONF_VERSION=v1
ENTRYPOINT_APPSAKKA_VERSION=v1
ENTRYPOINT_FSESLAKKA_VERSION=v1
ENTRYPOINT_WEBRTCSFU_VERSION=v1
-MONGOD_CONF_VERSION=v1
-INIT_REPLICA_VERSION=v1
+ENTRYPOINT_GRAPHQLSERVER_VERSION=v1
+INITDB_SH_VERSION=v1
ENTRYPOINT_BBBPADS_VERSION=v1
ENTRYPOINT_ETHERPAD_VERSION=v1
ENTRYPOINT_FREESWITCH_VERSION=v1
ENTRYPOINT_BBBWEB_VERSION=v1
+WS_CONF_VERSION=v1
+WN_CONF_VERSION=v1
+WSN_CONF_VERSION=v1
+NGINX_CONF_VERSION=v1
+BRF_CONF_VERSION=v1
+BHDN_CONF_VERSION=v1
+BEG_CONF_VERSION=v1
+AA_CONF_VERSION=v1
# ====================================
# ADDITIONS to BigBlueButton
diff --git a/compose-original.yml b/compose-original.yml.old
similarity index 99%
rename from compose-original.yml
rename to compose-original.yml.old
index 9dbf617..0be0804 100644
--- a/compose-original.yml
+++ b/compose-original.yml.old
@@ -431,6 +431,7 @@ services:
extra_hosts:
- "redis:10.7.7.5"
+ # HAPROXY NOT NECESSARY FOR CO-OP CLOUD
haproxy:
build: mod/haproxy
image: alangecker/bbb-haproxy:3.0.9
diff --git a/compose.yml b/compose.yml
index 216f8a2..92c42bf 100644
--- a/compose.yml
+++ b/compose.yml
@@ -3,7 +3,7 @@ version: '3.8'
services:
bbb-web:
- image: alangecker/bbb-docker-web:v3.0.4
+ image: alangecker/bbb-docker-web:v3.0.19
depends_on:
- redis
- etherpad
@@ -24,6 +24,7 @@ services:
# SHARED_SECRET is set via entrypoint.bbb-web.sh
# TURN_SECRET is set via entrypoint.bbb-web.sh
ENABLE_LEARNING_DASHBOARD: ${ENABLE_LEARNING_DASHBOARD:-true}
+ COLLABORA_URL: ${COLLABORA_URL:-https://collabora:9980/cool}
# NUMBER_OF_BACKEND_NODEJS_PROCESSES: 2 # look for containers?
configs:
- source: entrypoint_bbbweb
@@ -37,13 +38,11 @@ services:
- bigbluebutton:/var/bigbluebutton
- vol-freeswitch:/var/freeswitch/meetings
networks:
- bbb-net:
- aliases:
- - bbb-web
+ - internal
# freeswitch (audio input streaming and telco dial-in support)
freeswitch:
- image: alangecker/bbb-docker-freeswitch:v1.10.12-v3.0.4
+ image: alangecker/bbb-docker-freeswitch:v1.10.12-v3.0.19
cap_add:
- IPC_LOCK
- NET_ADMIN
@@ -73,9 +72,7 @@ services:
- vol-freeswitch:/var/freeswitch/meetings
# network_mode: host
networks:
- bbb-net:
- aliases:
- - freeswitch
+ - internal
logging:
# reduce logs to a minimum, so `docker compose logs -f` still works
driver: "local"
@@ -86,16 +83,42 @@ services:
# nginx (webserver gateway for a bunch of things)
nginx:
- image: alangecker/bbb-docker-nginx:v3.0.4-v5.3.1-1.25
+ image: alangecker/bbb-docker-nginx:v3.0.19-v5.4.3-1.29
volumes:
- bigbluebutton:/var/bigbluebutton
- ${DEFAULT_PRESENTATION:-/dev/null}:/www/default.pdf
tmpfs:
- /tmp
+ configs:
+ - source: nginx_conf
+ target: /etc/nginx/nginx.conf
+ mode: 0555
+ - source: beg_conf
+ target: /etc/nginx/bbb/bbb-exporter.nginx
+ mode: 0555
+ - source: bhdn_conf
+ target: /etc/nginx/bbb/bbb-html5.dev.nginx
+ mode: 0555
+ - source: wn_conf
+ target: /etc/nginx/bbb/webhooks.nginx
+ mode: 0555
+ - source: wsn_conf
+ target: /etc/nginx/bbb/webrtc-sfu.nginx
+ mode: 0555
networks:
- bbb-net:
- aliases:
- - nginx
+ - proxy
+ - internal
+ deploy:
+ labels:
+ - "traefik.enable=true"
+ - "traefik.docker.network=proxy"
+ - "traefik.http.services.${STACK_NAME}.loadbalancer.server.port=80"
+ - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`${EXTRA_DOMAINS})"
+ - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}"
+ - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure"
+ - "traefik.http.routers.${STACK_NAME}.middlewares=${STACK_NAME}-redirect"
+ - "traefik.http.middlewares.${STACK_NAME}-redirect.redirectscheme.scheme=https"
+ - "traefik.http.middlewares.${STACK_NAME}-redirect.redirectscheme.permanent=true"
# extra_hosts:
# - "host.docker.internal:10.7.7.1"
# - "bbb-web:10.7.7.2"
@@ -107,11 +130,12 @@ services:
# etherpad (collaborative notepad)
etherpad:
- image: alangecker/bbb-docker-etherpad:2.2.7-s8328b77-p88f3f6b
+ image: alangecker/bbb-docker-etherpad:2.4.2-s8328b77-p88f3f6b
depends_on:
- redis
- collabora
- # environment:
+ environment:
+ COLLABORA_URL: ${COLLABORA_URL:-https://collabora:9980/cool}
# ETHERPAD_API_KEY is set via entrypoint
configs:
- source: entrypoint_etherpad
@@ -121,13 +145,11 @@ services:
- etherpad_api_key
entrypoint: /usr/local/bin/docker-entrypoint.sh
networks:
- bbb-net:
- aliases:
- - etherpad
+ - internal
# bbb-pads (bbb etherpad integration)
bbb-pads:
- image: alangecker/bbb-docker-pads:v1.5.3
+ image: alangecker/bbb-docker-pads:v1.5.6
depends_on:
- redis
- etherpad
@@ -141,25 +163,21 @@ services:
- etherpad_api_key
entrypoint: /usr/local/bin/docker-entrypoint.sh
networks:
- bbb-net:
- aliases:
- - bbb-pads
+ - internal
# redis (caching)
redis:
- image: redis:7.2-alpine
+ image: redis:8.4-alpine
#healthcheck:
# test: ["CMD", "redis-cli", "ping"]
# interval: 1s
# timeout: 3s
# retries: 30
networks:
- bbb-net:
- aliases:
- - redis
+ - internal
bbb-export-annotations:
- image: alangecker/bbb-docker-bbb-export-annotations:v3.0.4
+ image: alangecker/bbb-docker-bbb-export-annotations:v3.0.19
depends_on:
- redis
- etherpad
@@ -169,9 +187,7 @@ services:
# https://github.com/bigbluebutton/bigbluebutton/blob/v2.7.0/bbb-export-annotations/config/settings.json
# "bbbWebAPI": "http://127.0.0.1:8090", -> bbb-web
# "bbbPadsAPI": "http://127.0.0.1:9002", -> bbb-pads
- bbb-net:
- aliases:
- - bbb-export-annotations
+ - internal
volumes:
- bigbluebutton:/var/bigbluebutton
tmpfs:
@@ -179,17 +195,24 @@ services:
# webrtc-sfu (webrtc controller for negotiation and media stream)
webrtc-sfu:
- image: alangecker/bbb-docker-webrtc-sfu:v2.17.0-beta.6
+ image: alangecker/bbb-docker-webrtc-sfu:v2.21.2
depends_on:
- redis
- freeswitch
+ ports:
+ # mediasoup UDP port range — must match mediasoup.worker.rtcMinPort/rtcMaxPort in webrtc-sfu-config.yaml
+ - "24577-24676:24577-24676/udp"
environment:
# ESL_PASSWORD is set via entrypoint.webrtc-sfu.sh
- MS_WEBRTC_LISTEN_IPS: '[{"ip":"${EXTERNAL_IPv4}", "announcedIp":"${EXTERNAL_IPv4}"}]'
+ # ip must be 0.0.0.0 (container can't bind to external host IP)
+ MS_WEBRTC_LISTEN_IPS: '[{"ip":"0.0.0.0", "announcedIp":"${EXTERNAL_IPv4}"}]'
configs:
- source: entrypoint_webrtcsfu
target: /usr/local/bin/docker-entrypoint.sh
mode: 0555
+ - source: ws_conf
+ target: /etc/bigbluebutton/bbb-webrtc-sfu/production.yml
+ mode: 0555
entrypoint: /usr/local/bin/docker-entrypoint.sh
volumes:
- vol-mediasoup:/var/mediasoup
@@ -197,16 +220,19 @@ services:
- /var/log/bbb-webrtc-sfu
secrets:
- fsesl_password
- # network_mode: host
+ # network_mode: host would be needed for mediasoup UDP to work from outside;
+ # keeping on overlay network for now so other services can reach it by name.
# security_opt:
# - seccomp:unconfined # allow io_uring access for mediasoup
ulimits:
memlock: -1 # allow io_uring_register_buffers to allocate enough ram
+ networks:
+ - internal
# fsesl-akka (bbb freeswitch integration)
fsesl-akka:
- image: alangecker/bbb-docker-fsesl-akka:v3.0.4
+ image: alangecker/bbb-docker-fsesl-akka:v3.0.19
depends_on:
- redis
- freeswitch
@@ -220,13 +246,11 @@ services:
- fsesl_password
entrypoint: /usr/local/bin/docker-entrypoint.sh
networks:
- bbb-net:
- aliases:
- - fsesl-akka
+ - internal
# apps-akka (seems to be an bbb app integration endpoint)
apps-akka:
- image: alangecker/bbb-docker-apps-akka:v3.0.4
+ image: alangecker/bbb-docker-apps-akka:v3.0.19
depends_on:
- redis
environment:
@@ -241,17 +265,18 @@ services:
- source: bbbhtml5_conf
target: /etc/bigbluebutton/bbb-html5.yml
mode: 0555
+ - source: aa_conf
+ target: /etc/bigbluebutton/mod/bbb-apps-akka.conf.tmpl
+ mode: 0555
secrets:
- shared_secret
- postgres_password
entrypoint: /usr/local/bin/docker-entrypoint.sh
networks:
- bbb-net:
- aliases:
- - apps-akka
+ - internal
bbb-graphql-server:
- image: alangecker/bbb-docker-graphql-server:v3.0.4
+ image: alangecker/bbb-docker-graphql-server:v3.0.19
depends_on:
- postgres
- bbb-web
@@ -261,34 +286,36 @@ services:
- postgres_password
environment:
POSTGRES_USER: postgres
- POSTGRES_PASSWORD: ${POSTGRESQL_SECRET:-test}
- HASURA_GRAPHQL_ADMIN_SECRET: TODO_CHANGE_ME
+ # POSTGRES_PASSWORD and HASURA_GRAPHQL_ADMIN_SECRET are set via entrypoint
+ configs:
+ - source: entrypoint_graphqlserver
+ target: /usr/local/bin/docker-entrypoint.sh
+ mode: 0555
+ entrypoint: /usr/local/bin/docker-entrypoint.sh
+ command: ["graphql-engine", "serve"]
+ secrets:
+ - postgres_password
+ - hasura_admin_secret
networks:
- bbb-net:
- aliases:
- - bbb-graphql-server
+ - internal
bbb-graphql-actions:
- image: alangecker/bbb-docker-graphql-actions:v3.0.4
+ image: alangecker/bbb-docker-graphql-actions:v3.0.19
depends_on:
- redis
- apps-akka
networks:
- bbb-net:
- aliases:
- - bbb-graphql-actions
+ - internal
bbb-graphql-middleware:
- image: alangecker/bbb-docker-graphql-middleware:v3.0.4
+ image: alangecker/bbb-docker-graphql-middleware:v3.0.19
depends_on:
- bbb-graphql-server
- bbb-graphql-actions
- bbb-web
- redis
networks:
- bbb-net:
- aliases:
- - bbb-graphql-middleware
+ - internal
# extra_hosts:
# - "nginx:10.7.7.1"
@@ -297,9 +324,7 @@ services:
tmpfs:
- /tmp
networks:
- bbb-net:
- aliases:
- - collabora
+ - internal
# disable logging (way to verbose)
logging:
driver: none
@@ -308,7 +333,7 @@ services:
periodic:
image: alangecker/bbb-docker-periodic:v3.0.0
depends_on:
- - mongodb
+ - postgres
volumes:
- /var/run/docker.sock:/var/run/docker.sock # not sure what prupose this has?
- bigbluebutton:/var/bigbluebutton # access bbb data
@@ -320,32 +345,23 @@ services:
REMOVE_OLD_RECORDING: ${REMOVE_OLD_RECORDING}
RECORDING_MAX_AGE_DAYS: ${RECORDING_MAX_AGE_DAYS}
networks:
- bbb-net:
- aliases:
- - periodic
+ - internal
bbb-webrtc-recorder:
- image: alangecker/bbb-docker-webrtc-recorder:v0.8.0
+ image: alangecker/bbb-docker-webrtc-recorder:v0.13.1
depends_on:
- redis
- volumes:
- - webrtc-recorder-data:/var/lib/bbb-webrtc-recorder
- # WebRTC connection to bbb-webrtc-sfu seem to
- # only to work via the external IP
- # extra_hosts:
- # - "redis:10.7.7.5"
+ volumes:
+ - vol-webrtc-recorder:/var/lib/bbb-webrtc-recorder
networks:
- bbb-net:
- aliases:
- - bbb-webrtc-recorder
+ - internal
- # coturn
+ # coturn (TURN server — must use host networking for UDP relay to reach clients)
coturn:
- image: coturn/coturn:4.6-alpine
+ image: coturn/coturn:4.8-alpine
command:
- "--external-ip=${EXTERNAL_IPv4}/${EXTERNAL_IPv4}"
- "--external-ip=${EXTERNAL_IPv6:-::1}/${EXTERNAL_IPv6:-::1}"
- - "--static-auth-secret=${TURN_SECRET}"
- "--allowed-peer-ip=${EXTERNAL_IPv4}"
- "--relay-ip=${EXTERNAL_IPv4}"
- "--relay-ip=${EXTERNAL_IPv6:-::1}"
@@ -362,13 +378,14 @@ services:
volumes:
- "/var/home/thebastard/.abra/recipes/bigbluebutton/cert/cert.pem:/tmp/cert.pem:ro"
- "/var/home/thebastard/.abra/recipes/bigbluebutton/cert/key.pem:/tmp/key.pem:ro"
- # network_mode: host
+ # network_mode: host <- mine has this commented out
+ network_mode: host
user: root
entrypoint: /usr/local/bin/docker-entrypoint.sh
# greenlight
greenlight:
- image: bigbluebutton/greenlight:v3.5.0
+ image: bigbluebutton/greenlight:v3.6.3
depends_on:
- postgres
- redis
@@ -391,39 +408,37 @@ services:
- rails_secret
entrypoint: /usr/local/bin/docker-entrypoint.sh
networks:
- bbb-net:
- aliases:
- - greenlight
+ - internal
- # postgres for greenlight
+ # postgres for greenlight
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_DB: greenlight-v3
+ POSTGRES_MULTIPLE_DATABASES: bbb_graphql,hasura_app,greenlight
POSTGRES_USER: postgres
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
- #healthcheck:
- #test: ["CMD-SHELL", "pg_isready -U postgres"]
- #interval: 10s
- #timeout: 5s
- #retries: 5
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
volumes:
- "postgres_data:/var/lib/postgresql/data"
+ configs:
+ - source: initdb_sh
+ target: /docker-entrypoint-initdb.d/initdb.sh
+ mode: 0555
secrets:
- postgres_password
networks:
- bbb-net:
- aliases:
- - postgres
+ - internal
netshoot:
image: nicolaka/netshoot
entrypoint: /bin/bash
command: -c "sleep infinity"
networks:
- bbb-net:
- aliases:
- - netshoot
+ - internal
volumes:
greenlight_data:
@@ -431,7 +446,7 @@ volumes:
bigbluebutton:
vol-mediasoup:
vol-freeswitch:
- webrtc-recorder-data:
+ vol-webrtc-recorder:
configs:
entrypoint_greenlight:
@@ -455,12 +470,12 @@ configs:
entrypoint_webrtcsfu:
name: ${STACK_NAME}_entrypoint_webrtcsfu_${ENTRYPOINT_WEBRTCSFU_VERSION}
file: ./entrypoint.webrtc-sfu.sh
- mongod_conf:
- name: ${STACK_NAME}_mongod_conf_${MONGOD_CONF_VERSION}
- file: ./mongod.conf
- init_replica:
- name: ${STACK_NAME}_init_replica_${INIT_REPLICA_VERSION}
- file: ./init-replica.sh
+ entrypoint_graphqlserver:
+ name: ${STACK_NAME}_entrypoint_graphqlserver_${ENTRYPOINT_GRAPHQLSERVER_VERSION}
+ file: ./entrypoint.bbb-graphql-server.sh
+ initdb_sh:
+ name: ${STACK_NAME}_initdb_sh_${INITDB_SH_VERSION}
+ file: ./mod/initdb.sh
entrypoint_bbbpads:
name: ${STACK_NAME}_entrypoint_bbbpads_${ENTRYPOINT_BBBPADS_VERSION}
file: ./entrypoint.bbb-pads.sh
@@ -473,6 +488,30 @@ configs:
entrypoint_bbbweb:
name: ${STACK_NAME}_entrypoint_bbbweb_${ENTRYPOINT_BBBWEB_VERSION}
file: ./entrypoint.bbb-web.sh
+ aa_conf:
+ name: ${STACK_NAME}_aa_conf_${AA_CONF_VERSION}
+ file: ./mod/bbb-apps-akka.conf
+ beg_conf:
+ name: ${STACK_NAME}_beg_conf_${BEG_CONF_VERSION}
+ file: ./mod/bbb-exporter.nginx
+ bhdn_conf:
+ name: ${STACK_NAME}_bhdn_conf_${BHDN_CONF_VERSION}
+ file: ./mod/bbb-html5.dev.nginx
+ brf_conf:
+ name: ${STACK_NAME}_brf_conf_${BRF_CONF_VERSION}
+ file: ./mod/bbb-resync-freeswitch
+ nginx_conf:
+ name: ${STACK_NAME}_nginx_conf_${NGINX_CONF_VERSION}
+ file: ./mod/nginx.conf
+ wn_conf:
+ name: ${STACK_NAME}_wn_conf_${WN_CONF_VERSION}
+ file: ./mod/webhooks.nginx
+ wsn_conf:
+ name: ${STACK_NAME}_wsn_conf_${WSN_CONF_VERSION}
+ file: ./mod/webrtc-sfu.nginx
+ ws_conf:
+ name: ${STACK_NAME}_ws_conf_${WS_CONF_VERSION}
+ file: ./mod/webrtc-sfu-config.yaml
secrets:
postgres_password:
@@ -493,10 +532,11 @@ secrets:
etherpad_api_key:
external: true
name: ${STACK_NAME}_etherpad_api_key_${ETHERPAD_API_KEY_VERSION}
+ hasura_admin_secret:
+ external: true
+ name: ${STACK_NAME}_hasura_admin_secret_${SECRET_HASURA_ADMIN_SECRET_VERSION}
networks:
- bbb-net:
- ipam:
- driver: default
- config:
- - subnet: "10.7.7.0/24"
+ proxy:
+ external: true
+ internal:
\ No newline at end of file
diff --git a/entrypoint.bbb-graphql-server.sh b/entrypoint.bbb-graphql-server.sh
new file mode 100644
index 0000000..fad2e3b
--- /dev/null
+++ b/entrypoint.bbb-graphql-server.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+set -e
+
+# set POSTGRES_PASSWORD from Docker secret
+if test -f "/run/secrets/postgres_password"; then
+ pwd=$(cat /run/secrets/postgres_password)
+ if [ -z "$pwd" ]; then
+ echo >&2 "error: /run/secrets/postgres_password is empty"
+ exit 1
+ fi
+ echo "entrypoint.bbb-graphql-server.sh setting POSTGRES_PASSWORD"
+ export POSTGRES_PASSWORD="${pwd}"
+ unset pwd
+else
+ echo >&2 "error: /run/secrets/postgres_password does not exist"
+ exit 1
+fi
+
+# set HASURA_GRAPHQL_ADMIN_SECRET from Docker secret
+if test -f "/run/secrets/hasura_admin_secret"; then
+ pwd=$(cat /run/secrets/hasura_admin_secret)
+ if [ -z "$pwd" ]; then
+ echo >&2 "error: /run/secrets/hasura_admin_secret is empty"
+ exit 1
+ fi
+ echo "entrypoint.bbb-graphql-server.sh setting HASURA_GRAPHQL_ADMIN_SECRET"
+ export HASURA_GRAPHQL_ADMIN_SECRET="${pwd}"
+ unset pwd
+else
+ echo >&2 "error: /run/secrets/hasura_admin_secret does not exist"
+ exit 1
+fi
+
+exec "$@"
diff --git a/entrypoint.coturn.sh b/entrypoint.coturn.sh
index 561c70b..b23e73d 100755
--- a/entrypoint.coturn.sh
+++ b/entrypoint.coturn.sh
@@ -5,8 +5,13 @@ apk add jq su-exec
# create certs for proxy
if [ "$ENABLE_HTTPS_PROXY" == true ]; then
- while [ ! -f /etc/resty-auto-ssl/storage/file/*latest ]
+ while true
do
+ for cert_file in /etc/resty-auto-ssl/storage/file/*latest; do
+ if [ -f "$cert_file" ]; then
+ break 2
+ fi
+ done
echo "ERROR: certificate doesn't exist yet."
echo "Certificate gets create on the first request to the HTTPS proxy."
echo "We will try again..."
@@ -18,13 +23,6 @@ if [ "$ENABLE_HTTPS_PROXY" == true ]; then
cat /etc/resty-auto-ssl/storage/file/*%3Alatest | jq -r '.privkey_pem' > /tmp/key.pem
fi
-if [ ! -f /tmp/cert.pem ] || [ ! -f /tmp/key.pem ]; then
- echo "ERROR: certificate not found, but coturn relies on it."
- echo "Use either auto HTTPS proxy or"
- echo "provide path to certificates in .env file"
- exit 1
-fi
-
# set turn_secret variable
if test -f "/run/secrets/turn_secret"; then
pwd=$(cat /run/secrets/turn_secret)
diff --git a/entrypoint.greenlight.sh b/entrypoint.greenlight.sh
index 86a0dbf..8510412 100644
--- a/entrypoint.greenlight.sh
+++ b/entrypoint.greenlight.sh
@@ -9,7 +9,7 @@ if test -f "/run/secrets/postgres_password"; then
exit 1
fi
echo "entrypoint.greenlight.sh setting DATABASE_URL"
- export "DATABASE_URL"="postgres://postgres:${pwd}@postgres:5432/greenlight-v3"
+ export "DATABASE_URL"="postgres://postgres:${pwd}@postgres:5432/greenlight"
unset "pwd"
else
echo >&2 "error: /run/secrets/postgres_password does not exist"
diff --git a/init-replica.sh b/init-replica.sh
deleted file mode 100755
index 188cdda..0000000
--- a/init-replica.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-set -e
-
-
-host=${HOSTNAME:-$(hostname -f)}
-
-# shut down again
-mongod --pidfilepath /tmp/docker-entrypoint-temp-mongod.pid --shutdown
-# restart again binding to 0.0.0.0 to allow a replset with 10.7.7.6
-mongod --oplogSize 8 --replSet rs0 --noauth \
- --config /tmp/docker-entrypoint-temp-config.json \
- --bind_ip 0.0.0.0 --port 27017 \
- --tlsMode disabled \
- --logpath /proc/1/fd/1 --logappend \
- --pidfilepath /tmp/docker-entrypoint-temp-mongod.pid --fork
-
-# init replset with defaults
-mongo 10.7.7.6 --eval "rs.initiate({
- _id: 'rs0',
- members: [ { _id: 0, host: '10.7.7.6:27017' } ]
-})"
-
-echo "Waiting to become a master"
-echo 'while (!db.isMaster().ismaster) { sleep(100); }' | mongo
-
-echo "I'm the master!"
\ No newline at end of file
diff --git a/mod/apps-akka/Dockerfile b/mod/apps-akka/Dockerfile
new file mode 100644
index 0000000..6d4bf57
--- /dev/null
+++ b/mod/apps-akka/Dockerfile
@@ -0,0 +1,43 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+COPY --from=src-common-message / /bbb-common-message
+
+# build bbb-common-message
+RUN cd /bbb-common-message && ./deploy.sh
+
+# ===================================================
+
+ARG TAG_APPS_AKKA
+
+COPY --from=src-apps-akka / /source
+
+# compile and unzip bin
+RUN cd /source \
+ && sbt universal:packageBin \
+ && unzip /source/target/universal/bbb-apps-akka-0.0.4.zip -d /
+
+# ===================================================
+
+
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder-settings
+RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_linux_amd64 && chmod a+x /usr/local/bin/yq
+COPY --from=src-config /settings.yml /settings.yml
+ARG TAG_BBB
+RUN yq e -i ".public.app.bbbServerVersion = \"$TAG_BBB\"" /settings.yml
+RUN yq e -i ".public.app.html5ClientBuild = \"$TAG_BBB\"" /settings.yml
+
+
+# ===================================================
+
+FROM alangecker/bbb-docker-base-java
+
+COPY --from=builder-settings /usr/local/bin/yq /usr/local/bin/yq
+COPY --from=builder /bbb-apps-akka-0.0.4 /bbb-apps-akka
+COPY bbb-apps-akka.conf /etc/bigbluebutton/bbb-apps-akka.conf.tmpl
+COPY logback.xml /bbb-apps-akka/conf/logback.xml
+COPY entrypoint.sh /entrypoint.sh
+COPY --from=builder-settings --chown=bigbluebutton:bigbluebutton /settings.yml /usr/share/bigbluebutton/html5-client/private/config/settings.yml
+
+USER bigbluebutton
+ENTRYPOINT /entrypoint.sh
diff --git a/mod/apps-akka/entrypoint.sh b/mod/apps-akka/entrypoint.sh
new file mode 100644
index 0000000..033429e
--- /dev/null
+++ b/mod/apps-akka/entrypoint.sh
@@ -0,0 +1,17 @@
+#!/bin/sh -e
+
+# bbb-apps-akka.conf
+TARGET=/etc/bigbluebutton/bbb-apps-akka.conf
+cp /etc/bigbluebutton/bbb-apps-akka.conf.tmpl $TARGET
+sed -i "s/DOMAIN/$DOMAIN/" $TARGET
+sed -i "s/SHARED_SECRET/$SHARED_SECRET/" $TARGET
+sed -i "s/POSTGRES_PASSWORD/$POSTGRES_PASSWORD/" $TARGET
+
+
+# settings.yml
+TARGET=/usr/share/bigbluebutton/html5-client/private/config/settings.yml
+yq e -i ".public.kurento.wsUrl = \"wss://$DOMAIN/bbb-webrtc-sfu\"" $TARGET
+yq e -i ".public.pads.url = \"https://$DOMAIN/pad\"" $TARGET
+
+cd /bbb-apps-akka
+/bbb-apps-akka/bin/bbb-apps-akka
\ No newline at end of file
diff --git a/mod/apps-akka/logback.xml b/mod/apps-akka/logback.xml
new file mode 100644
index 0000000..c29b1fb
--- /dev/null
+++ b/mod/apps-akka/logback.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ %d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"} %-5level %logger{35} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/base-java/Dockerfile b/mod/base-java/Dockerfile
new file mode 100644
index 0000000..810feee
--- /dev/null
+++ b/mod/base-java/Dockerfile
@@ -0,0 +1,24 @@
+FROM eclipse-temurin:17-jre-jammy
+
+RUN apt-get update && apt-get install -y \
+ wget unzip gosu locales \
+ imagemagick xpdf-utils curl \
+ && sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
+
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US:en
+ENV LC_ALL en_US.UTF-8
+
+# add user & group
+RUN groupadd -g 998 bigbluebutton \
+ && useradd -m -u 998 -g bigbluebutton bigbluebutton \
+ && mkdir /etc/bigbluebutton \
+ && chown bigbluebutton:bigbluebutton /etc/bigbluebutton
+
+# add dockerize
+ENV DOCKERIZE_VERSION v0.7.0
+RUN wget -q https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
+ && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
+ && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
+
+
diff --git a/mod/bbb-apps-akka.conf b/mod/bbb-apps-akka.conf
new file mode 100644
index 0000000..ae21ad1
--- /dev/null
+++ b/mod/bbb-apps-akka.conf
@@ -0,0 +1,25 @@
+// include default config from upstream
+include "/bbb-apps-akka/conf/application.conf"
+
+redis {
+ host="redis"
+}
+
+services {
+ bbbWebAPI="https://DOMAIN/bigbluebutton/api"
+ sharedSecret="SHARED_SECRET"
+ graphqlMiddlewareAPI = "http://bbb-graphql-middleware:8378"
+}
+http {
+ interface = "0.0.0.0"
+}
+
+postgres {
+ properties = {
+ serverName = "postgres"
+ portNumber = "5432"
+ databaseName = "bbb_graphql"
+ user = "postgres"
+ password = "POSTGRES_PASSWORD"
+ }
+}
\ No newline at end of file
diff --git a/mod/bbb-export-annotations/Dockerfile b/mod/bbb-export-annotations/Dockerfile
new file mode 100644
index 0000000..d6c591f
--- /dev/null
+++ b/mod/bbb-export-annotations/Dockerfile
@@ -0,0 +1,23 @@
+FROM node:22-bookworm-slim AS builder
+
+COPY --from=src / /bbb-export-annotations
+RUN cd /bbb-export-annotations && npm ci && npm install
+
+# --------------------
+
+FROM node:22-bookworm-slim
+
+RUN groupadd -g 998 bigbluebutton \
+ && useradd -m -u 998 -g bigbluebutton bigbluebutton
+
+RUN apt update && apt install -y \
+ nodejs npm cairosvg ghostscript imagemagick nodejs poppler-utils
+
+COPY --from=builder /bbb-export-annotations /bbb-export-annotations
+COPY ./config/settings.json /bbb-export-annotations/config/settings.json
+
+USER bigbluebutton
+WORKDIR /bbb-export-annotations
+ENV NODE_ENV=production
+
+ENTRYPOINT npm start
diff --git a/mod/bbb-export-annotations/config/settings.json b/mod/bbb-export-annotations/config/settings.json
new file mode 100644
index 0000000..294c3be
--- /dev/null
+++ b/mod/bbb-export-annotations/config/settings.json
@@ -0,0 +1,40 @@
+{
+ "log": {
+ "level": "info",
+ "msgName": "PresAnnStatusMsg"
+ },
+ "shared": {
+ "presAnnDropboxDir": "/tmp/pres-ann-dropbox",
+ "cairosvg": "/usr/bin/cairosvg",
+ "ghostscript": "/usr/bin/gs"
+ },
+ "process": {
+ "maxImageWidth": 1440,
+ "maxImageHeight": 1080,
+ "pointsPerInch": 72,
+ "pixelsPerInch": 96,
+ "cairoSVGUnsafeFlag": false
+ },
+ "notifier": {
+ "pod_id": "DEFAULT_PRESENTATION_POD",
+ "is_downloadable": "false",
+ "msgName": "NewPresFileAvailableMsg"
+ },
+ "bbbWebAPI": "http://bbb-web:8090",
+ "bbbPadsAPI": "http://bbb-pads:9002",
+ "redis": {
+ "host": "redis",
+ "port": 6379,
+ "password": null,
+ "channels": {
+ "queue": "exportJobs",
+ "publish": "to-akka-apps-redis-channel"
+ }
+ },
+ "fonts": {
+ "draw": "/usr/local/share/fonts/Shantell_Sans-Tldrawish.woff2",
+ "sans": "/usr/local/share/fonts/IBMPlexSans-Medium.woff2",
+ "serif": "/usr/local/share/fonts/IBMPlexSerif-Medium.woff2",
+ "mono": "/usr/local/share/fonts/IBMPlexMono-Medium.woff2"
+ }
+}
\ No newline at end of file
diff --git a/mod/bbb-exporter.nginx b/mod/bbb-exporter.nginx
new file mode 100644
index 0000000..7b1dfaa
--- /dev/null
+++ b/mod/bbb-exporter.nginx
@@ -0,0 +1,4 @@
+location /bbb-exporter {
+ proxy_pass http://prometheus-exporter:9688;
+ proxy_http_version 1.1;
+}
\ No newline at end of file
diff --git a/mod/bbb-graphql-actions/Dockerfile b/mod/bbb-graphql-actions/Dockerfile
new file mode 100644
index 0000000..66ac9b8
--- /dev/null
+++ b/mod/bbb-graphql-actions/Dockerfile
@@ -0,0 +1,34 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+COPY --from=src ./ /src
+RUN cd /src && \
+ npm ci --no-progress && \
+ npm run build
+
+# delete node_modules (it should create a fresh one inside /src/dist/)
+RUN rm -rf /src/node_modules
+
+RUN cd /src/dist && \
+ mv index.js bbb-graphql-actions.js && \
+ cp ../package.json ../package-lock.json . && \
+ npm ci --no-progress --omit=dev
+
+
+# ------------------------------
+FROM node:22-bookworm-slim
+
+RUN groupadd -g 2062 app \
+ && useradd -m -u 2063 -g app app
+
+USER app
+
+WORKDIR /app
+
+ENV SERVER_HOST 0.0.0.0
+ENV BBB_REDIS_HOST redis
+ENV NODE_ENV=production
+
+COPY --from=builder /src/dist /app
+
+CMD [ "node", "/app/bbb-graphql-actions.js" ]
\ No newline at end of file
diff --git a/mod/bbb-graphql-actions/Dockerfile.dev b/mod/bbb-graphql-actions/Dockerfile.dev
new file mode 100644
index 0000000..22babbb
--- /dev/null
+++ b/mod/bbb-graphql-actions/Dockerfile.dev
@@ -0,0 +1,16 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+RUN apt-get update && apt-get install -y gosu
+
+# allow any user to use node in /root/.nvm
+RUN chmod 755 /root
+
+COPY dev-entrypoint.sh /dev-entrypoint.sh
+ENTRYPOINT [ "/dev-entrypoint.sh" ]
+
+WORKDIR /app
+ENV SERVER_HOST 0.0.0.0
+ENV BBB_REDIS_HOST redis
+
+CMD [ "npm install && npm start" ]
\ No newline at end of file
diff --git a/mod/bbb-graphql-actions/dev-entrypoint.sh b/mod/bbb-graphql-actions/dev-entrypoint.sh
new file mode 100644
index 0000000..7c3700c
--- /dev/null
+++ b/mod/bbb-graphql-actions/dev-entrypoint.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# get owner of /app
+OWNER="$(stat -c '%u' "/app")"
+GROUP="$(stat -c '%g' "/app")"
+useradd --home-dir /tmp -u $OWNER user || /bin/true
+
+# run with same user to avoid any issues
+# with file permissions
+. /root/.nvm/nvm.sh
+gosu $OWNER:$GROUP bash -c "$@"
+
diff --git a/mod/bbb-graphql-middleware/Dockerfile b/mod/bbb-graphql-middleware/Dockerfile
new file mode 100644
index 0000000..763ee1a
--- /dev/null
+++ b/mod/bbb-graphql-middleware/Dockerfile
@@ -0,0 +1,12 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+COPY --from=src / /src/
+RUN cd /src/ && CGO_ENABLED=0 go build -o bbb-graphql-middleware cmd/bbb-graphql-middleware/main.go
+
+# ------------------------------
+FROM alpine
+COPY --from=builder /src/bbb-graphql-middleware /app/bbb-graphql-middleware
+COPY --from=builder /src/config/config.yml /usr/share/bbb-graphql-middleware/config.yml
+COPY config.yml /etc/bigbluebutton/bbb-graphql-middleware.yml
+CMD [ "/app/bbb-graphql-middleware" ]
\ No newline at end of file
diff --git a/mod/bbb-graphql-middleware/Dockerfile.dev b/mod/bbb-graphql-middleware/Dockerfile.dev
new file mode 100644
index 0000000..d1952d4
--- /dev/null
+++ b/mod/bbb-graphql-middleware/Dockerfile.dev
@@ -0,0 +1,8 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+WORKDIR /app
+
+ENV GOPATH /gopath
+
+CMD ["go", "run", "cmd/bbb-graphql-middleware/main.go", "--signal", "SIGTERM"]
\ No newline at end of file
diff --git a/mod/bbb-graphql-middleware/config.yml b/mod/bbb-graphql-middleware/config.yml
new file mode 100644
index 0000000..f323157
--- /dev/null
+++ b/mod/bbb-graphql-middleware/config.yml
@@ -0,0 +1,15 @@
+server:
+ listen_host: 0.0.0.0
+ listen_port: 8378
+redis:
+ host: redis
+ port: 6379
+ password: ""
+hasura:
+ url: ws://nginx:8185/v1/graphql
+graphql-actions:
+ url: http://bbb-graphql-actions:8093
+auth_hook:
+ url: http://bbb-web:8090/bigbluebutton/connection/checkGraphqlAuthorization
+session_vars_hook:
+ url: http://apps-akka:8901/userInfo
\ No newline at end of file
diff --git a/mod/bbb-graphql-server/Dockerfile b/mod/bbb-graphql-server/Dockerfile
new file mode 100644
index 0000000..3c087cc
--- /dev/null
+++ b/mod/bbb-graphql-server/Dockerfile
@@ -0,0 +1,25 @@
+ARG BBB_BUILD_TAG
+ARG GRAPHQL_ENGINE_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+RUN curl -L https://github.com/hasura/graphql-engine/raw/stable/cli/get.sh | INSTALL_PATH=/usr/local/bin VERSION=v2.44.0 bash
+RUN wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 && chmod a+x /usr/local/bin/yq
+
+# ----------------------------
+FROM hasura/graphql-engine:$GRAPHQL_ENGINE_TAG
+
+# install netstat, required for start script
+RUN apt-get update && apt-get install -y net-tools gosu
+
+COPY --from=builder /usr/local/bin/yq /usr/local/bin/yq
+COPY --from=builder /usr/local/bin/hasura /usr/local/bin/hasura
+
+COPY --from=src /bbb_schema.sql /app/
+COPY --from=src /metadata /app/metadata
+
+COPY config.yaml /app/config.yaml
+COPY entrypoint.sh /entrypoint.sh
+COPY start.sh /app/start.sh
+
+ENTRYPOINT [ "/entrypoint.sh" ]
+CMD [ "/app/start.sh" ]
diff --git a/mod/bbb-graphql-server/config.yaml b/mod/bbb-graphql-server/config.yaml
new file mode 100644
index 0000000..cd39dc2
--- /dev/null
+++ b/mod/bbb-graphql-server/config.yaml
@@ -0,0 +1,7 @@
+version: 3
+endpoint: http://localhost:8085
+admin_secret: bigbluebutton
+metadata_directory: metadata
+actions:
+ kind: synchronous
+ handler_webhook_baseurl: http://localhost:3000
diff --git a/mod/bbb-graphql-server/entrypoint.sh b/mod/bbb-graphql-server/entrypoint.sh
new file mode 100644
index 0000000..f14e2f4
--- /dev/null
+++ b/mod/bbb-graphql-server/entrypoint.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# for psql
+export PGHOST=postgres
+export PGUSER="${POSTGRES_USER}"
+export PGPASSWORD="${POSTGRES_PASSWORD}"
+
+
+# for hasura
+export HASURA_GRAPHQL_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/hasura_app
+export HASURA_GRAPHQL_METADATA_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/hasura_app
+export HASURA_GRAPHQL_LOG_LEVEL=warn
+export HASURA_GRAPHQL_ENABLE_CONSOLE=false
+export HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL=333
+export HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_BATCH_SIZE=1000
+export HASURA_GRAPHQL_STREAMING_QUERIES_MULTIPLEXED_REFETCH_INTERVAL=150
+export HASURA_GRAPHQL_STREAMING_QUERIES_MULTIPLEXED_BATCH_SIZE=1000
+export HASURA_GRAPHQL_SERVER_PORT=8085
+export HASURA_GRAPHQL_ENABLE_TELEMETRY=false
+export HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE=10
+export HASURA_GRAPHQL_AUTH_HOOK=http://apps-akka:8901/userInfo
+export HASURA_BBB_GRAPHQL_ACTIONS_ADAPTER_URL=http://bbb-graphql-actions:8093
+
+
+export HASURA_GRAPHQL_BBB_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/bbb_graphql
+
+exec $@
\ No newline at end of file
diff --git a/mod/bbb-graphql-server/start.sh b/mod/bbb-graphql-server/start.sh
new file mode 100644
index 0000000..5fc3354
--- /dev/null
+++ b/mod/bbb-graphql-server/start.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+set -e
+
+cd /app/
+
+# patch database url
+# TODO: this should be possible upstream in BBB via an environment variable
+yq e -i ".[1].configuration.connection_info.database_url = \"$HASURA_GRAPHQL_BBB_DATABASE_URL\"" metadata/databases/databases.yaml
+
+sed -i "s/^admin_secret: .*/admin_secret: $HASURA_GRAPHQL_ADMIN_SECRET/g" /app/config.yaml
+
+echo "SELECT 'CREATE DATABASE hasura_app' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'hasura_app')\gexec" | psql
+
+echo "Restarting database bbb_graphql"
+psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname = 'bbb_graphql'" > /dev/null
+psql -c "drop database if exists bbb_graphql with (force)"
+psql -c "create database bbb_graphql WITH TEMPLATE template0 LC_COLLATE 'C.UTF-8'"
+psql -c "alter database bbb_graphql set timezone to 'UTC'"
+
+echo "Creating tables in bbb_graphql"
+psql -U postgres -d bbb_graphql -q -f bbb_schema.sql --set ON_ERROR_STOP=on
+
+echo "Starting hasura-graphql-engine"
+gosu nobody graphql-engine serve &
+PID=$!
+
+sleep 1
+
+
+#Check if Hasura is ready before applying metadata
+while ! netstat -tuln | grep ":$HASURA_GRAPHQL_SERVER_PORT " > /dev/null; do
+ echo "Waiting for Hasura's port ($HASURA_GRAPHQL_SERVER_PORT) to be ready..."
+ sleep 1
+done
+
+echo "Applying new metadata to Hasura"
+/usr/local/bin/hasura metadata apply --skip-update-check
+
+wait "$PID"
\ No newline at end of file
diff --git a/mod/bbb-html5.dev.nginx b/mod/bbb-html5.dev.nginx
new file mode 100644
index 0000000..5b059ad
--- /dev/null
+++ b/mod/bbb-html5.dev.nginx
@@ -0,0 +1,23 @@
+# serve locale index from prebuilt static files
+location = /html5client/locales/ {
+ alias /usr/share/bigbluebutton/html5-client/locales/;
+ autoindex on;
+ autoindex_format json;
+
+ # Prevent browsers from caching
+ add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
+ add_header Pragma "no-cache";
+ add_header Expires 0;
+}
+
+# running from source (npm start)
+location /html5client/ {
+ rewrite /html5client/(.*) /$1 break;
+ gzip_static on;
+ proxy_pass http://webrtc-sfu:3000/;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ proxy_set_header Host $host;
+}
+
diff --git a/mod/bbb-pads/Dockerfile b/mod/bbb-pads/Dockerfile
new file mode 100644
index 0000000..e366366
--- /dev/null
+++ b/mod/bbb-pads/Dockerfile
@@ -0,0 +1,18 @@
+FROM node:22-bookworm-slim AS builder
+
+COPY --from=src / /bbb-pads
+RUN cd /bbb-pads && npm install --production
+
+
+RUN chmod 777 /bbb-pads/config
+# ------------------------------
+
+FROM node:22-bookworm-slim
+
+RUN apt update && apt install -y jq moreutils \
+ && useradd --uid 2003 --create-home --user-group bbb-pads
+
+COPY --from=builder /bbb-pads /bbb-pads
+USER bbb-pads
+COPY entrypoint.sh /entrypoint.sh
+ENTRYPOINT /entrypoint.sh
\ No newline at end of file
diff --git a/mod/bbb-pads/entrypoint.sh b/mod/bbb-pads/entrypoint.sh
new file mode 100644
index 0000000..9f93722
--- /dev/null
+++ b/mod/bbb-pads/entrypoint.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+
+TARGET=/bbb-pads/config/settings.json
+
+cp /bbb-pads/config/settings.json.template $TARGET
+sed -i "s/ETHERPAD_API_KEY/\"$ETHERPAD_API_KEY\"/g" $TARGET
+jq '.etherpad.host = "etherpad"' $TARGET | sponge $TARGET
+jq '.express.host = "0.0.0.0"' $TARGET | sponge $TARGET
+jq '.redis.host = "redis"' $TARGET | sponge $TARGET
+
+
+cd /bbb-pads
+export NODE_ENV=production
+npm start
\ No newline at end of file
diff --git a/mod/bbb-resync-freeswitch b/mod/bbb-resync-freeswitch
new file mode 100644
index 0000000..8b73c06
--- /dev/null
+++ b/mod/bbb-resync-freeswitch
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# https://github.com/bigbluebutton/bigbluebutton/pull/9597/files
+
+docker exec -it bbb-freeswitch fs_cli -H webrtc-sfu -P 8021 -x 'fsctl sync_clock_when_idle'
\ No newline at end of file
diff --git a/mod/bbb-web/Dockerfile b/mod/bbb-web/Dockerfile
new file mode 100644
index 0000000..5a08075
--- /dev/null
+++ b/mod/bbb-web/Dockerfile
@@ -0,0 +1,60 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+COPY --from=src-common-message / /bbb-common-message
+
+# build bbb-common-message
+RUN cd /bbb-common-message && ./deploy.sh
+
+# ===================================================
+
+
+COPY --from=src-common-web / /bbb-common-web
+# build bbb-common-web
+RUN cd /bbb-common-web && ./deploy.sh
+
+COPY --from=src-web / /bbb-web
+
+# compile bbb-web
+RUN cd /bbb-web && sh ./gradlew assemble
+
+# compile pres-checker
+RUN cd /bbb-web/pres-checker && gradle jar
+RUN mkdir -p /bbb-web/pres-checker/lib && find /bbb-web/pres-checker && \
+ cp /bbb-web/pres-checker/build/libs/bbb-pres-check-0.0.1.jar /bbb-web/pres-checker/lib
+
+# extract .war
+RUN unzip -q /bbb-web/build/libs/bigbluebutton-0.10.0.war -d /dist
+
+
+# ===================================================
+FROM alangecker/bbb-docker-base-java
+
+# add blank presentation files and allow conversion to pdf/svg
+RUN mkdir -p /usr/share/bigbluebutton/blank \
+ && cd /usr/share/bigbluebutton/blank \
+ && wget \
+ https://raw.githubusercontent.com/bigbluebutton/bigbluebutton/v3.0.19/bigbluebutton-config/slides/blank-svg.svg \
+ https://raw.githubusercontent.com/bigbluebutton/bigbluebutton/v3.0.19/bigbluebutton-config/slides/blank-thumb.png \
+ https://raw.githubusercontent.com/bigbluebutton/bigbluebutton/v3.0.19/bigbluebutton-config/slides/blank-presentation.pdf \
+ https://raw.githubusercontent.com/bigbluebutton/bigbluebutton/v3.0.19/bigbluebutton-config/slides/blank-png.png \
+ && sed -i 's///g' /etc/ImageMagick-6/policy.xml \
+ && sed -i '/potrace/d' /etc/ImageMagick-6/delegates.xml
+
+
+# get bbb-web
+COPY --from=builder /dist /usr/share/bbb-web
+
+# get pres-checker
+COPY --from=builder /bbb-web/pres-checker/lib /usr/share/prescheck/lib
+COPY --from=builder /bbb-web/pres-checker/run.sh /usr/share/prescheck/prescheck.sh
+
+# add entrypoint and templates
+COPY entrypoint.sh /entrypoint.sh
+COPY bbb-web.properties /etc/bigbluebutton/bbb-web.properties.tmpl
+COPY turn-stun-servers.xml /etc/bigbluebutton/turn-stun-servers.xml.tmpl
+COPY logback.xml /usr/share/bbb-web/WEB-INF/classes/logback.xml
+COPY office-convert.sh /usr/share/bbb-libreoffice-conversion/convert.sh
+COPY run-in-systemd.sh /usr/share/bbb-web/run-in-systemd.sh
+
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/mod/bbb-web/bbb-web.properties b/mod/bbb-web/bbb-web.properties
new file mode 100644
index 0000000..7c653cd
--- /dev/null
+++ b/mod/bbb-web/bbb-web.properties
@@ -0,0 +1,24 @@
+defaultWelcomeMessage={{ .Env.WELCOME_MESSAGE }}
+defaultWelcomeMessageFooter={{ .Env.WELCOME_FOOTER }}
+
+{{ if isTrue .Env.ENABLE_RECORDING }}
+disableRecordingDefault=false
+{{ else }}
+disableRecordingDefault=true
+{{ end }}
+
+bigbluebutton.web.serverURL=https://{{ .Env.DOMAIN }}
+
+securitySalt={{ .Env.SHARED_SECRET }}
+
+redisHost=redis
+
+{{ if isTrue .Env.IGNORE_TLS_CERT_ERRORS }}
+beans.presentationService.defaultUploadedPresentation=https://raw.githubusercontent.com/bigbluebutton/bigbluebutton/v3.0.19/bigbluebutton-config/assets/default.pdf
+{{else}}
+beans.presentationService.defaultUploadedPresentation=${bigbluebutton.web.serverURL}/default.pdf
+{{end}}
+
+learningDashboardEnabled={{ .Env.ENABLE_LEARNING_DASHBOARD }}
+
+defaultNumDigitsForTelVoice=9
\ No newline at end of file
diff --git a/mod/bbb-web/entrypoint.sh b/mod/bbb-web/entrypoint.sh
new file mode 100644
index 0000000..f9182f2
--- /dev/null
+++ b/mod/bbb-web/entrypoint.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+set -e
+
+# create recording directory structure if it doesn't exist yet
+mkdir -p /var/bigbluebutton/recording/status
+mkdir -p /var/bigbluebutton/events
+mkdir -p /var/bigbluebutton/recording
+mkdir -p /var/bigbluebutton/recording/raw
+mkdir -p /var/bigbluebutton/recording/process
+mkdir -p /var/bigbluebutton/recording/publish
+mkdir -p /var/bigbluebutton/recording/status/recorded
+mkdir -p /var/bigbluebutton/recording/status/archived
+mkdir -p /var/bigbluebutton/recording/status/processed
+mkdir -p /var/bigbluebutton/recording/status/ended
+mkdir -p /var/bigbluebutton/recording/status/sanity
+mkdir -p /var/bigbluebutton/recording/status/published
+mkdir -p /var/bigbluebutton/captions
+mkdir -p /var/bigbluebutton/captions/inbox
+mkdir -p /var/bigbluebutton/published
+mkdir -p /var/bigbluebutton/deleted
+mkdir -p /var/bigbluebutton/unpublished
+mkdir -p /var/bigbluebutton/basic_stats
+chown -R bigbluebutton:bigbluebutton /var/bigbluebutton
+
+cd /usr/share/bbb-web/
+dockerize \
+ -template /etc/bigbluebutton/bbb-web.properties.tmpl:/etc/bigbluebutton/bbb-web.properties \
+ -template /etc/bigbluebutton/turn-stun-servers.xml.tmpl:/etc/bigbluebutton/turn-stun-servers.xml \
+ gosu bigbluebutton java -Dgrails.env=prod -Dserver.address=0.0.0.0 -Dserver.port=8090 -Dspring.main.allow-circular-references=true -Xms384m -Xmx384m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/bigbluebutton/diagnostics -cp WEB-INF/lib/*:/:WEB-INF/classes/:. org.springframework.boot.loader.launch.WarLauncher
+
+
diff --git a/mod/bbb-web/logback.xml b/mod/bbb-web/logback.xml
new file mode 100644
index 0000000..def4f59
--- /dev/null
+++ b/mod/bbb-web/logback.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ %d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"} %-5level %logger{35} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/bbb-web/office-convert.sh b/mod/bbb-web/office-convert.sh
new file mode 100644
index 0000000..ee88b34
--- /dev/null
+++ b/mod/bbb-web/office-convert.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+set -e
+set -u
+PATH="/bin/:/usr/bin/"
+
+# This script receives three params
+# Param 1: Input office file path (e.g. "/tmp/test.odt")
+# Param 2: Output pdf file path (e.g. "/tmp/test.pdf")
+# Param 3: Destination Format (pdf default)
+# Param 4: Timeout (secs) (optional)
+
+if (( $# == 0 )); then
+ echo "Missing parameter 1 (Input office file path)";
+ exit 1
+elif (( $# == 1 )); then
+ echo "Missing parameter 2 (Output pdf file path)";
+ exit 1
+fi;
+
+
+source="$1"
+dest="$2"
+
+# If output format is missing, define PDF
+convertTo="${3:-pdf}"
+
+# If timeout is missing, define 60
+timeoutSecs="${4:-60}"
+# Truncate timeout to max 3 digits (as expected by sudoers)
+timeoutSecs="${timeoutSecs:0:3}"
+
+# The timeout is important.
+
+timeout $(printf %03d $timeoutSecs)s curl -F "data=@${source}" -k $COLLABORA_URL/convert-to/$convertTo > "${dest}"
+
+exit 0
diff --git a/mod/bbb-web/run-in-systemd.sh b/mod/bbb-web/run-in-systemd.sh
new file mode 100644
index 0000000..79018d1
--- /dev/null
+++ b/mod/bbb-web/run-in-systemd.sh
@@ -0,0 +1,10 @@
+#!/bin/sh -e
+
+# bbb-web requires a script under /usr/share/bbb-web/run-in-systemd.sh to run certain tasks
+# this is used for sandboxing, which is in our case a bit more difficult, because
+# we run it without systemd in an unprivileged container, with currently no extra sandboxing capabilities
+
+# TODO: exploring better ways! (e. g. firejail)
+
+timeout_secs="$1"; shift
+exec timeout "${timeout_secs}" "$@"
\ No newline at end of file
diff --git a/mod/bbb-web/turn-stun-servers.xml b/mod/bbb-web/turn-stun-servers.xml
new file mode 100644
index 0000000..de92838
--- /dev/null
+++ b/mod/bbb-web/turn-stun-servers.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{if and (isTrue .Env.ENABLE_HTTPS_PROXY) (not (isTrue .Env.IGNORE_TLS_CERT_ERRORS)) }}
+ {{/* ignore when using a self signed certificate in dev mode */}}
+
+
+
+
+
+ {{end}}
+
+
+ {{if .Env.TURN_EXT_SERVER }}
+
+
+
+
+
+ {{end}}
+
+
+
+
+
+
+
+
+
+
+
+ {{if and (isTrue .Env.ENABLE_HTTPS_PROXY) (not (isTrue .Env.IGNORE_TLS_CERT_ERRORS)) }}
+
+ {{end}}
+
+ {{if .Env.TURN_EXT_SERVER }}
+
+ {{end}}
+
+
+
+
+
+
+
+
diff --git a/mod/bbb-webrtc-recorder/Dockerfile b/mod/bbb-webrtc-recorder/Dockerfile
new file mode 100644
index 0000000..61fd252
--- /dev/null
+++ b/mod/bbb-webrtc-recorder/Dockerfile
@@ -0,0 +1,40 @@
+# Build stage
+FROM golang:1.25 as builder
+
+ARG APP_VERSION=devel
+ARG GOMOD=github.com/bigbluebutton/bbb-webrtc-recorder
+
+WORKDIR /app
+
+COPY --from=src go.* ./
+
+RUN go mod tidy
+
+COPY --from=src . ./
+
+RUN APP_VERSION=$(cat ./VERSION | sed 's/ /-/g') \
+ go build -o ./build/bbb-webrtc-recorder \
+ -ldflags="-X '$GOMOD/internal.AppVersion=v${APP_VERSION1}'" \
+ ./cmd/bbb-webrtc-recorder
+
+
+RUN mv /app/build/bbb-webrtc-recorder /usr/bin/bbb-webrtc-recorder
+
+# Running stage
+FROM debian:bookworm-slim
+
+RUN apt-get update && apt-get install -y gosu
+
+# use same UID as in the recordings container
+RUN groupadd -g 998 bigbluebutton && useradd -m -u 998 -g bigbluebutton bigbluebutton
+
+# config
+ENV BBBRECORDER_PUBSUB_ADAPTERS_REDIS_ADDRESS=redis:6379
+ENV BBBRECORDER_PUBSUB_ADAPTERS_REDIS_NETWORK=tcp
+ENV BBBRECORDER_DEBUG=true
+
+# Copy the binary to the production image from the builder stage.
+COPY --from=builder /usr/bin/bbb-webrtc-recorder /usr/bin/bbb-webrtc-recorder
+COPY --from=builder /app/config/bbb-webrtc-recorder.yml /etc/bbb-webrtc-recorder/bbb-webrtc-recorder.yml
+
+CMD ["/bin/sh", "-c", "chown -R bigbluebutton:bigbluebutton /var/lib/bbb-webrtc-recorder && gosu bigbluebutton /usr/bin/bbb-webrtc-recorder"]
\ No newline at end of file
diff --git a/mod/coturn/turnserver.conf b/mod/coturn/turnserver.conf
new file mode 100644
index 0000000..55cdf9d
--- /dev/null
+++ b/mod/coturn/turnserver.conf
@@ -0,0 +1,28 @@
+listening-port=3478
+
+# listening-ip=${INTERNAL_IP:-$IP}
+# relay-ip=${INTERNAL_IP:-$IP}
+
+min-port=32769
+max-port=65535
+# verbose
+
+fingerprint
+lt-cred-mech
+use-auth-secret
+realm=bbb-docker
+
+keep-address-family
+
+no-cli
+no-tlsv1
+no-tlsv1_1
+
+# Block connections to IP ranges which shouldn't be reachable
+no-loopback-peers
+no-multicast-peers
+
+
+# we only need to allow peer connections from the machine itself (from mediasoup or freeswitch).
+denied-peer-ip=0.0.0.0-255.255.255.255
+denied-peer-ip=::-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
\ No newline at end of file
diff --git a/mod/etherpad/Dockerfile b/mod/etherpad/Dockerfile
new file mode 100644
index 0000000..1633561
--- /dev/null
+++ b/mod/etherpad/Dockerfile
@@ -0,0 +1,29 @@
+ARG TAG_ETHERPAD
+FROM etherpad/etherpad:$TAG_ETHERPAD
+
+USER root
+
+RUN apk add git curl
+
+USER etherpad
+
+RUN pnpm run plugins i \
+ ep_disable_chat@0.0.13 \
+ ep_auth_session@1.1.1 \
+ --github \
+ mconf/ep_cursortrace#56fb8c2b211cdda4fc8715ec99e1cb7b7d9eb851 \
+ mconf/ep_pad_ttl#360136cd38493dd698435631f2373cbb7089082d \
+ mconf/ep_redis_publisher#2b6e47c1c59362916a0b2961a29b259f2977b694
+
+
+# add skin from git submodule
+COPY --chown=etherpad:0 --from=skin / /opt/etherpad-lite/src/static/skins/bigbluebutton
+
+# add plugin from git submodule
+COPY --chown=etherpad:0 --from=plugin / /ep_bigbluebutton_patches
+RUN pnpm run plugins i --path /ep_bigbluebutton_patches
+
+COPY settings.json /opt/etherpad-lite/settings.json
+COPY etherpad-export.sh /etherpad-export.sh
+COPY entrypoint.sh /entrypoint.sh
+ENTRYPOINT ["/entrypoint.sh"]
\ No newline at end of file
diff --git a/mod/etherpad/entrypoint.sh b/mod/etherpad/entrypoint.sh
new file mode 100644
index 0000000..acc2392
--- /dev/null
+++ b/mod/etherpad/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo $ETHERPAD_API_KEY > /tmp/apikey
+pnpm run prod --apikey /tmp/apikey
\ No newline at end of file
diff --git a/mod/etherpad/etherpad-export.sh b/mod/etherpad/etherpad-export.sh
new file mode 100644
index 0000000..0ebd733
--- /dev/null
+++ b/mod/etherpad/etherpad-export.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+src="$8"
+dest="$(echo $8 | sed -E -e 's/html|odt/'$7'/')"
+convertTo="$7"
+
+
+curl -v -F "data=@${src}" -k $COLLABORA_URL/convert-to/$convertTo > "${dest}"
+
+exit 0
\ No newline at end of file
diff --git a/mod/etherpad/settings.json b/mod/etherpad/settings.json
new file mode 100644
index 0000000..d3c1c4e
--- /dev/null
+++ b/mod/etherpad/settings.json
@@ -0,0 +1,723 @@
+/*
+ * This file must be valid JSON. But comments are allowed
+ *
+ * Please edit settings.json, not settings.json.template
+ *
+ * Please note that starting from Etherpad 1.6.0 you can store DB credentials in
+ * a separate file (credentials.json).
+ *
+ *
+ * ENVIRONMENT VARIABLE SUBSTITUTION
+ * =================================
+ *
+ * All the configuration values can be read from environment variables using the
+ * syntax "${ENV_VAR}" or "${ENV_VAR:default_value}".
+ *
+ * This is useful, for example, when running in a Docker container.
+ *
+ * DETAILED RULES:
+ * - If the environment variable is set to the string "true" or "false", the
+ * value becomes Boolean true or false.
+ * - If the environment variable is set to the string "null", the value
+ * becomes null.
+ * - If the environment variable is set to the string "undefined", the setting
+ * is removed entirely, except when used as the member of an array in which
+ * case it becomes null.
+ * - If the environment variable is set to a string representation of a finite
+ * number, the string is converted to that number.
+ * - If the environment variable is set to any other string, including the
+ * empty string, the value is that string.
+ * - If the environment variable is unset and a default value is provided, the
+ * value is as if the environment variable was set to the provided default:
+ * - "${UNSET_VAR:}" becomes the empty string.
+ * - "${UNSET_VAR:foo}" becomes the string "foo".
+ * - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false.
+ * - "${UNSET_VAR:null}" becomes null.
+ * - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set
+ * to null, if used as a member of an array).
+ * - If the environment variable is unset and no default value is provided,
+ * the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF
+ * ETHERPAD; if you want the default value to be null, you should explicitly
+ * specify "null" as the default value.
+ *
+ * EXAMPLE:
+ * "port": "${PORT:9001}"
+ * "minify": "${MINIFY}"
+ * "skinName": "${SKIN_NAME:colibris}"
+ *
+ * Would read the configuration values for those items from the environment
+ * variables PORT, MINIFY and SKIN_NAME.
+ *
+ * If PORT and SKIN_NAME variables were not defined, the default values 9001 and
+ * "colibris" would be used.
+ * The configuration value "minify", on the other hand, does not have a
+ * designated default value. Thus, if the environment variable MINIFY were
+ * undefined, "minify" would be null.
+ *
+ * REMARKS:
+ * 1) please note that variable substitution always needs to be quoted.
+ *
+ * "port": 9001, <-- Literal values. When not using
+ * "minify": false substitution, only strings must be
+ * "skinName": "colibris" quoted. Booleans and numbers must not.
+ *
+ * "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable
+ * "minify": "${MINIFY:true}" substitution, put quotes around its name,
+ * "skinName": "${SKIN_NAME}" even if the required value is a number or
+ * a boolean.
+ * Etherpad will take care of rewriting it
+ * to the proper type if necessary.
+ *
+ * "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes
+ * "minify": ${MINIFY} around variable names are missing.
+ * "skinName": ${SKIN_NAME}
+ *
+ * 2) Beware of undefined variables and default values: nulls and empty strings
+ * are different!
+ *
+ * This is particularly important for user's passwords (see the relevant
+ * section):
+ *
+ * "password": "${PASSW}" // if PASSW is not defined would result in password === null
+ * "password": "${PASSW:}" // if PASSW is not defined would result in password === ''
+ *
+ * If you want to use an empty value (null) as default value for a variable,
+ * simply do not set it, without putting any colons: "${ABIWORD}".
+ *
+ * 3) if you want to use newlines in the default value of a string parameter,
+ * use "\n" as usual.
+ *
+ * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2"
+ */
+ {
+ /*
+ * Name your instance!
+ */
+ "title": "Etherpad",
+
+ /*
+ * Pathname of the favicon you want to use. If null, the skin's favicon is
+ * used if one is provided by the skin, otherwise the default Etherpad favicon
+ * is used. If this is a relative path it is interpreted as relative to the
+ * Etherpad root directory.
+ */
+ "favicon": null,
+
+ /*
+ * Skin name.
+ *
+ * Its value has to be an existing directory under src/static/skins.
+ * You can write your own, or use one of the included ones:
+ *
+ * - "no-skin": an empty skin (default). This yields the unmodified,
+ * traditional Etherpad theme.
+ * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to
+ * become the default in Etherpad 2.0
+ */
+ "skinName": "bigbluebutton",
+
+ /*
+ * Skin Variants
+ *
+ * Use the UI skin variants builder at /p/test#skinvariantsbuilder
+ *
+ * For the colibris skin only, you can choose how to render the three main
+ * containers:
+ * - toolbar (top menu with icons)
+ * - editor (containing the text of the pad)
+ * - background (area outside of editor, mostly visible when using page style)
+ *
+ * For each of the 3 containers you can choose 4 color combinations:
+ * super-light, light, dark, super-dark.
+ *
+ * For example, to make the toolbar dark, you will include "dark-toolbar" into
+ * skinVariants.
+ *
+ * You can provide multiple skin variants separated by spaces. Default
+ * skinVariant is "super-light-toolbar super-light-editor light-background".
+ *
+ * For the editor container, you can also make it full width by adding
+ * "full-width-editor" variant (by default editor is rendered as a page, with
+ * a max-width of 900px).
+ */
+ "skinVariants": "",
+
+ /*
+ * IP and port which Etherpad should bind at.
+ *
+ * Binding to a Unix socket is also supported: just use an empty string for
+ * the ip, and put the full path to the socket in the port parameter.
+ *
+ * EXAMPLE USING UNIX SOCKET:
+ * "ip": "", // <-- has to be an empty string
+ * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket
+ */
+ "ip": "0.0.0.0",
+ "port": 9001,
+
+ /*
+ * Option to hide/show the settings.json in admin page.
+ *
+ * Default option is set to true
+ */
+ "showSettingsInAdminPage": true,
+
+ /*
+ * Settings for cleanup of pads
+ */
+ "cleanup": {
+ "enabled": false,
+ "keepRevisions": 5
+ },
+
+ /*
+ * Node native SSL support
+ *
+ * This is disabled by default.
+ * Make sure to have the minimum and correct file access permissions set so
+ * that the Etherpad server can access them
+ */
+
+ /*
+ "ssl" : {
+ "key" : "/path-to-your/epl-server.key",
+ "cert" : "/path-to-your/epl-server.crt",
+ "ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"]
+ },
+ */
+
+ /*
+ * The type of the database.
+ *
+ * You can choose between many DB drivers, for example: dirty, postgres,
+ * sqlite, mysql.
+ *
+ * You shouldn't use "dirty" for for anything else than testing or
+ * development.
+ *
+ *
+ * Database specific settings are dependent on dbType, and go in dbSettings.
+ * Remember that since Etherpad 1.6.0 you can also store this information in
+ * credentials.json.
+ *
+ * For a complete list of the supported drivers, please refer to:
+ * https://www.npmjs.com/package/ueberdb2
+ */
+
+ "dbType": "redis",
+ "dbSettings": {
+ "url": "redis://redis:6379"
+ },
+
+ /*
+ * An Example of MySQL Configuration (commented out).
+ *
+ * See: https://github.com/ether/etherpad-lite/wiki/How-to-use-Etherpad-Lite-with-MySQL
+ */
+
+ /*
+ "dbType" : "redis",
+ "dbSettings" : {
+ "host": "127.0.0.1",
+ "port": 6379,
+ "client_options": {
+ "password": "PASSWORD"
+ }
+ },
+ */
+
+ /*
+ * The default text of a pad: A zero-width-space is used to work around an issue with Etherpad 1.9.1 where empty pads are not being created.
+ * See: https://github.com/ether/etherpad-lite/issues/5787
+ */
+ "defaultPadText" : "\u200b",
+
+ /*
+ * Default Pad behavior.
+ *
+ * Change them if you want to override.
+ */
+ "padOptions": {
+ "noColors": true,
+ "showControls": true,
+ "showChat": false,
+ "showLineNumbers": false,
+ "useMonospaceFont": false,
+ "userName": false,
+ "userColor": false,
+ "rtl": false,
+ "alwaysShowChat": false,
+ "chatAndUsers": false,
+ "lang": "en"
+ },
+
+ /*
+ * Pad Shortcut Keys
+ */
+ "padShortcutEnabled" : {
+ "altF9": true, /* focus on the File Menu and/or editbar */
+ "altC": false, /* focus on the Chat window */
+ "cmdShift2": true, /* shows a gritter popup showing a line author */
+ "delete": true,
+ "return": true,
+ "esc": true, /* in mozilla versions 14-19 avoid reconnecting pad */
+ "cmdS": true, /* save a revision */
+ "tab": true, /* indent */
+ "cmdZ": true, /* undo/redo */
+ "cmdY": true, /* redo */
+ "cmdI": true, /* italic */
+ "cmdB": true, /* bold */
+ "cmdU": true, /* underline */
+ "cmd5": true, /* strike through */
+ "cmdShiftL": true, /* unordered list */
+ "cmdShiftN": true, /* ordered list */
+ "cmdShift1": true, /* ordered list */
+ "cmdShiftC": true, /* clear authorship */
+ "cmdH": true, /* backspace */
+ "ctrlHome": true, /* scroll to top of pad */
+ "pageUp": true,
+ "pageDown": true
+ },
+
+ /*
+ * Enables the use of a different server. We have a different one that syncs changes from the original server.
+ * It is hosted on GitHub and should not be blocked by many firewalls.
+ * https://etherpad.org/ep_infos
+ */
+
+ "updateServer": "https://etherpad.org/ep_infos",
+
+ /*
+ * Should we suppress errors from being visible in the default Pad Text?
+ */
+ "suppressErrorsInPadText": true,
+
+ /*
+ * If this option is enabled, a user must have a session to access pads.
+ * This effectively allows only group pads to be accessed.
+ */
+ "requireSession": true,
+
+ /*
+ * Users may edit pads but not create new ones.
+ *
+ * Pad creation is only via the API.
+ * This applies both to group pads and regular pads.
+ */
+ "editOnly": true,
+
+ /*
+ * If true, all css & js will be minified before sending to the client.
+ *
+ * This will improve the loading performance massively, but makes it difficult
+ * to debug the javascript/css
+ */
+ "minify": true,
+
+ /*
+ * How long may clients use served javascript code (in seconds)?
+ *
+ * Not setting this may cause problems during deployment.
+ * Set to 0 to disable caching.
+ */
+ "maxAge": 21600, // 60 * 60 * 6 = 6 hours
+
+ /*
+ * Absolute path to the Abiword executable.
+ *
+ * Abiword is needed to get advanced import/export features of pads. Setting
+ * it to null disables Abiword and will only allow plain text and HTML
+ * import/exports.
+ */
+ "abiword": null,
+
+ /*
+ * This is the absolute path to the soffice executable.
+ *
+ * LibreOffice can be used in lieu of Abiword to export pads.
+ * Setting it to null disables LibreOffice exporting.
+ */
+ "soffice": "/etherpad-export.sh",
+
+ /*
+ * Allow import of file types other than the supported ones:
+ * txt, doc, docx, rtf, odt, html & htm
+ */
+ "allowUnknownFileEnds": false,
+
+ /*
+ * This setting is used if you require authentication of all users.
+ *
+ * Note: "/admin" always requires authentication.
+ */
+ "requireAuthentication": false,
+
+ /*
+ * Require authorization by a module, or a user with is_admin set, see below.
+ */
+ "requireAuthorization": false,
+
+ /*
+ * When you use NGINX or another proxy/load-balancer set this to true.
+ *
+ * This is especially necessary when the reverse proxy performs SSL
+ * termination, otherwise the cookies will not have the "secure" flag.
+ *
+ * The other effect will be that the logs will contain the real client's IP,
+ * instead of the reverse proxy's IP.
+ */
+ "trustProxy": true,
+
+ /*
+ * Settings controlling the session cookie issued by Etherpad.
+ */
+ "cookie": {
+ /*
+ * How often (in milliseconds) the key used to sign the express_sid cookie
+ * should be rotated. Long rotation intervals reduce signature verification
+ * overhead (because there are fewer historical keys to check) and database
+ * load (fewer historical keys to store, and less frequent queries to
+ * get/update the keys). Short rotation intervals are slightly more secure.
+ *
+ * Multiple Etherpad processes sharing the same database (table) is
+ * supported as long as the clock sync error is significantly less than this
+ * value.
+ *
+ * Key rotation can be disabled (not recommended) by setting this to 0 or
+ * null, or by disabling session expiration (see sessionLifetime).
+ */
+ "keyRotationInterval": 86400000, // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s
+
+ /*
+ * Value of the SameSite cookie property. "Lax" is recommended unless
+ * Etherpad will be embedded in an iframe from another site, in which case
+ * this must be set to "None". Note: "None" will not work (the browser will
+ * not send the cookie to Etherpad) unless https is used to access Etherpad
+ * (either directly or via a reverse proxy with "trustProxy" set to true).
+ *
+ * "Strict" is not recommended because it has few security benefits but
+ * significant usability drawbacks vs. "Lax". See
+ * https://stackoverflow.com/q/41841880 for discussion.
+ */
+ "sameSite": "None",
+
+ /*
+ * How long (in milliseconds) after navigating away from Etherpad before the
+ * user is required to log in again. (The express_sid cookie is set to
+ * expire at time now + sessionLifetime when first created, and its
+ * expiration time is periodically refreshed to a new now + sessionLifetime
+ * value.) If requireAuthentication is false then this value does not really
+ * matter.
+ *
+ * The "best" value depends on your users' usage patterns and the amount of
+ * convenience you desire. A long lifetime is more convenient (users won't
+ * have to log back in as often) but has some drawbacks:
+ * - It increases the amount of state kept in the database.
+ * - It might weaken security somewhat: The cookie expiration is refreshed
+ * indefinitely without consulting authentication or authorization
+ * hooks, so once a user has accessed a pad, the user can continue to
+ * use the pad until the user leaves for longer than sessionLifetime.
+ * - More historical keys (sessionLifetime / keyRotationInterval) must be
+ * checked when verifying signatures.
+ *
+ * Session lifetime can be set to infinity (not recommended) by setting this
+ * to null or 0. Note that if the session does not expire, most browsers
+ * will delete the cookie when the browser exits, but a session record is
+ * kept in the database forever.
+ */
+ "sessionLifetime": 864000000, // = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s
+
+ /*
+ * How long (in milliseconds) before the expiration time of an active user's
+ * session is refreshed (to now + sessionLifetime). This setting affects the
+ * following:
+ * - How often a new session expiration time will be written to the
+ * database.
+ * - How often each user's browser will ping the Etherpad server to
+ * refresh the expiration time of the session cookie.
+ *
+ * High values reduce the load on the database and the load from browsers,
+ * but can shorten the effective session lifetime if Etherpad is restarted
+ * or the user navigates away.
+ *
+ * Automatic session refreshes can be disabled (not recommended) by setting
+ * this to null.
+ */
+ "sessionRefreshInterval": 86400000 // = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s
+ },
+
+ /*
+ * Privacy: disable IP logging
+ */
+ "disableIPlogging": true,
+
+ /*
+ * Time (in seconds) to automatically reconnect pad when a "Force reconnect"
+ * message is shown to user.
+ *
+ * Set to 0 to disable automatic reconnection.
+ */
+ "automaticReconnectionTimeout": 0,
+
+ /*
+ * By default, when caret is moved out of viewport, it scrolls the minimum
+ * height needed to make this line visible.
+ */
+ "scrollWhenFocusLineIsOutOfViewport": {
+
+ /*
+ * Percentage of viewport height to be additionally scrolled.
+ *
+ * E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in
+ * the middle of viewport, when user edits a line above of the
+ * viewport
+ *
+ * Set to 0 to disable extra scrolling
+ */
+ "percentage": {
+ "editionAboveViewport": 0,
+ "editionBelowViewport": 0
+ },
+
+ /*
+ * Time (in milliseconds) used to animate the scroll transition.
+ * Set to 0 to disable animation
+ */
+ "duration": 0,
+
+ /*
+ * Flag to control if it should scroll when user places the caret in the
+ * last line of the viewport
+ */
+ "scrollWhenCaretIsInTheLastLineOfViewport": false,
+
+ /*
+ * Percentage of viewport height to be additionally scrolled when user
+ * presses arrow up in the line of the top of the viewport.
+ *
+ * Set to 0 to let the scroll to be handled as default by Etherpad
+ */
+ "percentageToScrollWhenUserPressesArrowUp": 0
+ },
+
+ /*
+ * User accounts. These accounts are used by:
+ * - default HTTP basic authentication if no plugin handles authentication
+ * - some but not all authentication plugins
+ * - some but not all authorization plugins
+ *
+ * User properties:
+ * - password: The user's password. Some authentication plugins will ignore
+ * this.
+ * - is_admin: true gives access to /admin. Defaults to false. If you do not
+ * uncomment this, /admin will not be available!
+ * - readOnly: If true, this user will not be able to create new pads or
+ * modify existing pads. Defaults to false.
+ * - canCreate: If this is true and readOnly is false, this user can create
+ * new pads. Defaults to true.
+ *
+ * Authentication and authorization plugins may define additional properties.
+ *
+ * WARNING: passwords should not be stored in plaintext in this file.
+ * If you want to mitigate this, please install ep_hash_auth and
+ * follow the section "secure your installation" in README.md
+ */
+
+ /*
+ "users": {
+ "admin": {
+ // 1) "password" can be replaced with "hash" if you install ep_hash_auth
+ // 2) please note that if password is null, the user will not be created
+ "password": "changeme1",
+ "is_admin": true
+ },
+ "user": {
+ // 1) "password" can be replaced with "hash" if you install ep_hash_auth
+ // 2) please note that if password is null, the user will not be created
+ "password": "changeme1",
+ "is_admin": false
+ }
+ },
+ */
+
+ /*
+ * Restrict socket.io transport methods
+ */
+ "socketTransportProtocols" : ["websocket", "polling"],
+
+ "socketIo": {
+ /*
+ * Maximum permitted client message size (in bytes). All messages from
+ * clients that are larger than this will be rejected. Large values make it
+ * possible to paste large amounts of text, and plugins may require a larger
+ * value to work properly, but increasing the value increases susceptibility
+ * to denial of service attacks (malicious clients can exhaust memory).
+ */
+ "maxHttpBufferSize": 50000
+ },
+
+ /*
+ * Allow Load Testing tools to hit the Etherpad Instance.
+ *
+ * WARNING: this will disable security on the instance.
+ */
+ "loadTest": false,
+
+ /**
+ * Disable dump of objects preventing a clean exit
+ */
+ "dumpOnUncleanExit": false,
+
+ /*
+ * Disable indentation on new line when previous line ends with some special
+ * chars (':', '[', '(', '{')
+ */
+
+ /*
+ "indentationOnNewLine": false,
+ */
+
+ "ep_pad_ttl": {
+ "ttl": 86400, // 24 hours
+ "timeout": 30,
+ "interval": 21600 // 6 hours
+ },
+
+ /*
+ * Redis publisher plugin configuration.
+ * npm i git+https://git@github.com/mconf/ep_redis_publisher.git
+ */
+
+ "ep_redis_publisher": {
+ "host": "redis",
+ "port": 6379
+ },
+
+ /*
+ * From Etherpad 1.8.3 onwards, import and export of pads is always rate
+ * limited.
+ *
+ * The default is to allow at most 10 requests per IP in a 90 seconds window.
+ * After that the import/export request is rejected.
+ *
+ * See https://github.com/nfriedly/express-rate-limit for more options
+ */
+ "importExportRateLimiting": {
+ // duration of the rate limit window (milliseconds)
+ "windowMs": 90000,
+
+ // maximum number of requests per IP to allow during the rate limit window
+ "max": 32
+ },
+
+ /*
+ * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported
+ * file is always bounded.
+ *
+ * File size is specified in bytes. Default is 50 MB.
+ */
+ "importMaxFileSize": 52428800, // 50 * 1024 * 1024
+
+ /*
+ The authentication method used by the server.
+ The default value is sso
+ If you want to use the old authentication system, change this to apikey
+ */
+ "authenticationMethod": "apikey",
+
+ /*
+ * From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited
+ *
+ * The default is to allow at most 10 changes per IP in a 1 second window.
+ * After that the change is rejected.
+ *
+ * See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
+ */
+ "commitRateLimiting": {
+ // duration of the rate limit window (seconds)
+ "duration": 1,
+
+ // maximum number of changes per IP to allow during the rate limit window
+ "points": 100
+ },
+
+ /*
+ * Toolbar buttons configuration.
+ *
+ * Uncomment to customize.
+ */
+
+ "toolbar": {
+ "left": [
+ ["bold", "italic", "underline", "strikethrough"],
+ ["orderedlist", "unorderedlist", "undo", "redo"],
+ ["importexport"]
+ ],
+ "right": [[]]
+ },
+
+ /*
+ * Expose Etherpad version in the web interface and in the Server http header.
+ *
+ * Do not enable on production machines.
+ */
+ "exposeVersion": false,
+
+ /*
+ * The log level we are using.
+ *
+ * Valid values: DEBUG, INFO, WARN, ERROR
+ */
+ "loglevel": "INFO",
+
+ /*
+ * The log layout type to use.
+ *
+ * Valid values: basic, colored
+ */
+ "logLayoutType": "colored",
+
+ /* Override any strings found in locale directories */
+ "customLocaleStrings": {
+ "de": {
+ "pad.importExport.import_export": "Export",
+ "pad.toolbar.import_export.title": "Export zu verschiedenen Dateiformaten"
+ },
+ "en-gb": {
+ "pad.importExport.import_export": "Export",
+ "pad.toolbar.import_export.title": "Export to different file formats"
+ },
+ "en": {
+ "pad.importExport.import_export": "Export",
+ "pad.toolbar.import_export.title": "Export to different file formats"
+ },
+ "es": {
+ "pad.importExport.import_export": "Exportar",
+ "pad.toolbar.import_export.title": "Exportar a diferentes formatos de archivos"
+ },
+ "fr": {
+ "pad.importExport.import_export": "Exporter",
+ "pad.toolbar.import_export.title": "Exporter vers un format de fichier différent"
+ },
+ "it": {
+ "pad.importExport.import_export": "Esportazione",
+ "pad.toolbar.import_export.title": "Esporta a diversi formati di file"
+ },
+ "pt-br": {
+ "pad.importExport.import_export": "Exportar",
+ "pad.toolbar.import_export.title": "Exportar para diferentes formatos de arquivo"
+ },
+ "pt": {
+ "pad.importExport.import_export": "Exportar",
+ "pad.toolbar.import_export.title": "Exportar para diferentes formatos de ficheiro"
+ }
+ },
+
+ /* Disable Admin UI tests */
+ "enableAdminUITests": false,
+
+ /*
+ * Enable/Disable case-insensitive pad names.
+ */
+ "lowerCasePadIds": false
+}
\ No newline at end of file
diff --git a/mod/freeswitch/Dockerfile b/mod/freeswitch/Dockerfile
new file mode 100644
index 0000000..0153763
--- /dev/null
+++ b/mod/freeswitch/Dockerfile
@@ -0,0 +1,71 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+COPY --from=freeswitch / /build/freeswitch
+
+# install most recent git version for proper sparse-checkout support
+# https://stackoverflow.com/questions/72223738/failed-to-initialize-sparse-checkout
+RUN echo 'deb https://ppa.launchpadcontent.net/git-core/ppa/ubuntu focal main' > /etc/apt/sources.list.d/git-core-ppa.list && \
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A1715D88E1DF1F24 && \
+ apt-get update && \
+ apt-get install -y git
+
+# get build files for bbb-freeswitch (build/packages-template/bbb-freeswitch-core/)
+COPY --from=build-files / /build/
+
+# mock files expected by build.sh
+RUN mkdir -p /build/bbb-voice-conference/config/freeswitch/conf/ && \
+ touch \
+ /build/opts-build.sh \
+ /build/freeswitch.service.build \
+ /build/bbb-voice-conference/config/freeswitch/conf/a \
+ && \
+ echo "" > /usr/local/bin/fpm
+
+# build freeswitch
+RUN cd /build && ./build.sh
+
+
+# add english sounds
+RUN mkdir -p /build/staging/opt/freeswitch/share/freeswitch && \
+ wget https://ubuntu.bigbluebutton.org/sounds.tar.gz -O sounds.tar.gz && \
+ tar xvfz sounds.tar.gz -C /build/staging/opt/freeswitch/share/freeswitch && \
+ wget https://gitlab.senfcall.de/senfcall-public/mute-and-unmute-sounds/-/archive/master/mute-and-unmute-sounds-master.zip && \
+ unzip mute-and-unmute-sounds-master.zip && \
+ cd mute-and-unmute-sounds-master/sounds && \
+ find . -name "*.wav" -exec /bin/bash -c "sox -v 0.3 {} /tmp/tmp.wav; cp /tmp/tmp.wav /build/staging/opt/freeswitch/share/freeswitch/sounds/en/us/callie/conference/{}" \;
+
+# add bigblugbutton config
+ARG TAG_FS_CONFIG
+COPY --from=fs-config / /build/staging/opt/freeswitch/etc/freeswitch/
+
+# ===============================================
+
+# we are using ubuntu here, because libjpeg8 is required, but not available in debian
+FROM ubuntu:22.04
+RUN apt-get update && \
+ apt-get install -y \
+ xmlstarlet wget iptables curl \
+ libfreetype6 libcurl4 libspeex1 libspeexdsp1 libopus0 libsndfile1 libopusfile0 liblua5.2-0 libjbig0 libldns3 libedit2 libtiff5 libpng16-16 libsqlite3-0 \
+ && \
+# install libopusenc0
+ wget -O /tmp/libopusenc0_0.2.1-1bbb2_amd64.deb https://launchpad.net/~bigbluebutton/+archive/ubuntu/support/+files/libopusenc0_0.2.1-1bbb2_amd64.deb \
+ && dpkg -i /tmp/libopusenc0_0.2.1-1bbb2_amd64.deb \
+ && rm /tmp/libopusenc0_0.2.1-1bbb2_amd64.deb
+
+# add dockerize
+COPY --from=alangecker/bbb-docker-base-java /usr/local/bin/dockerize /usr/local/bin/dockerize
+
+# copy over built freeswitch & config
+COPY --from=builder /build/staging/opt /opt
+COPY --from=builder /build/staging/etc /etc
+
+RUN ldconfig && \
+ ln -s /opt/freeswitch/conf /etc/freeswitch && \
+ groupadd freeswitch && \
+ useradd --home-dir /opt/freeswitch --shell /usr/sbin/nologin -g freeswitch freeswitch
+
+COPY ./entrypoint.sh /entrypoint.sh
+COPY ./conf /etc/freeswitch/
+
+ENTRYPOINT /entrypoint.sh
\ No newline at end of file
diff --git a/mod/freeswitch/conf/autoload_configs/conference.conf.xml.tmpl b/mod/freeswitch/conf/autoload_configs/conference.conf.xml.tmpl
new file mode 100644
index 0000000..1171614
--- /dev/null
+++ b/mod/freeswitch/conf/autoload_configs/conference.conf.xml.tmpl
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{if not (isTrue .Env.DISABLE_SOUND_MUTED) }}
+
+
+ {{end}}
+ {{if not (isTrue .Env.DISABLE_SOUND_ALONE) }}
+
+ {{end}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/freeswitch/conf/autoload_configs/event_socket.conf.xml b/mod/freeswitch/conf/autoload_configs/event_socket.conf.xml
new file mode 100644
index 0000000..6d7d4d7
--- /dev/null
+++ b/mod/freeswitch/conf/autoload_configs/event_socket.conf.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/freeswitch/conf/autoload_configs/modules.conf.xml b/mod/freeswitch/conf/autoload_configs/modules.conf.xml
new file mode 100644
index 0000000..f05aa52
--- /dev/null
+++ b/mod/freeswitch/conf/autoload_configs/modules.conf.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/freeswitch/conf/dialplan/public/dialin.xml b/mod/freeswitch/conf/dialplan/public/dialin.xml
new file mode 100644
index 0000000..02c4ed7
--- /dev/null
+++ b/mod/freeswitch/conf/dialplan/public/dialin.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mod/freeswitch/conf/sip_profiles/external-dialin.xml b/mod/freeswitch/conf/sip_profiles/external-dialin.xml
new file mode 100644
index 0000000..fbe7ca3
--- /dev/null
+++ b/mod/freeswitch/conf/sip_profiles/external-dialin.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/freeswitch/conf/sip_profiles/external.xml b/mod/freeswitch/conf/sip_profiles/external.xml
new file mode 100644
index 0000000..53c9de1
--- /dev/null
+++ b/mod/freeswitch/conf/sip_profiles/external.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/freeswitch/conf/vars.xml.tmpl b/mod/freeswitch/conf/vars.xml.tmpl
new file mode 100644
index 0000000..b86502d
--- /dev/null
+++ b/mod/freeswitch/conf/vars.xml.tmpl
@@ -0,0 +1,453 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/freeswitch/entrypoint.sh b/mod/freeswitch/entrypoint.sh
new file mode 100644
index 0000000..bf6dae1
--- /dev/null
+++ b/mod/freeswitch/entrypoint.sh
@@ -0,0 +1,72 @@
+#!/bin/bash -e
+
+# remove all SIP (port 5060) iptable rules
+iptables -S INPUT | grep "\-\-dport 5060 " | cut -d " " -f 2- | xargs -rL1 iptables -D
+
+# block requests to 5060 (tcp/udp)
+iptables -A INPUT -p tcp --dport 5060 -s 0.0.0.0/0 -j REJECT
+iptables -A INPUT -p udp --dport 5060 -s 0.0.0.0/0 -j REJECT
+
+# allow some IPs
+IFS=',' read -ra ADDR <<< "$SIP_IP_ALLOWLIST"
+for IP in "${ADDR[@]}"; do
+ # process "$i"
+ echo "allow port 5060/udp for $IP"
+ iptables -I INPUT -p udp --dport 5060 -s $IP -j ACCEPT
+done
+
+mkdir -p /var/freeswitch/meetings
+chown -R freeswitch:daemon /var/freeswitch/meetings
+chmod 777 /var/freeswitch/meetings
+chown -R freeswitch:daemon /opt/freeswitch/var
+chown -R freeswitch:daemon /opt/freeswitch/etc
+chmod -R g-rwx,o-rwx /opt/freeswitch/etc
+
+# install freeswitch sounds if missing
+SOUNDS_DIR=/opt/freeswitch/share/freeswitch/sounds
+if [ "$SOUNDS_LANGUAGE" == "en-us-callie" ]; then
+ # default, is already installed
+ echo ""
+elif [ "$SOUNDS_LANGUAGE" == "de-de-daedalus3" ]; then
+ if [ ! -d "$SOUNDS_DIR/de/de/daedalus3" ]; then
+ echo "sounds package for de-de-daedalus3 not installed yet"
+ wget -O /tmp/freeswitch-german-soundfiles.zip https://github.com/Daedalus3/freeswitch-german-soundfiles/archive/master.zip
+ mkdir -p $SOUNDS_DIR/de/de/daedalus3
+ unzip /tmp/freeswitch-german-soundfiles.zip -d /tmp/
+ mv /tmp/freeswitch-german-soundfiles-master $SOUNDS_DIR/de/de/daedalus3/conference
+
+ # symlink other folders
+ for folder in "digits" "ivr" "misc"; do
+ ln -s $SOUNDS_DIR/en/us/callie/$folder $SOUNDS_DIR/de/de/daedalus3/$folder
+ done
+
+ fi
+else
+ if [ ! -f $SOUNDS_DIR/$SOUNDS_LANGUAGE.installed ]; then
+ echo "sounds package for $SOUNDS_LANGUAGE not installed yet"
+
+ # get filename of latest release for this sound package
+ FILENAME=$(curl -s https://files.freeswitch.org/releases/sounds/ | grep -i $SOUNDS_LANGUAGE 2> /dev/null | awk -F'\"' '{print $8}' | grep -E '\-48000-.*\.gz$' | sort -V | tail -n 1)
+
+ if [ "$FILENAME" = "" ]; then
+ echo "Error: could not find sounds for language '$SOUNDS_LANGUAGE'"
+ echo "make sure to specify a value for SOUNDS_LANGUAGE which exists on https://files.freeswitch.org/releases/sounds/"
+ exit 1
+ fi
+ for bitrate in 8000 16000 32000 48000; do
+ URL=https://files.freeswitch.org/releases/sounds/$(echo $FILENAME | sed "s/48000/$bitrate/")
+ wget -O /tmp/sounds.tar.gz $URL
+ tar xvfz /tmp/sounds.tar.gz -C $SOUNDS_DIR
+ done
+
+ touch $SOUNDS_DIR/$SOUNDS_LANGUAGE.installed
+ fi
+fi
+
+
+export SOUNDS_PATH=$SOUNDS_DIR/$(echo "$SOUNDS_LANGUAGE" | sed 's|-|/|g')
+
+dockerize \
+ -template /etc/freeswitch/vars.xml.tmpl:/etc/freeswitch/vars.xml \
+ -template /etc/freeswitch/autoload_configs/conference.conf.xml.tmpl:/etc/freeswitch/autoload_configs/conference.conf.xml \
+ /opt/freeswitch/bin/freeswitch -u freeswitch -g daemon -nonat -nf
diff --git a/mod/fsesl-akka/Dockerfile b/mod/fsesl-akka/Dockerfile
new file mode 100644
index 0000000..8f66f59
--- /dev/null
+++ b/mod/fsesl-akka/Dockerfile
@@ -0,0 +1,30 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+COPY --from=src-common-message / /bbb-common-message
+
+# build bbb-common-message
+RUN cd /bbb-common-message && ./deploy.sh
+
+# ===================================================
+COPY --from=src-fsesl-client / /bbb-fsesl-client
+RUN cd /bbb-fsesl-client && ./deploy.sh
+
+COPY --from=src-fsesl-akka / /source
+
+# compile and unzip bin
+RUN cd /source \
+ && sbt universal:packageBin
+RUN unzip /source/target/universal/bbb-fsesl-akka-0.0.2.zip -d /
+
+# # ===================================================
+
+FROM alangecker/bbb-docker-base-java
+
+COPY --from=builder /bbb-fsesl-akka-0.0.2 /bbb-fsesl-akka
+COPY bbb-fsesl-akka.conf /etc/bigbluebutton/bbb-fsesl-akka.conf.tmpl
+COPY logback.xml /bbb-fsesl-akka/conf/logback.xml
+COPY entrypoint.sh /entrypoint.sh
+
+USER bigbluebutton
+ENTRYPOINT /entrypoint.sh
\ No newline at end of file
diff --git a/mod/fsesl-akka/bbb-fsesl-akka.conf b/mod/fsesl-akka/bbb-fsesl-akka.conf
new file mode 100644
index 0000000..12acb3e
--- /dev/null
+++ b/mod/fsesl-akka/bbb-fsesl-akka.conf
@@ -0,0 +1,18 @@
+// include default config from upstream
+include "/bbb-fsesl-akka/conf/application.conf"
+
+
+freeswitch {
+ esl {
+ host="freeswitch"
+ password="FSESL_PASSWORD"
+ }
+}
+
+redis {
+ host="redis"
+}
+
+http {
+ interface = "0.0.0.0"
+}
\ No newline at end of file
diff --git a/mod/fsesl-akka/entrypoint.sh b/mod/fsesl-akka/entrypoint.sh
new file mode 100644
index 0000000..2000ce3
--- /dev/null
+++ b/mod/fsesl-akka/entrypoint.sh
@@ -0,0 +1,9 @@
+#!/bin/sh -e
+
+TARGET=/etc/bigbluebutton/bbb-fsesl-akka.conf
+
+cp /etc/bigbluebutton/bbb-fsesl-akka.conf.tmpl $TARGET
+sed -i "s/FSESL_PASSWORD/$FSESL_PASSWORD/" $TARGET
+
+cd /bbb-fsesl-akka
+/bbb-fsesl-akka/bin/bbb-fsesl-akka
\ No newline at end of file
diff --git a/mod/fsesl-akka/logback.xml b/mod/fsesl-akka/logback.xml
new file mode 100644
index 0000000..9e587d9
--- /dev/null
+++ b/mod/fsesl-akka/logback.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ %d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"} %-5level %logger{35} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mod/haproxy.cfg b/mod/haproxy.cfg
new file mode 100644
index 0000000..feb3532
--- /dev/null
+++ b/mod/haproxy.cfg
@@ -0,0 +1,80 @@
+global
+ log stdout format raw local0 debug
+
+ maxconn 20480
+ ############# IMPORTANT #################################
+ ## DO NOT SET CHROOT OTHERWISE YOU HAVE TO CHANGE THE ##
+ ## acme-http01-webroot.lua file ##
+ # chroot /jail ##
+ #########################################################
+ lua-load /etc/haproxy/acme-http01-webroot.lua
+ #
+ # SSL options
+ ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
+ ssl-default-bind-options ssl-min-ver TLSv1.2
+ tune.ssl.default-dh-param 4096
+
+
+ # workaround for bug #14 (Cert renewal blocks HAProxy indefinitely with Websocket connections)
+ hard-stop-after 3s
+
+
+# DNS runt-time resolution on backend hosts
+resolvers docker
+ nameserver dns "127.0.0.11:53"
+
+defaults
+ log global
+ mode http
+ timeout connect 5000ms
+ timeout client 50000ms
+ timeout server 50000ms
+ # option forwardfor
+ option httplog
+
+ option dontlognull
+ timeout connect 5000
+ timeout client 50000
+ timeout server 50000
+
+ # never fail on address resolution
+ default-server init-addr last,libc,none
+
+frontend http
+ bind *:80,[::]:80
+ mode http
+ acl url_acme_http01 path_beg /.well-known/acme-challenge/
+ http-request use-service lua.acme-http01 if METH_GET url_acme_http01
+ redirect scheme https code 301 if !{ ssl_fc }
+
+frontend nginx_or_turn
+ bind *:443,:::443 ssl crt /etc/haproxy/certs/ ssl-min-ver TLSv1.2 alpn h2,http/1.1,stun.turn
+ mode tcp
+ option tcplog
+ tcp-request content capture req.payload(0,1) len 1
+ log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq captured_user:%{+X}[capture.req.hdr(0)]"
+ tcp-request inspect-delay 30s
+ # We terminate SSL on haproxy. HTTP2 is a binary protocol. haproxy has to
+ # decide which protocol is spoken. This is negotiated by ALPN.
+ #
+ # Depending on the ALPN value traffic is redirected to either port 82 (HTTP2,
+ # ALPN value h2) or 81 (HTTP 1.0 or HTTP 1.1, ALPN value http/1.1 or no value)
+ # If no ALPN value is set, the first byte is inspected and depending on the
+ # value traffic is sent to either port 81 or coturn.
+ use_backend nginx-http2 if { ssl_fc_alpn h2 }
+ use_backend nginx if { ssl_fc_alpn http/1.1 }
+ use_backend turn if { ssl_fc_alpn stun.turn }
+ use_backend %[capture.req.hdr(0),map_str(/etc/haproxy/protocolmap,turn)]
+ default_backend turn
+
+backend turn
+ mode tcp
+ server localhost webrtc-sfu:3478 check
+
+backend nginx
+ mode tcp
+ server localhost nginx:48081 send-proxy check
+
+backend nginx-http2
+ mode tcp
+ server localhost nginx:48082 send-proxy check
diff --git a/mod/haproxy/Dockerfile b/mod/haproxy/Dockerfile
new file mode 100644
index 0000000..f172a4b
--- /dev/null
+++ b/mod/haproxy/Dockerfile
@@ -0,0 +1,4 @@
+FROM ghcr.io/tomdess/docker-haproxy-certbot:2.8.10
+
+# overwrite bootstrap.sh
+COPY bootstrap.sh /bootstrap.sh
\ No newline at end of file
diff --git a/mod/haproxy/bootstrap.sh b/mod/haproxy/bootstrap.sh
new file mode 100644
index 0000000..c17e9f9
--- /dev/null
+++ b/mod/haproxy/bootstrap.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+set -e
+
+# save container environment variables to use it
+# in cron scripts
+
+declare -p | grep -Ev '^declare -[[:alpha:]]*r' > /container.env
+
+# when used with an IP, we'll also disable certbot
+if [[ "$CERT1" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+ IGNORE_TLS_CERT_ERRORS=true
+fi
+
+if [ "$IGNORE_TLS_CERT_ERRORS" ] && [ "$IGNORE_TLS_CERT_ERRORS" != "false" ]; then
+ # use self signed certificate
+ if [ ! -f /etc/haproxy/certs/haproxy-10.7.7.1.pem ]; then
+ mkdir -p /etc/haproxy/certs
+ # generate self signed certificate
+ openssl req -x509 -nodes -days 700 -newkey rsa:2048 \
+ -keyout /tmp/domain.key -out /tmp/domain.crt \
+ -subj "/C=CA/ST=Quebec/L=Montreal/O=BigBlueButton Development/OU=bbb-docker/CN=10.7.7.1"
+
+ cat /tmp/domain.key /tmp/domain.crt | tee /etc/haproxy/certs/haproxy-10.7.7.1.pem >/dev/null
+ fi
+else
+ # obtain certificates from lets encrypt
+ /certs.sh
+fi
+supervisord -c /etc/supervisord.conf -n
\ No newline at end of file
diff --git a/mod/haproxy/protocolmap b/mod/haproxy/protocolmap
new file mode 100644
index 0000000..0f85dd0
--- /dev/null
+++ b/mod/haproxy/protocolmap
@@ -0,0 +1,52 @@
+a nginx
+b nginx
+c nginx
+d nginx
+e nginx
+f nginx
+g nginx
+h nginx
+i nginx
+j nginx
+k nginx
+l nginx
+m nginx
+n nginx
+o nginx
+p nginx
+q nginx
+r nginx
+s nginx
+t nginx
+u nginx
+v nginx
+w nginx
+x nginx
+y nginx
+z nginx
+A nginx
+B nginx
+C nginx
+D nginx
+E nginx
+F nginx
+G nginx
+H nginx
+I nginx
+J nginx
+K nginx
+L nginx
+M nginx
+N nginx
+O nginx
+P nginx
+Q nginx
+R nginx
+S nginx
+T nginx
+U nginx
+V nginx
+W nginx
+X nginx
+Y nginx
+Z nginx
\ No newline at end of file
diff --git a/mod/html5-dev/Dockerfile b/mod/html5-dev/Dockerfile
new file mode 100644
index 0000000..474410a
--- /dev/null
+++ b/mod/html5-dev/Dockerfile
@@ -0,0 +1,13 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG
+
+
+# use /tmp as home dir as writeable directory for whatever UID we get
+ENV HOME /tmp
+
+# allow all user to access .nvm in root
+RUN chmod 755 /root
+
+WORKDIR /app
+COPY /entrypoint.sh /entrypoint.sh
+ENTRYPOINT /entrypoint.sh
diff --git a/mod/html5-dev/entrypoint.sh b/mod/html5-dev/entrypoint.sh
new file mode 100644
index 0000000..09c1ee1
--- /dev/null
+++ b/mod/html5-dev/entrypoint.sh
@@ -0,0 +1,11 @@
+set -e
+
+# enable nvm
+. /root/.nvm/nvm.sh
+
+if [ -n "$1" ]; then
+ exec "$@"
+else
+ npm install
+ npm start -- --host 0.0.0.0
+fi
\ No newline at end of file
diff --git a/mod/initdb.sh b/mod/initdb.sh
new file mode 100644
index 0000000..fb0560e
--- /dev/null
+++ b/mod/initdb.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+set -e
+set -u
+
+function create_user_and_database() {
+ local database=$1
+ echo " Creating user and database '$database'"
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
+ CREATE DATABASE $database;
+ GRANT ALL PRIVILEGES ON DATABASE $database TO $POSTGRES_USER;
+EOSQL
+}
+
+if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then
+ echo "Multiple database creation requested: $POSTGRES_MULTIPLE_DATABASES"
+ for db in $(echo $POSTGRES_MULTIPLE_DATABASES | tr ',' ' '); do
+ create_user_and_database $db
+ done
+ echo "Multiple databases created"
+fi
\ No newline at end of file
diff --git a/mod/livekit/livekit.yaml b/mod/livekit/livekit.yaml
new file mode 100644
index 0000000..55653f3
--- /dev/null
+++ b/mod/livekit/livekit.yaml
@@ -0,0 +1,15 @@
+port: 7880
+log_level: debug
+# when enabled, LiveKit will expose prometheus metrics on :6789/metrics
+#prometheus_port: 6789
+rtc:
+ port_range_start: 16384
+ port_range_end: 32768
+ use_external_ip: false
+redis:
+ # redis is recommended for production deploys
+ address: redis:6379
+
+keys:
+ # TODO: change keys
+ TEST: TEST
diff --git a/mod/nginx.conf b/mod/nginx.conf
new file mode 100644
index 0000000..d1e9b3d
--- /dev/null
+++ b/mod/nginx.conf
@@ -0,0 +1,33 @@
+user nginx;
+worker_processes auto;
+
+error_log /var/log/nginx/error.log warn;
+pid /var/run/nginx.pid;
+
+worker_rlimit_nofile 20000;
+
+events {
+ worker_connections 10000;
+}
+
+
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ keepalive_timeout 65;
+
+ #gzip on;
+
+ include /etc/nginx/conf.d/*.conf;
+
+}
diff --git a/mod/nginx/Dockerfile b/mod/nginx/Dockerfile
new file mode 100644
index 0000000..dc92c41
--- /dev/null
+++ b/mod/nginx/Dockerfile
@@ -0,0 +1,49 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder-learning-dashboard
+COPY --from=src-learning-dashboard / /bbb-learning-dashboard
+RUN cd /bbb-learning-dashboard && npm ci && npm run build
+
+
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder-playback
+COPY --from=src-playback / /bbb-playback
+RUN cd /bbb-playback && npm install && npm run-script build
+
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder-html5
+COPY --from=src-html5 / /source
+RUN cd /source && CI=true npm ci
+RUN cd /source && DISABLE_ESLINT_PLUGIN=true npm run build-safari && npm run build
+RUN cd /source/dist && \
+ HASH=$(ls | grep -Eo 'bundle\.[a-f0-9]{20}\.js' | head -n 1 | grep -Eo '[a-f0-9]{20}') && \
+ if [ -z "$HASH" ]; then \
+ echo "Bundle hash not found."; \
+ else \
+ for FILE in *.safari.js *.safari.js.map; do \
+ if [[ "$FILE" == *"$HASH"* ]]; then \
+ continue; \
+ fi; \
+ PREFIX="${FILE%%.safari.js*}"; \
+ SUFFIX="${FILE#*.safari.js}"; \
+ NEW_NAME="${PREFIX}.${HASH}.safari.js${SUFFIX}"; \
+ echo "Renaming $FILE → $NEW_NAME"; \
+ mv "$FILE" "$NEW_NAME"; \
+ done; \
+ fi
+
+RUN find /source/dist -name '*.js' -exec gzip -k -f -9 '{}' \; \
+ && find /source/dist -name '*.css' -exec gzip -k -f -9 '{}' \; \
+ && find /source/dist -name '*.wasm' -exec gzip -k -f -9 '{}' \;
+
+RUN sed -i "s/?v=VERSION/?v=$BBB_BUILD_TAG/g" /source/dist/index.html && \
+ sed -i "s/?v=VERSION/?v=$BBB_BUILD_TAG/g" /source/dist/stylesheets/fonts.css
+
+# --------------------
+
+FROM nginx:1.29-alpine
+
+COPY --from=builder-learning-dashboard /bbb-learning-dashboard/build /www/learning-analytics-dashboard/
+COPY --from=builder-playback /bbb-playback/build /www/playback/presentation/2.3
+COPY --from=builder-html5 /source/dist /usr/share/bigbluebutton/html5-client/
+COPY ./bbb /etc/nginx/bbb
+COPY ./bigbluebutton /etc/nginx/conf.d/default.conf
+COPY ./bbb-graphql-client-settings-cache.conf /etc/nginx/conf.d/bbb-graphql-client-settings-cache.conf
+COPY ./nginx.conf /etc/nginx/nginx.conf
diff --git a/mod/nginx/bbb-graphql-client-settings-cache.conf b/mod/nginx/bbb-graphql-client-settings-cache.conf
new file mode 100644
index 0000000..fbea8b7
--- /dev/null
+++ b/mod/nginx/bbb-graphql-client-settings-cache.conf
@@ -0,0 +1 @@
+proxy_cache_path /tmp/hasura-client-settings-cache levels=1:2 keys_zone=client_settings_cache:64m inactive=2880m use_temp_path=off;
\ No newline at end of file
diff --git a/mod/nginx/bbb/bbb-html5.nginx b/mod/nginx/bbb/bbb-html5.nginx
new file mode 100644
index 0000000..fc73a84
--- /dev/null
+++ b/mod/nginx/bbb/bbb-html5.nginx
@@ -0,0 +1,21 @@
+# running in production (static assets)
+location /html5client {
+ gzip_static on;
+ alias /usr/share/bigbluebutton/html5-client/;
+ index index.html;
+ try_files $uri $uri/ =404;
+}
+
+location /html5client/locales {
+ alias /usr/share/bigbluebutton/html5-client/locales;
+ autoindex on;
+ autoindex_format json;
+}
+
+location /html5client/wasm {
+ types {
+ application/wasm wasm;
+ }
+ gzip_static on;
+ alias /usr/share/bigbluebutton/html5-client/wasm;
+}
\ No newline at end of file
diff --git a/mod/nginx/bbb/demo.nginx b/mod/nginx/bbb/demo.nginx
new file mode 100644
index 0000000..8b68775
--- /dev/null
+++ b/mod/nginx/bbb/demo.nginx
@@ -0,0 +1,26 @@
+ # Forward request to /demo to tomcat. This is for
+ # the BigBlueButton api demos.
+ location = /demo/ {
+ return 301 /demo/demo1.jsp;
+ }
+ location /demo {
+ proxy_pass http://host.docker.internal:8001;
+ proxy_redirect default;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ # Allow 30M uploaded presentation document.
+ client_max_body_size 30m;
+ client_body_buffer_size 128k;
+
+ proxy_connect_timeout 90;
+ proxy_send_timeout 90;
+ proxy_read_timeout 90;
+
+ proxy_buffer_size 4k;
+ proxy_buffers 4 32k;
+ proxy_busy_buffers_size 64k;
+ proxy_temp_file_write_size 64k;
+
+ include fastcgi_params;
+ }
+
diff --git a/mod/nginx/bbb/graphql.nginx b/mod/nginx/bbb/graphql.nginx
new file mode 100644
index 0000000..be1f8cd
--- /dev/null
+++ b/mod/nginx/bbb/graphql.nginx
@@ -0,0 +1,71 @@
+# Websocket connection
+location /graphql {
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ proxy_set_header Host $host;
+ #proxy_pass http://bbb-graphql-server:8085; #Hasura (it requires to change the location to /v1/graphql)
+ proxy_pass http://bbb-graphql-middleware:8378; #Graphql Middleware
+}
+
+#DEPRECATED:
+#This endpoint is being replaced by /api/rest/meetingStaticData (which contain clientSettings and more)
+#It will be removed in BBB 3.1
+location /api/rest/clientSettings {
+ auth_request /bigbluebutton/connection/checkGraphqlAuthorization;
+ auth_request_set $meeting_id $sent_http_meeting_id;
+
+ proxy_cache client_settings_cache;
+ proxy_cache_key "$uri|$meeting_id";
+ proxy_cache_use_stale updating;
+ proxy_cache_valid 24h;
+ proxy_cache_lock on;
+ proxy_cache_lock_timeout 5s; # how long other requests may wait for the first one holding the cache lock
+ proxy_cache_lock_age 10s; # consider the lock stale after this time (prevents a stuck lock if upstream hangs)
+ # proxy_cache_background_update on; # optional: serve stale while refreshing the cache in background
+
+ add_header X-Cached $upstream_cache_status;
+
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_connect_timeout 3s; # max time to establish TCP connection to Hasura
+ proxy_send_timeout 15s; # max time to send the request to Hasura
+ proxy_read_timeout 30s; # max time to wait for Hasura’s response
+ proxy_set_header Host $host;
+ proxy_pass http://bbb-graphql-server:8085; #Hasura
+}
+
+#Set cache system for meeting static data
+location /api/rest/meetingStaticData {
+ auth_request /bigbluebutton/connection/checkGraphqlAuthorization;
+ auth_request_set $meeting_id $sent_http_meeting_id;
+
+ proxy_cache client_settings_cache;
+ proxy_cache_key "$uri|$meeting_id";
+ proxy_cache_use_stale updating;
+ proxy_cache_valid 24h;
+ proxy_cache_lock on;
+ proxy_cache_lock_timeout 5s; # how long other requests may wait for the first one holding the cache lock
+ proxy_cache_lock_age 10s; # consider the lock stale after this time (prevents a stuck lock if upstream hangs)
+ # proxy_cache_background_update on; # optional: serve stale while refreshing the cache in background
+
+ add_header X-Cached $upstream_cache_status;
+
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_connect_timeout 3s; # max time to establish TCP connection to Hasura
+ proxy_send_timeout 15s; # max time to send the request to Hasura
+ proxy_read_timeout 30s; # max time to wait for Hasura’s response
+ proxy_set_header Host $host;
+ proxy_pass http://bbb-graphql-server:8085; #Hasura
+}
+
+location /api/rest/userMetadata {
+ auth_request /bigbluebutton/connection/checkGraphqlAuthorization;
+ auth_request_set $meeting_id $sent_http_meeting_id;
+
+ proxy_http_version 1.1;
+ proxy_set_header Connection "";
+ proxy_set_header Host $host;
+ proxy_pass http://bbb-graphql-server:8085; #Hasura
+}
diff --git a/mod/nginx/bbb/learning-dashboard.nginx b/mod/nginx/bbb/learning-dashboard.nginx
new file mode 100644
index 0000000..f0b4fc3
--- /dev/null
+++ b/mod/nginx/bbb/learning-dashboard.nginx
@@ -0,0 +1,4 @@
+location /learning-analytics-dashboard/ {
+ alias /www/learning-analytics-dashboard/;
+ autoindex off;
+}
diff --git a/mod/nginx/bbb/livekit.nginx b/mod/nginx/bbb/livekit.nginx
new file mode 100644
index 0000000..c295562
--- /dev/null
+++ b/mod/nginx/bbb/livekit.nginx
@@ -0,0 +1,11 @@
+location /livekit/ {
+ proxy_pass http://127.0.0.1:7880/;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+
+ proxy_read_timeout 60s;
+ proxy_send_timeout 60s;
+ client_body_timeout 60s;
+ send_timeout 60s;
+}
diff --git a/mod/nginx/bbb/loadbalancer.nginx b/mod/nginx/bbb/loadbalancer.nginx
new file mode 100644
index 0000000..e254118
--- /dev/null
+++ b/mod/nginx/bbb/loadbalancer.nginx
@@ -0,0 +1,4 @@
+# If you run this BBB node behind a proxy loadbalancer set the hostname of
+# the loadbalancer here. This will be used to add CORS headers so requesting
+# slides and API calls won't fail
+set $bbb_loadbalancer_node '';
diff --git a/mod/nginx/bbb/notes-playback.nginx b/mod/nginx/bbb/notes-playback.nginx
new file mode 100644
index 0000000..16f7c43
--- /dev/null
+++ b/mod/nginx/bbb/notes-playback.nginx
@@ -0,0 +1,4 @@
+location /notes {
+ root /var/bigbluebutton/published;
+ index index.html index.htm;
+}
\ No newline at end of file
diff --git a/mod/nginx/bbb/notes.nginx b/mod/nginx/bbb/notes.nginx
new file mode 100644
index 0000000..4965d2d
--- /dev/null
+++ b/mod/nginx/bbb/notes.nginx
@@ -0,0 +1,77 @@
+# https://github.com/ether/etherpad-lite/wiki/How-to-put-Etherpad-Lite-behind-a-reverse-Proxy
+location /pad/p/ {
+ # Avoid setting the user name from the embedded URL
+ if ($arg_userName) {
+ return 401;
+ }
+
+ rewrite /pad/p/(.*) /p/$1 break;
+ rewrite ^/pad/p$ /pad/p/ permanent;
+ proxy_pass http://etherpad:9001/p;
+ proxy_pass_header Server;
+ proxy_redirect /p /pad/p;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+
+ proxy_set_header X-Real-IP $remote_addr; # http://wiki.nginx.org/HttpProxyModule
+ proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
+ proxy_set_header X-Forwarded-Proto $real_scheme; # for EP to set secure cookie flag when https is used
+ proxy_http_version 1.1;
+
+ auth_request /bigbluebutton/connection/checkAuthorization;
+ auth_request_set $auth_status $upstream_status;
+}
+
+location /pad/auth_session {
+ rewrite /pad/auth_session(.*) /auth_session$1 break;
+ proxy_pass http://etherpad:9001/;
+ proxy_pass_header Server;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+ auth_request /bigbluebutton/connection/checkAuthorization;
+ auth_request_set $auth_status $upstream_status;
+}
+
+location /pad {
+ rewrite /pad/(.*) /$1 break;
+ rewrite ^/pad$ /pad/ permanent;
+ proxy_pass http://etherpad:9001/;
+ proxy_pass_header Server;
+ proxy_redirect / /pad/;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+}
+
+location /pad/socket.io/socket.io.js {
+ rewrite /pad/socket.io/socket.io.js /socket.io/socket.io.js break;
+ proxy_pass http://etherpad:9001/;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+}
+
+location /pad/socket.io {
+ rewrite /pad/socket.io/(.*) /socket.io/$1 break;
+ proxy_pass http://etherpad:9001/;
+ proxy_redirect / /pad/;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+ proxy_set_header X-Real-IP $remote_addr; # http://wiki.nginx.org/HttpProxyModule
+ proxy_set_header X-Forwarded-For $remote_addr; # EP logs to show the actual remote IP
+ proxy_set_header X-Forwarded-Proto $real_scheme; # for EP to set secure cookie flag when https is used
+ proxy_set_header Host $host; # pass the host header
+ proxy_http_version 1.1; # recommended with keepalive connections
+ # WebSocket proxying - from http://nginx.org/en/docs/http/websocket.html
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+
+ auth_request /bigbluebutton/connection/checkAuthorization;
+ auth_request_set $auth_status $upstream_status;
+}
+
+location /static {
+ rewrite /static/(.*) /static/$1 break;
+ proxy_pass http://etherpad:9001/;
+ proxy_set_header Host $host;
+ proxy_buffering off;
+}
+
diff --git a/mod/nginx/bbb/playback-video.nginx b/mod/nginx/bbb/playback-video.nginx
new file mode 100644
index 0000000..39d0c68
--- /dev/null
+++ b/mod/nginx/bbb/playback-video.nginx
@@ -0,0 +1,21 @@
+# This file is part of BigBlueButton.
+#
+# Copyright © BigBlueButton Inc. and by respective authors.
+#
+# BigBlueButton is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3.0 of the License, or (at your
+# option) any later version.
+#
+# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with BigBlueButton. If not, see .
+
+location /playback/video/ {
+ alias /var/bigbluebutton/published/video/;
+ index index.html index.htm;
+}
diff --git a/mod/nginx/bbb/podcast.nginx b/mod/nginx/bbb/podcast.nginx
new file mode 100644
index 0000000..7d8c0a8
--- /dev/null
+++ b/mod/nginx/bbb/podcast.nginx
@@ -0,0 +1,22 @@
+#
+# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+#
+# Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+#
+# This program is free software; you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free Software
+# Foundation; either version 3.0 of the License, or (at your option) any later
+# version.
+#
+# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with BigBlueButton; if not, see .
+#
+
+ location /podcast {
+ root /var/bigbluebutton/published;
+ index index.html index.htm;
+ }
\ No newline at end of file
diff --git a/mod/nginx/bbb/presentation-slides.nginx b/mod/nginx/bbb/presentation-slides.nginx
new file mode 100644
index 0000000..d90adeb
--- /dev/null
+++ b/mod/nginx/bbb/presentation-slides.nginx
@@ -0,0 +1,46 @@
+#
+# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+#
+# Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+#
+# This program is free software; you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free Software
+# Foundation; either version 3.0 of the License, or (at your option) any later
+# version.
+#
+# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with BigBlueButton; if not, see .
+#
+
+# Have nginx serve the presentation slides instead of tomcat as large files
+# causes tomcat to OOM. (ralam sept 20, 2018)
+
+ location ~^\/bigbluebutton\/presentation\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/svg\/(?\d+)$ {
+ default_type image/svg+xml;
+ alias /var/bigbluebutton/$meeting_id_2/$meeting_id_2/$pres_id/svgs/slide$page_num.svg;
+ add_header 'Access-Control-Allow-Origin' '*' always;
+ }
+
+ location ~^\/bigbluebutton\/presentation\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/pdf\/(?[A-Za-z0-9]+)\/annotated_slides.pdf$ {
+ default_type application/pdf;
+ alias /var/bigbluebutton/$meeting_id_2/$meeting_id_2/$pres_id/pdfs/$job_id/annotated_slides.pdf;
+ add_header 'Access-Control-Allow-Origin' '*' always;
+ }
+
+ location ~^\/bigbluebutton\/presentation\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/thumbnail\/(?\d+)$ {
+ default_type image/png;
+ alias /var/bigbluebutton/$meeting_id_2/$meeting_id_2/$pres_id/thumbnails/thumb-$page_num.png;
+ add_header 'Access-Control-Allow-Origin' '*' always;
+ }
+
+ location ~^\/bigbluebutton\/presentation\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/(?[A-Za-z0-9\-]+)\/textfiles\/(?\d+)$ {
+ default_type text/plain;
+ alias /var/bigbluebutton/$meeting_id_2/$meeting_id_2/$pres_id/textfiles/slide-$page_num.txt;
+ add_header 'Access-Control-Allow-Origin' '*' always;
+ }
+
+
diff --git a/mod/nginx/bbb/presentation.nginx b/mod/nginx/bbb/presentation.nginx
new file mode 100644
index 0000000..2199332
--- /dev/null
+++ b/mod/nginx/bbb/presentation.nginx
@@ -0,0 +1,28 @@
+#
+# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+#
+# Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+#
+# This program is free software; you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free Software
+# Foundation; either version 3.0 of the License, or (at your option) any later
+# version.
+#
+# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with BigBlueButton; if not, see .
+#
+ location /playback/presentation/2.0/playback.html {
+ return 301 /playback/presentation/2.3/$arg_meetingId?$query_string;
+ }
+ location /playback/presentation/2.3 {
+ try_files $uri /playback/presentation/2.3/index.html;
+ }
+
+ location /presentation {
+ root /var/bigbluebutton/published;
+ index index.html index.htm;
+ }
diff --git a/mod/nginx/bbb/recording-screenshare.nginx b/mod/nginx/bbb/recording-screenshare.nginx
new file mode 100644
index 0000000..d639110
--- /dev/null
+++ b/mod/nginx/bbb/recording-screenshare.nginx
@@ -0,0 +1,22 @@
+#
+# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+#
+# Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+#
+# This program is free software; you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free Software
+# Foundation; either version 3.0 of the License, or (at your option) any later
+# version.
+#
+# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with BigBlueButton; if not, see .
+#
+
+ location /recording/screenshare {
+ alias /var/bigbluebutton/published/screenshare;
+ index index.html index.htm;
+ }
\ No newline at end of file
diff --git a/mod/nginx/bbb/slides.nginx b/mod/nginx/bbb/slides.nginx
new file mode 100644
index 0000000..1c3d170
--- /dev/null
+++ b/mod/nginx/bbb/slides.nginx
@@ -0,0 +1,28 @@
+
+#
+# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+#
+# Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+#
+# This program is free software; you can redistribute it and/or modify it under the
+# terms of the GNU Lesser General Public License as published by the Free Software
+# Foundation; either version 3.0 of the License, or (at your option) any later
+# version.
+#
+# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with BigBlueButton; if not, see .
+#
+ location /playback/slides {
+ root /var/bigbluebutton;
+ index index.html index.htm;
+ }
+
+ location /slides {
+ root /var/bigbluebutton/published;
+ index index.html index.htm;
+ }
+
diff --git a/mod/nginx/bbb/web.nginx b/mod/nginx/bbb/web.nginx
new file mode 100644
index 0000000..d854219
--- /dev/null
+++ b/mod/nginx/bbb/web.nginx
@@ -0,0 +1,186 @@
+ # Handle request to bbb-web running within a SpringBoot Tomcat embedded servlet container. This is for BBB-API and Presentation.
+ location /bigbluebutton {
+ proxy_http_version 1.1;
+
+ location /bigbluebutton {
+ proxy_pass http://bbb-web:8090;
+ proxy_redirect default;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ # Workaround IE refusal to set cookies in iframe
+ add_header P3P 'CP="No P3P policy available"';
+ }
+
+
+ location ~ "^\/bigbluebutton\/presentation\/(?[a-zA-Z0-9_-]+)/upload$" {
+ proxy_pass http://bbb-web:8090;
+ proxy_redirect default;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ # Workaround IE refusal to set cookies in iframe
+ add_header P3P 'CP="No P3P policy available"';
+
+ # high limit for presentation as bbb-web will reject upload if larger than configured
+ client_max_body_size 1000m;
+ client_body_buffer_size 128k;
+
+ proxy_connect_timeout 90;
+ proxy_send_timeout 90;
+ proxy_read_timeout 90;
+
+ proxy_buffer_size 4k;
+ proxy_buffers 4 32k;
+ proxy_busy_buffers_size 64k;
+ proxy_temp_file_write_size 64k;
+
+ include fastcgi_params;
+
+ proxy_request_buffering off;
+
+ # Send a sub-request to allow bbb-web to refuse before loading
+ # If file is larger than configured bbb-web will return with code 403 and Header: x-file-too-large = 1
+ auth_request /bigbluebutton/presentation/checkPresentation;
+ error_page 403 = @error403;
+ auth_request_set $file_too_large_header $upstream_http_x_file_too_large;
+
+ }
+
+ location /bigbluebutton/presentation/download {
+ return 404;
+ }
+
+ location ~ "^/bigbluebutton/presentation/download\/[0-9a-f]+-[0-9]+/[0-9a-f]+-[0-9]+$" {
+ if ($arg_presFilename !~ "^[0-9a-f]+-[0-9]+\.[0-9a-zA-Z]+$") {
+ return 404;
+ }
+ proxy_pass http://bbb-web:8090$uri$is_args$args;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ # Workaround IE refusal to set cookies in iframe
+ add_header P3P 'CP="No P3P policy available"';
+ }
+
+ location = /bigbluebutton/presentation/checkPresentation {
+ proxy_pass http://bbb-web:8090;
+ proxy_redirect default;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ proxy_set_header X-Presentation-Token $prestoken;
+ proxy_set_header X-Original-URI $request_uri;
+ proxy_set_header Content-Length "";
+ proxy_set_header X-Original-Content-Length $http_content_length;
+ proxy_set_header X-Original-Method $request_method;
+
+ # high limit for presentation as bbb-web will reject upload if larger than configured
+ client_max_body_size 1000m;
+ client_body_buffer_size 128k;
+
+ proxy_pass_request_body off;
+ proxy_request_buffering off;
+
+ }
+
+ # To check connection authentication, include:
+ # auth_request /bigbluebutton/connection/checkAuthorization;
+ # auth_request_set $auth_status $upstream_status;
+ #
+ # and make sure to add sessionToken param in the request URI
+ location = /bigbluebutton/connection/checkAuthorization {
+ internal;
+ proxy_pass http://bbb-web:8090;
+ proxy_pass_request_body off;
+ proxy_set_header Content-Length "";
+ proxy_set_header X-Original-URI $request_uri;
+ }
+
+ location = /bigbluebutton/connection/checkGraphqlAuthorization {
+ internal;
+ proxy_pass http://bbb-web:8090;
+ proxy_pass_request_body off;
+ proxy_set_header Content-Length "";
+ proxy_set_header X-Original-URI $request_uri;
+ # this is required for CORS preflight checks in cluster setup
+ proxy_set_header X-Original-Method $request_method;
+ }
+
+ location = /bigbluebutton/connection/legacyCheckAuthorization {
+ internal;
+ proxy_pass http://bbb-web:8090;
+ proxy_pass_request_body off;
+ proxy_set_header Content-Length "";
+ proxy_set_header X-Original-URI $request_uri;
+ }
+
+ location = /bigbluebutton/connection/validatePad {
+ internal;
+ proxy_pass http://bbb-web:8090;
+ proxy_pass_request_body off;
+ proxy_set_header Content-Length "";
+ proxy_set_header X-Original-URI $request_uri;
+ }
+
+ location ~ "^/bigbluebutton\/textTrack\/(?[a-zA-Z0-9]+)\/(?[a-zA-Z0-9_-]+)\/(?.+)$" {
+ # Workaround IE refusal to set cookies in iframe
+ add_header P3P 'CP="No P3P policy available"';
+
+ # Allow 30M uploaded presentation document.
+ client_max_body_size 30m;
+ client_body_buffer_size 128k;
+
+ proxy_connect_timeout 90;
+ proxy_send_timeout 90;
+ proxy_read_timeout 90;
+
+ proxy_buffer_size 4k;
+ proxy_buffers 4 32k;
+ proxy_busy_buffers_size 64k;
+ proxy_temp_file_write_size 64k;
+
+ include fastcgi_params;
+
+ proxy_request_buffering off;
+
+ # Send a sub-request to allow bbb-web to refuse before loading
+ auth_request /bigbluebutton/textTrack/validateAuthToken;
+
+ default_type text/plain;
+ alias /var/bigbluebutton/captions/$recordId/$textTrack;
+
+ }
+
+ location = /bigbluebutton/textTrack/validateAuthToken {
+ internal;
+ proxy_pass http://bbb-web:8090;
+ proxy_redirect default;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+ proxy_set_header X-textTrack-token $textTrackToken;
+ proxy_set_header X-textTrack-recordId $recordId;
+ proxy_set_header X-textTrack-track $textTrack;
+ proxy_set_header X-Original-URI $request_uri;
+ }
+
+ location /bigbluebutton/rtt-check {
+ default_type text/plain;
+ add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
+ add_header Pragma "no-cache";
+ add_header Expires "0";
+ add_header X-Server-Epoch-Msec $msec;
+ add_header X-Request-Id $request_id;
+
+ # this Header is required for cluster setups as the ping check is a
+ # CORS request. No cookies are required so we can just allow anyone
+ # to use this endpoint.
+ add_header 'Access-Control-Allow-Origin' '*';
+ add_header 'Access-Control-Expose-Headers' 'X-Server-Epoch-Msec,X-Request-Id';
+ return 200 "";
+ }
+
+ }
+
+ location @error403 {
+ if ($file_too_large_header = '1') {
+ return 413;
+ }
+
+ return 403;
+ }
diff --git a/mod/nginx/bigbluebutton b/mod/nginx/bigbluebutton
new file mode 100644
index 0000000..a7ff2f0
--- /dev/null
+++ b/mod/nginx/bigbluebutton
@@ -0,0 +1,85 @@
+server {
+ # proxied from HAProxy
+ listen 48082 http2 proxy_protocol;
+ listen 48081 proxy_protocol;
+
+ # optional ports for other reverse proxies
+ listen 48087 default_server;
+ listen [::]:48087 default_server;
+
+ server_name _;
+ access_log /dev/stdout;
+ absolute_redirect off;
+ root /www/;
+
+ # This variable is used instead of $scheme by bigbluebutton nginx include
+ # files, so $scheme can be overridden in reverse-proxy configurations.
+ set $real_scheme $scheme;
+
+ # opt-out of google's floc tracking
+ # https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea
+ add_header Permissions-Policy "interest-cohort=()";
+
+
+ # Include specific rules for record and playback
+ include /etc/nginx/bbb/*.nginx;
+
+ # redirect old greenlight v2 room links
+ location ~ "/b/([a-z0-9\-]+)" {
+ return 302 /rooms/$1;
+ }
+
+ # serve default.pdf from /www/
+ location = /default.pdf {
+ try_files $uri =404;
+ }
+
+ location / {
+ proxy_pass http://greenlight:3000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For "127.0.0.1";
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Forwarded-Ssl on;
+ proxy_http_version 1.1;
+ client_max_body_size 1000m;
+ }
+
+ location /cable {
+ proxy_pass http://greenlight:3000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For "127.0.0.1";
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Forwarded-Ssl on;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ proxy_http_version 1.1;
+ proxy_read_timeout 6h;
+ proxy_send_timeout 6h;
+ client_body_timeout 6h;
+ send_timeout 6h;
+ }
+}
+
+upstream hasura {
+ least_conn;
+ server bbb-graphql-server:8085;
+ # you might want to add more bbb-graphql-server@ instances to balance the
+ # load to multiple bbb-graphql-server instances. Execute
+ # `systemctl enable --now bbb-graphql-server@8086` and uncomment the
+ # following line:
+ # server 127.0.0.1:8086;
+}
+server {
+ listen 8185;
+
+ root /var/www/html;
+
+ location / {
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ proxy_set_header Host $host;
+
+ proxy_pass http://hasura;
+ }
+}
\ No newline at end of file
diff --git a/mod/nginx/default.pdf b/mod/nginx/default.pdf
new file mode 100644
index 0000000..8a23582
Binary files /dev/null and b/mod/nginx/default.pdf differ
diff --git a/mod/periodic/Dockerfile b/mod/periodic/Dockerfile
new file mode 100644
index 0000000..770dcaf
--- /dev/null
+++ b/mod/periodic/Dockerfile
@@ -0,0 +1,10 @@
+FROM debian:bookworm-slim
+
+# -- install docker cli
+COPY --from=library/docker:latest /usr/local/bin/docker /usr/bin/docker
+
+COPY bbb-remove-old-recordings bbb-resync-freeswitch entrypoint.sh /
+
+RUN chmod +x bbb-remove-old-recordings
+
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/mod/periodic/bbb-remove-old-recordings b/mod/periodic/bbb-remove-old-recordings
new file mode 100644
index 0000000..33f6c38
--- /dev/null
+++ b/mod/periodic/bbb-remove-old-recordings
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Source: https://docs.bigbluebutton.org/admin/customize.html#delete-recordings-older-than-n-days
+
+set -e
+LOGFILE=/var/log/bigbluebutton/bbb-recording-cleanup-$(date --iso-8601='seconds' -u).log
+shopt -s nullglob
+NOW=$(date +%s)
+
+echo "$(date --rfc-3339=seconds) Deleting recordings older than ${RECORDING_MAX_AGE_DAYS} days" >"${LOGFILE}"
+
+# Find the name of recordings container in order to access `bbb-record` utility
+BBB_RECORDINGS_CONTAINER_NAME=$(docker ps --filter "name=recordings" --filter "status=running" --format "{{.Names}}")
+if [ $BBB_RECORDINGS_CONTAINER_NAME == "" ]; then
+ echo "$(date --rfc-3339=seconds) ERROR: recordings container is not running" >>"${LOGFILE}"
+ exit 1
+fi
+
+for donefile in /var/bigbluebutton/recording/status/published/*-presentation.done ; do
+ MTIME=$(stat -c %Y "${donefile}")
+ # Check the age of the recording
+ if [ $(( ( $NOW - $MTIME ) / 86400 )) -gt $RECORDING_MAX_AGE_DAYS ]; then
+ MEETING_ID=$(basename "${donefile}")
+ MEETING_ID=${MEETING_ID%-presentation.done}
+ echo "${MEETING_ID}" >> "${LOGFILE}"
+
+ docker exec "$BBB_RECORDINGS_CONTAINER_NAME" bbb-record --delete "${MEETING_ID}" >>"${LOGFILE}"
+ fi
+done
+
+for eventsfile in /var/bigbluebutton/recording/raw/*/events.xml ; do
+ MTIME=$(stat -c %Y "${eventsfile}")
+ # Check the age of the recording
+ if [ $(( ( $NOW - $MTIME ) / 86400 )) -gt $RECORDING_MAX_AGE_DAYS ]; then
+ MEETING_ID="${eventsfile%/events.xml}"
+ MEETING_ID="${MEETING_ID##*/}"
+ echo "${MEETING_ID}" >> "${LOGFILE}"
+
+ docker exec "$BBB_RECORDINGS_CONTAINER_NAME" bbb-record --delete "${MEETING_ID}" >>"${LOGFILE}"
+ fi
+done
diff --git a/mod/periodic/entrypoint.sh b/mod/periodic/entrypoint.sh
new file mode 100644
index 0000000..cc3bbb0
--- /dev/null
+++ b/mod/periodic/entrypoint.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+#
+# How N days back to keep files
+#
+history=5
+
+while :
+do
+
+ # resync freeswitch
+ /bbb-resync-freeswitch
+
+ # delete presentations older than N days
+ find /var/bigbluebutton/ -maxdepth 1 -type d -name "*-[0-9]*" -mtime +$history -exec rm -rf '{}' +
+
+ # delete recordings older than $RECORDING_MAX_AGE_DAYS
+ if [ "$ENABLE_RECORDING" == true ] && [ "$REMOVE_OLD_RECORDING" == true ]; then
+ /bbb-remove-old-recordings
+ fi
+
+ sleep 30m
+done
diff --git a/mod/recordings/Dockerfile b/mod/recordings/Dockerfile
new file mode 100644
index 0000000..cd6fe87
--- /dev/null
+++ b/mod/recordings/Dockerfile
@@ -0,0 +1,126 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+# compile and install mkclean
+RUN cd /tmp \
+ && wget https://sourceforge.net/projects/matroska/files/mkclean/mkclean-0.8.10.tar.bz2/download -O mkclean-0.8.10.tar.bz2 \
+ && tar -xf /tmp/mkclean-0.8.10.tar.bz2 \
+ && cd /tmp/mkclean-0.8.10 \
+ && sed -i 's/\r//g' ./mkclean/configure.compiled \
+ && ./mkclean/configure.compiled \
+ && make -C mkclean \
+ && cp ./release/gcc_linux_x64/mkclean /usr/bin/mkclean \
+ && rm -r /tmp/mkclean-*
+
+
+FROM ruby:3.2-slim-trixie
+
+# install apt dependencies
+RUN apt-get update && apt-get install -y \
+ wget \
+ subversion \
+ rsync \
+ build-essential \
+ libsystemd-dev \
+ python3 \
+ python3-attr \
+ python3-cairo \
+ python3-gi \
+ python3-gi-cairo \
+ python3-lxml \
+ python3-icu \
+ python3-pyinotify \
+ python3-sortedcollections \
+ python3-packaging \
+ gir1.2-pangocairo-1.0 \
+ gir1.2-poppler-0.18 \
+ gir1.2-gtk-3.0 \
+ gir1.2-gdkpixbuf-2.0 \
+ fonts-croscore \
+ ffmpeg \
+ poppler-utils \
+ imagemagick \
+ supervisor \
+ unzip \
+ locales \
+ locales-all
+# TODO: missing packages
+
+ENV LC_ALL en_US.UTF-8
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US.UTF-8
+
+COPY --from=builder /usr/bin/mkclean /usr/bin/mkclean
+
+# add dockerize
+ENV DOCKERIZE_VERSION v0.6.1
+RUN wget -q https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
+ && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
+ && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz
+
+# add yq for bbb-record
+RUN wget -q https://github.com/mikefarah/yq/releases/download/v4.45.1/yq_linux_amd64 -O /usr/bin/yq \
+ && chmod +x /usr/bin/yq
+
+RUN mkdir -p \
+ /usr/local/bigbluebutton \
+ /usr/local/bigbluebutton/core \
+ /etc/bigbluebutton \
+ /etc/bigbluebutton/recording
+
+# dependency for bbb-presentation-video
+RUN wget -q -O /tmp/python3-perfect-freehand.deb https://github.com/bigbluebutton/perfect-freehand-python/releases/download/1.2.0/python3-perfect-freehand_1.2.0_all.deb && \
+ dpkg -i /tmp/python3-perfect-freehand.deb && \
+ rm /tmp/python3-perfect-freehand.deb
+
+ARG TAG_RECORDINGS
+
+COPY --from=record-core / /usr/local/bigbluebutton/core
+
+# add bbb-playback-presentation scripts
+COPY --from=presentation /scripts /usr/local/bigbluebutton/core/scripts/
+
+# install ruby dependencies
+RUN cd /usr/local/bigbluebutton/core \
+ && gem install builder \
+ && gem install bundler -v 2.4.22 --no-document \
+ && bundle config set --local deployment true \
+ && bundle install \
+ && bundle clean \
+ && rm -r vendor/bundle/ruby/*/cache \
+ && find vendor/bundle -name '*.o' -delete
+
+# log to file instead of journald
+RUN sed -i 's|Journald::Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/lib/recordandplayback.rb && \
+ sed -i 's|Journald::Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/scripts/rap-caption-inbox.rb && \
+ sed -i 's|Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/scripts/rap-process-worker.rb && \
+ sed -i 's|Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/scripts/archive/archive.rb && \
+ sed -i 's|Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/scripts/publish/presentation.rb && \
+ sed -i 's|Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/scripts/utils/captions.rb && \
+ sed -i 's|Logger\.new.*|Logger.new("/var/log/bigbluebutton/recording.log")|g' /usr/local/bigbluebutton/core/scripts/process/presentation.rb
+
+# add bbb-record with some adjustments so bbb-record works in this environment
+COPY --from=bbb-conf /bin/bbb-record /usr/bin/bbb-record
+RUN cd /usr/bin \
+ && chmod +x /usr/bin/bbb-record \
+ && sed -i 's/^BBB_WEB.*/BBB_WEB=""/' /usr/bin/bbb-record \
+ && sed -i 's/systemctl.*//' /usr/bin/bbb-record \
+ && echo "BIGBLUEBUTTON_RELEASE=$TAG_RECORDINGS" > /etc/bigbluebutton/bigbluebutton-release
+
+# change owner
+# https://github.com/alangecker/bigbluebutton-docker/issues/63
+RUN chown -R 998:998 /usr/local/bigbluebutton
+
+ARG TAG_BBB_PRESENTATION_VIDEO
+RUN cd /tmp/ && \
+ wget -q -O bbb-presentation-video.zip "https://github.com/bigbluebutton/bbb-presentation-video/releases/download/${TAG_BBB_PRESENTATION_VIDEO}/ubuntu-22.04.zip" && \
+ unzip -o bbb-presentation-video.zip -d bbb-presentation-video && \
+ dpkg -i bbb-presentation-video/bbb-presentation-video*.deb && \
+ rm -rf /tmp/*
+
+COPY bbb-web.properties /etc/bigbluebutton/bbb-web.properties.tmpl
+COPY recording.yml /etc/bigbluebutton/recording/recording.yml.tmpl
+COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
+COPY entrypoint.sh /entrypoint.sh
+
+ENTRYPOINT /entrypoint.sh
diff --git a/mod/recordings/bbb-web.properties b/mod/recordings/bbb-web.properties
new file mode 100644
index 0000000..e891d1c
--- /dev/null
+++ b/mod/recordings/bbb-web.properties
@@ -0,0 +1,2 @@
+bigbluebutton.web.serverURL=https://{{ .Env.DOMAIN }}
+securitySalt={{ .Env.SHARED_SECRET }}
\ No newline at end of file
diff --git a/mod/recordings/entrypoint.sh b/mod/recordings/entrypoint.sh
new file mode 100644
index 0000000..2a70f42
--- /dev/null
+++ b/mod/recordings/entrypoint.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+touch /var/log/bigbluebutton/recording.log
+touch /var/log/bigbluebutton/bbb-web.log
+touch /var/log/bigbluebutton/sanity.log
+touch /var/log/bigbluebutton/post_publish.log
+mkdir -p /var/log/bigbluebutton/presentation
+chown -R 998:998 /var/log/bigbluebutton
+
+dockerize \
+ -template /etc/bigbluebutton/recording/recording.yml.tmpl:/etc/bigbluebutton/recording/recording.yml \
+ -template /etc/bigbluebutton/bbb-web.properties.tmpl:/etc/bigbluebutton/bbb-web.properties \
+ -stdout /var/log/bigbluebutton/recording.log \
+ -stdout /var/log/bigbluebutton/post_publish.log \
+ -stdout /var/log/bigbluebutton/sanity.log \
+ /usr/bin/supervisord --nodaemon
\ No newline at end of file
diff --git a/mod/recordings/recording.yml b/mod/recordings/recording.yml
new file mode 100644
index 0000000..2e79bdf
--- /dev/null
+++ b/mod/recordings/recording.yml
@@ -0,0 +1,4 @@
+redis_host: redis
+notes_endpoint: http://bbb-pads:9002/p
+playback_host: {{ .Env.DOMAIN }}
+playback_protocol: https
diff --git a/mod/recordings/supervisord.conf b/mod/recordings/supervisord.conf
new file mode 100644
index 0000000..168999d
--- /dev/null
+++ b/mod/recordings/supervisord.conf
@@ -0,0 +1,34 @@
+[supervisord]
+user=root
+
+[program:rasque_workers]
+command=bundle exec rake -f Rakefile resque:workers
+directory=/usr/local/bigbluebutton/core/scripts
+environment=QUEUE="rap:archive,rap:publish,rap:process,rap:sanity,rap:captions,rap:events",COUNT="1",HOME="/tmp"
+user=998
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/fd/2
+stderr_logfile_maxbytes=0
+
+
+[program:rap_starter]
+command=bundle exec ruby /usr/local/bigbluebutton/core/scripts/rap-starter.rb
+directory=/usr/local/bigbluebutton/core/scripts
+environment=HOME="/tmp"
+user=998
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/fd/2
+stderr_logfile_maxbytes=0
+
+
+[program:rap_caption_inbox]
+command=bundle exec ruby /usr/local/bigbluebutton/core/scripts/rap-caption-inbox.rb
+directory=/usr/local/bigbluebutton/core/scripts
+environment=HOME="/tmp"
+user=998
+stdout_logfile=/dev/fd/1
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/fd/2
+stderr_logfile_maxbytes=0
diff --git a/mod/webhooks.nginx b/mod/webhooks.nginx
new file mode 100644
index 0000000..e2e3f5f
--- /dev/null
+++ b/mod/webhooks.nginx
@@ -0,0 +1,5 @@
+# Webhooks service is not deployed; return 503 if the endpoint is hit.
+# To enable webhooks, add a webhooks service and restore the proxy_pass block.
+location /bigbluebutton/api/hooks {
+ return 503;
+}
diff --git a/mod/webhooks/Dockerfile b/mod/webhooks/Dockerfile
new file mode 100644
index 0000000..e4b7ce3
--- /dev/null
+++ b/mod/webhooks/Dockerfile
@@ -0,0 +1,25 @@
+FROM node:22-bookworm-slim AS builder
+
+
+RUN apt-get update && apt-get install -y git wget
+
+RUN wget -q https://github.com/mikefarah/yq/releases/download/v4.25.1/yq_linux_amd64 -O /usr/bin/yq \
+ && chmod +x /usr/bin/yq
+
+COPY --from=src / /bbb-webhooks
+RUN cd /bbb-webhooks && npm ci --omit=dev && rm -rf /bbb-webhooks./.git
+
+RUN chmod 777 /bbb-webhooks/config
+# ------------------------------
+
+FROM node:22-bookworm-slim
+RUN useradd --uid 2004 --user-group bbb-webhooks
+
+COPY --from=builder /usr/bin/yq /usr/bin/yq
+COPY --from=builder /bbb-webhooks /bbb-webhooks
+COPY entrypoint.sh /entrypoint.sh
+
+RUN mkdir /bbb-webhooks/log && chmod 777 /bbb-webhooks/log
+USER bbb-webhooks
+ENTRYPOINT /entrypoint.sh
+
diff --git a/mod/webhooks/entrypoint.sh b/mod/webhooks/entrypoint.sh
new file mode 100644
index 0000000..1cd89e0
--- /dev/null
+++ b/mod/webhooks/entrypoint.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -e
+TARGET=/bbb-webhooks/config/production.yml
+cp /bbb-webhooks/config/default.example.yml $TARGET
+
+yq e -i ".hooks.getRaw = false" $TARGET
+yq e -i '.modules."../out/webhooks/index.js".config.getRaw = false' $TARGET
+
+export NODE_ENV=production
+export REDIS_HOST=redis
+export SERVER_DOMAIN=$DOMAIN
+export BEARER_AUTH=true
+export SERVER_BIND_IP=0.0.0.0
+
+cd /bbb-webhooks
+node app.js
+
diff --git a/mod/webrtc-sfu-config.yaml b/mod/webrtc-sfu-config.yaml
new file mode 100644
index 0000000..45c72da
--- /dev/null
+++ b/mod/webrtc-sfu-config.yaml
@@ -0,0 +1,36 @@
+kurento: []
+redisHost: redis
+clientHost: webrtc-sfu
+recordingAdapter: bbb-webrtc-recorder
+
+mcs-host: webrtc-sfu
+mcs-address: webrtc-sfu
+freeswitch:
+ ip: freeswitch
+ sip_ip: freeswitch
+ port: 5066
+ esl_ip: freeswitch
+ esl_port: 8021
+
+log:
+ # trace|debug|info|warn|error
+ level: debug
+ # Whether to log to stdout
+ stdout: true
+ # Whether to log to a file
+ file: false
+
+mediasoup:
+ dedicatedMediaTypeWorkers:
+ audio: auto
+ workerBalancing:
+ strategy: least-loaded
+ worker:
+ # Must match the port range published in compose.yml (24577-24676)
+ rtcMinPort: 24577
+ rtcMaxPort: 24676
+
+ plainRtp:
+ listenIp:
+ ip: "0.0.0.0"
+ announcedIp: "webrtc-sfu"
\ No newline at end of file
diff --git a/mod/webrtc-sfu.nginx b/mod/webrtc-sfu.nginx
new file mode 100644
index 0000000..daa67bc
--- /dev/null
+++ b/mod/webrtc-sfu.nginx
@@ -0,0 +1,25 @@
+location /bbb-webrtc-sfu {
+ auth_request /bigbluebutton/connection/checkAuthorization;
+ auth_request_set $auth_status $upstream_status;
+ # Extra variables are annotated by bbb-web as custom headers
+ auth_request_set $user_id $sent_http_user_id;
+ auth_request_set $meeting_id $sent_http_meeting_id;
+ auth_request_set $voice_bridge $sent_http_voice_bridge;
+ auth_request_set $user_name $sent_http_user_name;
+
+ proxy_pass http://webrtc-sfu:3008;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "Upgrade";
+ # Following custom headers are used by bbb-webrtc-sfu
+ proxy_set_header User-Id $user_id;
+ proxy_set_header Meeting-Id $meeting_id;
+ proxy_set_header Voice-Bridge $voice_bridge;
+ proxy_set_header User-Name $user_name;
+
+ proxy_read_timeout 60s;
+ proxy_send_timeout 60s;
+ client_body_timeout 60s;
+ send_timeout 60s;
+}
+
diff --git a/mod/webrtc-sfu/Dockerfile b/mod/webrtc-sfu/Dockerfile
new file mode 100644
index 0000000..cd2ee00
--- /dev/null
+++ b/mod/webrtc-sfu/Dockerfile
@@ -0,0 +1,42 @@
+ARG BBB_BUILD_TAG
+FROM bigbluebutton/bbb-build:$BBB_BUILD_TAG AS builder
+
+
+RUN useradd --uid 2004 --user-group webrtc-sfu
+
+# cache packages
+COPY --from=source /package.json /cache/package.json
+RUN cd /cache && npm install --unsafe-perm
+
+COPY --from=source / /app
+
+ENV NODE_ENV production
+
+
+RUN cd /app \
+ && rm -rf /app/node_modules && cp -a /cache/node_modules /app/node_modules \
+ && cp config/default.example.yml config/production.yml \
+ && npm install --unsafe-perm \
+ && npm cache clear --force \
+ && rm -rf node_modules/mediasoup/worker/out/Release/subprojects \
+ && rm -rf node_modules/mediasoup/worker/out/Release/mediasoup-worker.p \
+ && rm -rf node_modules/mediasoup/worker/out/Release/deps
+
+
+# =============================
+FROM node:22-bookworm-slim
+RUN useradd --uid 2004 --user-group webrtc-sfu
+ENV NODE_ENV production
+
+COPY --from=builder /app /app
+RUN mkdir /home/webrtc-sfu && chown -R webrtc-sfu:webrtc-sfu /app/config /home/webrtc-sfu
+
+USER webrtc-sfu
+WORKDIR /app
+
+
+COPY config.yaml /etc/bigbluebutton/bbb-webrtc-sfu/production.yml
+ENV NODE_ENV=production
+ENV NODE_CONFIG_DIR=/app/config/:/etc/bigbluebutton/bbb-webrtc-sfu/
+ENV ALLOW_CONFIG_MUTATIONS=true
+CMD [ "npm", "start" ]
diff --git a/mongod.conf b/mongod.conf
deleted file mode 100644
index f791065..0000000
--- a/mongod.conf
+++ /dev/null
@@ -1,33 +0,0 @@
-# mongod.conf
-
-# for documentation of all options, see:
-# http://docs.mongodb.org/manual/reference/configuration-options/
-
-storage:
- dbPath: /data/db
- journal:
- enabled: true
- wiredTiger:
- engineConfig:
- cacheSizeGB: 1
- journalCompressor: none
- directoryForIndexes: true
- collectionConfig:
- blockCompressor: none
- indexConfig:
- prefixCompression: false
-
-
-net:
- port: 27017
- bindIp: 0.0.0.0
-
-
-replication:
- replSetName: rs0
-
-setParameter:
- diagnosticDataCollectionEnabled: false
-
-security:
- javascriptEnabled: false