more updates march

This commit is contained in:
Nathan root
2026-03-01 17:38:47 +00:00
parent ceee62f62c
commit a085ba9714
810 changed files with 27066 additions and 6471 deletions

View File

@@ -0,0 +1,26 @@
server {
listen 80 default_server;
{{ if .Env.ENABLE_IPV6 | default "1" | toBool }}
listen [::]:80 default_server;
{{ end }}
{{ if .Env.ENABLE_HTTP_REDIRECT | default "0" | toBool }}
return 301 https://$host$request_uri;
{{ else }}
include /config/nginx/meet.conf;
{{ end }}
}
{{ if not (.Env.DISABLE_HTTPS | default "0" | toBool) }}
server {
listen 443 ssl http2;
{{ if .Env.ENABLE_IPV6 | default "1" | toBool }}
listen [::]:443 ssl http2;
{{ end }}
include /config/nginx/ssl.conf;
include /config/nginx/meet.conf;
}
{{ end }}

View File

@@ -0,0 +1,8 @@
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS-----

View File

@@ -0,0 +1,242 @@
{{ $ENABLE_COLIBRI_WEBSOCKET := .Env.ENABLE_COLIBRI_WEBSOCKET | default "0" | toBool }}
{{ $COLIBRI_WEBSOCKET_PORT := .Env.COLIBRI_WEBSOCKET_PORT | default "9090" }}
{{ $COLIBRI_WEBSOCKET_REGEX := .Env.COLIBRI_WEBSOCKET_REGEX | default "jvb" }}
{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }}
{{ $ENABLE_LOAD_TEST_CLIENT := .Env.ENABLE_LOAD_TEST_CLIENT | default "0" | toBool }}
{{ $ENABLE_OCTO := .Env.ENABLE_OCTO | default "0" | toBool -}}
{{ $ENABLE_XMPP_WEBSOCKET := .Env.ENABLE_XMPP_WEBSOCKET | default "1" | toBool }}
{{ $ENABLE_SUBDOMAINS := .Env.ENABLE_SUBDOMAINS | default "true" | toBool -}}
{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
{{ $XMPP_BOSH_URL_BASE := .Env.XMPP_BOSH_URL_BASE | default "http://xmpp.meet.jitsi:5280" -}}
{{ $CORS_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN := .Env.CORS_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN | default "*" }}
server_name _;
charset utf8;
client_max_body_size 0;
root /usr/share/jitsi-meet;
# ssi on with javascript for multidomain variables in config.js
ssi on;
ssi_types application/x-javascript application/javascript;
index index.html index.htm;
error_page 404 /static/404.html;
# Security headers
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
set $prefix "";
{{ if .Env.DEPLOYMENTINFO_SHARD }}
add_header X-Jitsi-Shard {{ .Env.DEPLOYMENTINFO_SHARD }};
{{ end }}
# Opt out of FLoC (deprecated)
add_header Permissions-Policy "interest-cohort=()";
include /config/nginx-custom/*.conf;
location = /config.js {
alias /config/config.js;
}
location = /interface_config.js {
alias /config/interface_config.js;
}
location = /external_api.js {
alias /usr/share/jitsi-meet/libs/external_api.min.js;
}
{{ if $ENABLE_JAAS_COMPONENTS }}
location = /_api/room-info {
proxy_pass {{ $XMPP_BOSH_URL_BASE }}/room-info?prefix=$prefix&$args;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
{{ end }}
# ensure all static content can always be found first
location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known|transcripts)/(.*)$ {
add_header 'Access-Control-Allow-Origin' '{{ $CORS_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN }}';
alias /usr/share/jitsi-meet/$1/$2;
# cache all versioned files
if ($arg_v) {
expires 1y;
}
}
{{ if $ENABLE_COLIBRI_WEBSOCKET }}
# colibri (JVB) websockets
location ~ ^/colibri-ws/({{ $COLIBRI_WEBSOCKET_REGEX }})/(.*) {
tcp_nodelay on;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://$1:{{ $COLIBRI_WEBSOCKET_PORT }}/colibri-ws/$1/$2$is_args$args;
}
{{ if $ENABLE_OCTO }}
# colibri (JVB) Relay to Relay websockets
location ~ ^/colibri-relay-ws/([a-zA-Z0-9-\._]+)/(.*) {
tcp_nodelay on;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://$1:{{ $COLIBRI_WEBSOCKET_PORT }}/colibri-relay-ws/$1/$2$is_args$args;
}
{{ end }}
{{ end }}
# BOSH
location = /http-bind {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host {{ $XMPP_DOMAIN }};
proxy_pass {{ $XMPP_BOSH_URL_BASE }}/http-bind?prefix=$prefix&$args;
}
{{ if $ENABLE_XMPP_WEBSOCKET }}
# xmpp websockets
location = /xmpp-websocket {
tcp_nodelay on;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host {{ $XMPP_DOMAIN }};
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass {{ $XMPP_BOSH_URL_BASE }}/xmpp-websocket?prefix=$prefix&$args;
}
{{ end }}
{{ if .Env.ETHERPAD_URL_BASE }}
# Etherpad-lite
location ^~ /etherpad/ {
proxy_buffering off;
proxy_cache_bypass $http_upgrade;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass {{ .Env.ETHERPAD_URL_BASE }}/;
}
{{ end }}
{{ if .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE }}
# whiteboard (excalidraw-backend)
location = /socket.io/ {
proxy_buffering off;
proxy_cache_bypass $http_upgrade;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass {{ .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE }}/socket.io/?$args;
}
{{ end }}
location ~ ^/([^/?&:'"]+)$ {
try_files $uri @root_path;
}
location @root_path {
rewrite ^/(.*)$ / break;
}
{{ if $ENABLE_SUBDOMAINS }}
# Matches /(TENANT)/pwa-worker.js or /(TENANT)/manifest.json to rewrite to / and look for file
location ~ ^/([^/?&:'"]+)/(pwa-worker.js|manifest.json)$ {
set $subdomain "$1.";
set $subdir "$1/";
rewrite ^/([^/?&:'"]+)/(pwa-worker.js|manifest.json)$ /$2;
}
location ~ ^/([^/?&:'"]+)/config.js$ {
set $subdomain "$1.";
set $subdir "$1/";
alias /config/config.js;
}
# BOSH for subdomains
location ~ ^/([^/?&:'"]+)/http-bind {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /http-bind;
}
{{ if $ENABLE_XMPP_WEBSOCKET }}
# websockets for subdomains
location ~ ^/([^/?&:'"]+)/xmpp-websocket {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /xmpp-websocket;
}
{{ end }}
{{ if $ENABLE_JAAS_COMPONENTS }}
location ~ ^/([^/?&:'"]+)/_api/room-info {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /_api/room-info;
}
{{ end }}
{{- if $ENABLE_LOAD_TEST_CLIENT }}
# load test minimal client, uncomment when used
location ~ ^/_load-test/([^/?&:'"]+)$ {
rewrite ^/_load-test/(.*)$ /load-test/index.html break;
}
location ~ ^/_load-test/libs/(.*)$ {
add_header 'Access-Control-Allow-Origin' '{{ $CORS_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN }}';
alias /usr/share/jitsi-meet/load-test/libs/$1;
}
# load-test for subdomains
location ~ ^/([^/?&:'"]+)/_load-test/([^/?&:'"]+)$ {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /load-test/index.html break;
}
# load-test for subdomains
location ~ ^/([^/?&:'"]+)/_load-test/libs/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
alias /usr/share/jitsi-meet/load-test/libs/$2;
}
{{- end }}
# Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
location ~ ^/([^/?&:'"]+)/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";
rewrite ^/([^/?&:'"]+)/(.*)$ /$2;
}
{{ end }}

View File

@@ -0,0 +1,71 @@
user www-data;
worker_processes {{ .Env.NGINX_WORKER_PROCESSES | default "4" }};
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections {{ .Env.NGINX_WORKER_CONNECTIONS | default "768" }};
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout {{ .Env.NGINX_KEEPALIVE_TIMEOUT | default "65" }};
types_hash_max_size 2048;
server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
client_max_body_size 0;
{{ if .Env.NGINX_RESOLVER }}
resolver {{ .Env.NGINX_RESOLVER }};
{{ end -}}
include /etc/nginx/mime.types;
types {
# add support for the wav MIME type that is requried to playback wav files in Firefox.
audio/wav wav;
}
default_type application/octet-stream;
##
# Logging Settings
##
access_log /dev/stdout;
error_log /dev/stderr;
##
# Gzip Settings
##
gzip on;
gzip_types text/plain text/css application/javascript application/json;
gzip_vary on;
gzip_min_length 860;
##
# Connection header for WebSocket reverse proxy
##
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
##
# Virtual Host Configs
##
include /config/nginx/site-confs/*;
}
daemon off;

View File

@@ -0,0 +1,631 @@
{{ $ENABLE_ADAPTIVE_MODE := .Env.ENABLE_ADAPTIVE_MODE | default "true" | toBool -}}
{{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}}
{{ $ENABLE_AUTOMATIC_GAIN_CONTROL := .Env.ENABLE_AUTOMATIC_GAIN_CONTROL | default "true" | toBool -}}
{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}}
{{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}}
{{ $ENABLE_FILE_RECORDING_SHARING := .Env.ENABLE_FILE_RECORDING_SHARING | default "false" | toBool -}}
{{ $ENABLE_NO_AUDIO_DETECTION := .Env.ENABLE_NO_AUDIO_DETECTION | default "true" | toBool -}}
{{ $ENABLE_P2P := .Env.ENABLE_P2P | default "true" | toBool -}}
{{ $ENABLE_PREJOIN_PAGE := .Env.ENABLE_PREJOIN_PAGE | default "true" | toBool -}}
{{ $ENABLE_WELCOME_PAGE := .Env.ENABLE_WELCOME_PAGE | default "true" | toBool -}}
{{ $ENABLE_CLOSE_PAGE := .Env.ENABLE_CLOSE_PAGE | default "false" | toBool -}}
{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "false" | toBool -}}
{{ $ENABLE_SERVICE_RECORDING := .Env.ENABLE_SERVICE_RECORDING | default ($ENABLE_RECORDING | printf "%t") | toBool -}}
{{ $ENABLE_LIVESTREAMING := .Env.ENABLE_LIVESTREAMING | default "false" | toBool -}}
{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK := .Env.ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK | default "https://policies.google.com/privacy" -}}
{{ $ENABLE_LIVESTREAMING_HELP_LINK := .Env.ENABLE_LIVESTREAMING_HELP_LINK | default "https://jitsi.org/live" -}}
{{ $ENABLE_LIVESTREAMING_TERMS_LINK := .Env.ENABLE_LIVESTREAMING_TERMS_LINK | default "https://www.youtube.com/t/terms" -}}
{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING := .Env.ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING | default "^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}" -}}
{{ $ENABLE_REMB := .Env.ENABLE_REMB | default "true" | toBool -}}
{{ $ENABLE_REQUIRE_DISPLAY_NAME := .Env.ENABLE_REQUIRE_DISPLAY_NAME | default "false" | toBool -}}
{{ $ENABLE_SIMULCAST := .Env.ENABLE_SIMULCAST | default "true" | toBool -}}
{{ $ENABLE_STEREO := .Env.ENABLE_STEREO | default "false" | toBool -}}
{{ $ENABLE_OPUS_RED := .Env.ENABLE_OPUS_RED | default "false" | toBool -}}
{{ $ENABLE_TALK_WHILE_MUTED := .Env.ENABLE_TALK_WHILE_MUTED | default "false" | toBool -}}
{{ $ENABLE_TCC := .Env.ENABLE_TCC | default "true" | toBool -}}
{{ $ENABLE_TRANSCRIPTIONS := .Env.ENABLE_TRANSCRIPTIONS | default "false" | toBool -}}
{{ $TRANSLATION_LANGUAGES := .Env.TRANSLATION_LANGUAGES | default "[]" -}}
{{ $TRANSLATION_LANGUAGES_HEAD := .Env.TRANSLATION_LANGUAGES_HEAD | default "['en']" -}}
{{ $USE_APP_LANGUAGE := .Env.USE_APP_LANGUAGE | default "true" | toBool -}}
{{ $PREFERRED_LANGUAGE := .Env.PREFERRED_LANGUAGE | default "en-US" -}}
{{ $DISABLE_START_FOR_ALL := .Env.DISABLE_START_FOR_ALL | default "false" | toBool -}}
{{ $AUTO_CAPTION_ON_RECORD := .Env.AUTO_CAPTION_ON_RECORD | default "false" | toBool -}}
{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }}
{{ $HIDE_PREJOIN_DISPLAY_NAME := .Env.HIDE_PREJOIN_DISPLAY_NAME | default "false" | toBool -}}
{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}}
{{ $RESOLUTION := .Env.RESOLUTION | default "720" -}}
{{ $RESOLUTION_MIN := .Env.RESOLUTION_MIN | default "180" -}}
{{ $RESOLUTION_WIDTH := .Env.RESOLUTION_WIDTH | default "1280" -}}
{{ $RESOLUTION_WIDTH_MIN := .Env.RESOLUTION_WIDTH_MIN | default "320" -}}
{{ $START_AUDIO_ONLY := .Env.START_AUDIO_ONLY | default "false" | toBool -}}
{{ $START_AUDIO_MUTED := .Env.START_AUDIO_MUTED | default 10 -}}
{{ $START_WITH_AUDIO_MUTED := .Env.START_WITH_AUDIO_MUTED | default "false" | toBool -}}
{{ $START_SILENT := .Env.START_SILENT | default "false" | toBool -}}
{{ $DISABLE_AUDIO_LEVELS := .Env.DISABLE_AUDIO_LEVELS | default "false" | toBool -}}
{{ $ENABLE_NOISY_MIC_DETECTION := .Env.ENABLE_NOISY_MIC_DETECTION | default "true" | toBool -}}
{{ $START_VIDEO_MUTED := .Env.START_VIDEO_MUTED | default 10 -}}
{{ $START_WITH_VIDEO_MUTED := .Env.START_WITH_VIDEO_MUTED | default "false" | toBool -}}
{{ $DESKTOP_SHARING_FRAMERATE_AUTO := .Env.DESKTOP_SHARING_FRAMERATE_AUTO | default "true" | toBool -}}
{{ $DESKTOP_SHARING_FRAMERATE_MIN := .Env.DESKTOP_SHARING_FRAMERATE_MIN | default 5 -}}
{{ $DESKTOP_SHARING_FRAMERATE_MAX := .Env.DESKTOP_SHARING_FRAMERATE_MAX | default 5 -}}
{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
{{ $XMPP_HIDDEN_DOMAIN := .Env.XMPP_HIDDEN_DOMAIN | default "hidden.meet.jitsi" -}}
{{ $DISABLE_DEEP_LINKING := .Env.DISABLE_DEEP_LINKING | default "false" | toBool -}}
{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}}
{{ $DISABLE_REACTIONS := .Env.DISABLE_REACTIONS | default "false" | toBool -}}
{{ $DISABLE_REMOTE_VIDEO_MENU := .Env.DISABLE_REMOTE_VIDEO_MENU | default "false" | toBool -}}
{{ $DISABLE_PRIVATE_CHAT:= .Env.DISABLE_PRIVATE_CHAT | default "false" | toBool -}}
{{ $DISABLE_KICKOUT := .Env.DISABLE_KICKOUT | default "false" | toBool -}}
{{ $DISABLE_GRANT_MODERATOR := .Env.DISABLE_GRANT_MODERATOR | default "false" | toBool -}}
{{ $ENABLE_E2EPING := .Env.ENABLE_E2EPING | default "false" | toBool -}}
{{ $DISABLE_LOCAL_RECORDING := .Env.DISABLE_LOCAL_RECORDING | default "false" | toBool -}}
{{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT := .Env.ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT | default "false" | toBool -}}
{{ $ENABLE_LOCAL_RECORDING_SELF_START := .Env.ENABLE_LOCAL_RECORDING_SELF_START | default "false" | toBool -}}
{{ $DISABLE_PROFILE := .Env.DISABLE_PROFILE | default "false" | toBool -}}
{{ $ROOM_PASSWORD_DIGITS := .Env.ROOM_PASSWORD_DIGITS | default "false" -}}
{{ $WHITEBOARD_ENABLED := or (.Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" | toBool) (.Env.WHITEBOARD_COLLAB_SERVER_URL_BASE | default "" | toBool) }}
{{ $CODEC_ORDER_JVB := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
{{ $CODEC_ORDER_JVB_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
{{ $CODEC_ORDER_P2P := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
{{ $CODEC_ORDER_P2P_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
// Video configuration.
//
config.resolution = {{ $RESOLUTION }};
config.constraints = {
video: {
height: { ideal: {{ $RESOLUTION }}, max: {{ $RESOLUTION }}, min: {{ $RESOLUTION_MIN }} },
width: { ideal: {{ $RESOLUTION_WIDTH }}, max: {{ $RESOLUTION_WIDTH }}, min: {{ $RESOLUTION_WIDTH_MIN }}},
}
};
{{ if not $ENABLE_SIMULCAST -}}
config.disableSimulcast = true;
{{ end -}}
config.startVideoMuted = {{ $START_VIDEO_MUTED }};
config.startWithVideoMuted = {{ $START_WITH_VIDEO_MUTED }};
config.flags = {
sourceNameSignaling: true,
sendMultipleVideoStreams: true,
receiveMultipleVideoStreams: true
};
// ScreenShare Configuration.
//
{{ if not $DESKTOP_SHARING_FRAMERATE_AUTO -}}
config.desktopSharingFrameRate = {
min: {{ $DESKTOP_SHARING_FRAMERATE_MIN }},
max: {{ $DESKTOP_SHARING_FRAMERATE_MAX }}
};
{{ end -}}
// Audio configuration.
//
config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }};
config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }};
config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }};
config.disableAGC = {{ not $ENABLE_AUTOMATIC_GAIN_CONTROL }};
config.audioQuality = {
stereo: {{ $ENABLE_STEREO }}
};
{{ if .Env.AUDIO_QUALITY_OPUS_BITRATE -}}
config.audioQuality.opusMaxAverageBitrate = '{{ .Env.AUDIO_QUALITY_OPUS_BITRATE }}';
{{ end -}}
config.startAudioOnly = {{ $START_AUDIO_ONLY }};
config.startAudioMuted = {{ $START_AUDIO_MUTED }};
config.startWithAudioMuted = {{ $START_WITH_AUDIO_MUTED }};
config.startSilent = {{ $START_SILENT }};
config.enableOpusRed = {{ $ENABLE_OPUS_RED }};
config.disableAudioLevels = {{ $DISABLE_AUDIO_LEVELS }};
config.enableNoisyMicDetection = {{ $ENABLE_NOISY_MIC_DETECTION }};
// Peer-to-Peer options.
//
config.p2p = {
enabled: {{ $ENABLE_P2P }},
codecPreferenceOrder: {{ $CODEC_ORDER_P2P }},
mobileCodecPreferenceOrder: {{ $CODEC_ORDER_P2P_MOBILE }}
};
{{ if .Env.P2P_STUN_SERVERS -}}
config.p2p.stunServers = '{{ .Env.P2P_STUN_SERVERS }}'.split(',').map(function (url) { return { urls: 'stun:' + url }; } );
{{ end -}}
// Breakout Rooms
//
config.hideAddRoomButton = {{ $ENABLE_BREAKOUT_ROOMS | not }};
// Etherpad
//
{{ if .Env.ETHERPAD_PUBLIC_URL -}}
config.etherpad_base = '{{ .Env.ETHERPAD_PUBLIC_URL }}';
{{ else if .Env.ETHERPAD_URL_BASE -}}
config.etherpad_base = '{{ $PUBLIC_URL }}/etherpad/p/';
{{ end -}}
// Recording.
//
{{ if or $ENABLE_RECORDING $ENABLE_TRANSCRIPTIONS -}}
config.hiddenDomain = '{{ $XMPP_HIDDEN_DOMAIN }}';
{{ end -}}
{{ if $ENABLE_RECORDING -}}
config.recordingService = {
// Whether to enable file recording or not using the "service" defined by the finalizer in Jibri
enabled: {{ $ENABLE_SERVICE_RECORDING }},
// Whether to show the possibility to share file recording with other people
// (e.g. meeting participants), based on the actual implementation
// on the backend.
sharingEnabled: {{ $ENABLE_FILE_RECORDING_SHARING }}
};
// Live streaming configuration.
config.liveStreaming = {
enabled: {{ $ENABLE_LIVESTREAMING }},
dataPrivacyLink: '{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK }}',
helpLink: '{{ $ENABLE_LIVESTREAMING_HELP_LINK }}',
termsLink: '{{ $ENABLE_LIVESTREAMING_TERMS_LINK }}',
validatorRegExpString: '{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING }}'
};
{{ if .Env.DROPBOX_APPKEY -}}
// Enable the dropbox integration.
config.dropbox = {
appKey: '{{ .Env.DROPBOX_APPKEY }}'
};
{{ if .Env.DROPBOX_REDIRECT_URI -}}
// A URL to redirect the user to, after authenticating
// by default uses:
// 'https://jitsi-meet.example.com/static/oauth.html'
config.dropbox.redirectURI = '{{ .Env.DROPBOX_REDIRECT_URI }}';
{{ end -}}
{{ end -}}
{{ end -}}
// Local recording configuration.
config.localRecording = {
disable: {{ $DISABLE_LOCAL_RECORDING }},
notifyAllParticipants: {{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT }},
disableSelfRecording: {{ $ENABLE_LOCAL_RECORDING_SELF_START }}
};
// Analytics.
//
config.analytics = {};
{{ if .Env.AMPLITUDE_ID -}}
// The Amplitude APP Key:
config.analytics.amplitudeAPPKey = '{{ .Env.AMPLITUDE_ID }}';
{{ end -}}
{{ if .Env.GOOGLE_ANALYTICS_ID -}}
// The Google Analytics Tracking ID:
config.analytics.googleAnalyticsTrackingId = '{{ .Env.GOOGLE_ANALYTICS_ID }}';
{{ end -}}
{{ if .Env.MATOMO_ENDPOINT -}}
// Matomo endpoint:
config.analytics.matomoEndpoint = '{{ .Env.MATOMO_ENDPOINT }}';
{{ end -}}
{{ if .Env.MATOMO_SITE_ID -}}
// Matomo site ID:
config.analytics.matomoSiteID = '{{ .Env.MATOMO_SITE_ID }}';
{{ end -}}
{{ if .Env.ANALYTICS_SCRIPT_URLS -}}
// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS | compact) }}' ];
{{ end -}}
{{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}}
config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS | compact) }}' ];
{{ end -}}
// Dial in/out services.
//
{{ if $ENABLE_JAAS_COMPONENTS }}
config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access';
config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids';
{{ else }}
{{ if .Env.CONFCODE_URL -}}
config.dialInConfCodeUrl = '{{ .Env.CONFCODE_URL }}';
{{ end -}}
{{ if .Env.DIALIN_NUMBERS_URL -}}
config.dialInNumbersUrl = '{{ .Env.DIALIN_NUMBERS_URL }}';
{{ end -}}
{{ end -}}
{{ if .Env.DIALOUT_AUTH_URL -}}
config.dialOutAuthUrl = '{{ .Env.DIALOUT_AUTH_URL }}';
{{ end -}}
{{ if .Env.DIALOUT_CODES_URL -}}
config.dialOutCodesUrl = '{{ .Env.DIALOUT_CODES_URL }}';
{{ end -}}
// Calendar service integration.
//
config.enableCalendarIntegration = {{ $ENABLE_CALENDAR }};
{{ if .Env.GOOGLE_API_APP_CLIENT_ID -}}
config.googleApiApplicationClientID = '{{ .Env.GOOGLE_API_APP_CLIENT_ID }}';
{{ end -}}
{{ if .Env.MICROSOFT_API_APP_CLIENT_ID -}}
config.microsoftApiApplicationClientID = '{{ .Env.MICROSOFT_API_APP_CLIENT_ID }}';
{{ end -}}
// Invitation service.
//
{{ if .Env.INVITE_SERVICE_URL -}}
config.inviteServiceUrl = '{{ .Env.INVITE_SERVICE_URL }}';
{{ end -}}
{{ if .Env.PEOPLE_SEARCH_URL -}}
config.peopleSearchUrl = '{{ .Env.PEOPLE_SEARCH_URL }}';
config.peopleSearchQueryTypes = ['user','conferenceRooms'];
{{ end -}}
// Miscellaneous.
//
// Prejoin page.
config.prejoinConfig = {
enabled: {{ $ENABLE_PREJOIN_PAGE }},
// Hides the participant name editing field in the prejoin screen.
hideDisplayName: {{ $HIDE_PREJOIN_DISPLAY_NAME }}
};
// List of buttons to hide from the extra join options dropdown on prejoin screen.
{{ if .Env.HIDE_PREJOIN_EXTRA_BUTTONS -}}
config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS | compact) }}' ];
{{ end -}}
// Welcome page.
config.welcomePage = {
disabled: {{ not $ENABLE_WELCOME_PAGE }}
};
// Close page.
config.enableClosePage = {{ $ENABLE_CLOSE_PAGE }};
// Default language.
{{ if .Env.DEFAULT_LANGUAGE -}}
config.defaultLanguage = '{{ .Env.DEFAULT_LANGUAGE }}';
{{ end -}}
// Require users to always specify a display name.
config.requireDisplayName = {{ $ENABLE_REQUIRE_DISPLAY_NAME }};
// Chrome extension banner.
{{ if .Env.CHROME_EXTENSION_BANNER_JSON -}}
config.chromeExtensionBanner = {{ .Env.CHROME_EXTENSION_BANNER_JSON }};
{{ end -}}
// Disables profile and the edit of all fields from the profile settings (display name and email)
config.disableProfile = {{ $DISABLE_PROFILE }};
// Room password (false for anything, number for max digits)
{{ if $ENABLE_JAAS_COMPONENTS -}}
config.roomPasswordNumberOfDigits = 10;
{{ else -}}
config.roomPasswordNumberOfDigits = {{ $ROOM_PASSWORD_DIGITS }};
{{ end -}}
// Advanced.
//
{{ if not $ENABLE_REMB -}}
config.enableRemb = false;
{{ end -}}
{{ if not $ENABLE_TCC -}}
config.enableTcc = false;
{{ end -}}
// Transcriptions (subtitles and buttons can be configured in interface_config)
config.transcription = {
enabled: {{ $ENABLE_TRANSCRIPTIONS }},
disableClosedCaptions: {{ not $ENABLE_TRANSCRIPTIONS }},
translationLanguages: {{ $TRANSLATION_LANGUAGES }},
translationLanguagesHead: {{ $TRANSLATION_LANGUAGES_HEAD }},
useAppLanguage: {{ $USE_APP_LANGUAGE }},
preferredLanguage: '{{ $PREFERRED_LANGUAGE }}',
disableStartForAll: {{ $DISABLE_START_FOR_ALL }},
autoCaptionOnRecord: {{ $AUTO_CAPTION_ON_RECORD }},
};
// Dynamic branding
{{ if .Env.DYNAMIC_BRANDING_URL -}}
// External API url used to receive branding specific information.
config.dynamicBrandingUrl = '{{ .Env.DYNAMIC_BRANDING_URL }}';
{{ else if .Env.BRANDING_DATA_URL -}}
config.brandingDataUrl = '{{ .Env.BRANDING_DATA_URL }}';
{{ end -}}
{{ if .Env.TOKEN_AUTH_URL -}}
// Authenticate using external service
config.tokenAuthUrl = '{{ .Env.TOKEN_AUTH_URL }}';
{{ end -}}
// Deployment information.
//
config.deploymentInfo = {};
{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT -}}
config.deploymentInfo.environment = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT }}';
{{ end -}}
{{ if .Env.DEPLOYMENTINFO_SHARD -}}
config.deploymentInfo.shard = '{{ .Env.DEPLOYMENTINFO_SHARD }}';
{{ end -}}
{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE -}}
config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}';
{{ end -}}
{{ if .Env.DEPLOYMENTINFO_REGION -}}
config.deploymentInfo.region = '{{ .Env.DEPLOYMENTINFO_REGION }}';
{{ end -}}
// Deep Linking
config.disableDeepLinking = {{ $DISABLE_DEEP_LINKING }};
// P2P preferred codec
{{ if .Env.P2P_PREFERRED_CODEC -}}
config.p2p.preferredCodec = '{{ .Env.P2P_PREFERRED_CODEC }}';
{{ end -}}
// Video quality settings.
//
config.videoQuality = {};
config.videoQuality.codecPreferenceOrder = {{ $CODEC_ORDER_JVB }};
config.videoQuality.mobileCodecPreferenceOrder = {{ $CODEC_ORDER_JVB_MOBILE }};
config.videoQuality.enableAdaptiveMode = {{ $ENABLE_ADAPTIVE_MODE }};
{{ if .Env.VIDEOQUALITY_PREFERRED_CODEC -}}
config.videoQuality.preferredCodec = '{{ .Env.VIDEOQUALITY_PREFERRED_CODEC }}';
{{ end -}}
config.videoQuality.av1 = {};
{{ if .Env.VIDEOQUALITY_BITRATE_AV1_LOW }}
config.videoQuality.av1.low = {{ .Env.VIDEOQUALITY_BITRATE_AV1_LOW }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }}
config.videoQuality.av1.standard = {{ .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }}
config.videoQuality.av1.high = {{ .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_AV1_FULL }}
config.videoQuality.av1.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_FULL }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }}
config.videoQuality.av1.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }}
config.videoQuality.av1.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }};
{{ end -}}
config.videoQuality.h264 = {};
{{ if .Env.VIDEOQUALITY_BITRATE_H264_LOW }}
config.videoQuality.h264.low = {{ .Env.VIDEOQUALITY_BITRATE_H264_LOW }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }}
config.videoQuality.h264.standard = {{ .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_H264_HIGH }}
config.videoQuality.h264.high = {{ .Env.VIDEOQUALITY_BITRATE_H264_HIGH }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_H264_FULL }}
config.videoQuality.h264.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_FULL }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }}
config.videoQuality.h264.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }}
config.videoQuality.h264.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }};
{{ end -}}
config.videoQuality.vp8 = {};
{{ if .Env.VIDEOQUALITY_BITRATE_VP8_LOW }}
config.videoQuality.vp8.low = {{ .Env.VIDEOQUALITY_BITRATE_VP8_LOW }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }}
config.videoQuality.vp8.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }}
config.videoQuality.vp8.high = {{ .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP8_FULL }}
config.videoQuality.vp8.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_FULL }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }}
config.videoQuality.vp8.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }}
config.videoQuality.vp8.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }};
{{ end -}}
config.videoQuality.vp9 = {};
{{ if .Env.VIDEOQUALITY_BITRATE_VP9_LOW }}
config.videoQuality.vp9.low = {{ .Env.VIDEOQUALITY_BITRATE_VP9_LOW }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }}
config.videoQuality.vp9.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }}
config.videoQuality.vp9.high = {{ .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP9_FULL }}
config.videoQuality.vp9.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_FULL }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }}
config.videoQuality.vp9.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }};
{{ end -}}
{{ if .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }}
config.videoQuality.vp9.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }};
{{ end -}}
// Reactions
config.disableReactions = {{ $DISABLE_REACTIONS }};
// Polls
config.disablePolls = {{ $DISABLE_POLLS }};
// Configure toolbar buttons
{{ if .Env.TOOLBAR_BUTTONS -}}
config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS | compact) }}' ];
{{ end -}}
// Hides the buttons at pre-join screen
{{ if .Env.HIDE_PREMEETING_BUTTONS -}}
config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS | compact) }}' ];
{{ end -}}
// Configure remote participant video menu
config.remoteVideoMenu = {
disabled: {{ $DISABLE_REMOTE_VIDEO_MENU }},
disableKick: {{ $DISABLE_KICKOUT }},
disableGrantModerator: {{ $DISABLE_GRANT_MODERATOR }},
disablePrivateChat: {{ $DISABLE_PRIVATE_CHAT }}
};
// Configure e2eping
config.e2eping = {
enabled: {{ $ENABLE_E2EPING }}
};
{{ if .Env.E2EPING_NUM_REQUESTS -}}
config.e2eping.numRequests = {{ .Env.E2EPING_NUM_REQUESTS }};
{{ end -}}
{{ if .Env.E2EPING_MAX_CONFERENCE_SIZE -}}
config.e2eping.maxConferenceSize = {{ .Env.E2EPING_MAX_CONFERENCE_SIZE }};
{{ end -}}
{{ if .Env.E2EPING_MAX_MESSAGE_PER_SECOND -}}
config.e2eping.maxMessagePerSecond = {{ .Env.E2EPING_MAX_MESSAGE_PER_SECOND }};
{{ end }}
// Settings for the Excalidraw whiteboard integration.
config.whiteboard = {
enabled: {{ $WHITEBOARD_ENABLED }},
{{ if .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL -}}
collabServerBaseUrl: '{{ .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'
{{ else if .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE -}}
collabServerBaseUrl: '{{ $PUBLIC_URL }}'
{{ end -}}
};
// JaaS support: pre-configure image if JAAS_APP_ID was set.
{{ if .Env.JAAS_APP_ID -}}
{{ $JAAS_USE_STAGING := .Env.JAAS_USE_STAGING | default "false" | toBool -}}
{{ $JAAS_DOMAIN := $JAAS_USE_STAGING | ternary "stage.8x8.vc" "8x8.vc" -}}
config.hosts.domain = '{{ $JAAS_DOMAIN }}';
config.hosts.muc = 'conference.{{ .Env.JAAS_APP_ID }}.{{ $JAAS_DOMAIN }}';
config.hosts.focus = 'focus.{{ $JAAS_DOMAIN }}';
config.analytics.rtcstatsEnabled = true;
config.analytics.rtcstatsStoreLogs = true;
config.analytics.rtcstatsUseLegacy = false;
config.analytics.rtcstatsEndpoint = 'wss://rtcstats-server-8x8.jitsi.net/';
config.analytics.rtcstatsPollInterval = 10000;
config.analytics.rtcstatsSendSdp = true;
config.bosh = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/http-bind';
config.websocket = 'wss://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/xmpp-websocket';
config.websocketKeepAliveUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/_unlock';
config.conferenceRequestUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/conference-request/v1';
config.hiddenDomain = 'recorder.{{ $JAAS_DOMAIN }}';
config.hiddenFromRecorderFeatureEnabled = true;
config.enableEmailInStats = true;
config.jaasActuatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-actuator';
config.jaasTokenUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/token-mapping';
config.jaasConferenceCreatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access/conference-creator';
config.webhookProxyUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy';
config.billingCounterUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/billing-counter/v1/connection';
config.brandingDataUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/branding/public/v1/conferences';
config.dialInNumbersUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/access/v1/dids';
config.dialInConfCodeUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access';
config.dialOutAuthUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/phone-authorize';
config.dialOutRegionUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/customer-configs/v1/outbound-destination';
config.peopleSearchUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/directory/search';
config.inviteServiceUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/meeting/invite';
config.recordingSharingUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-recordings/link';
config.peopleSearchQueryTypes = ['user','conferenceRooms'];
config.sipInviteUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/sip-jibri-gateway/jibris/invite';
config.jaasFeedbackMetadataURL = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy/feedback';
{{ if $JAAS_USE_STAGING -}}
config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend-pilot.cloudflare.jitsi.net';
{{ else -}}
config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend.cloudflare.jitsi.net';
{{ end -}}
config.whiteboard.userLimit = 25;
{{ end -}}
// Testing
config.testing = {
enableCodecSelectionAPI: true
};

View File

@@ -0,0 +1,28 @@
# session settings
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# ssl certs
{{ if .Env.ENABLE_LETSENCRYPT | default "0" | toBool }}
ssl_certificate /config/acme-certs/{{ .Env.LETSENCRYPT_DOMAIN }}/fullchain.pem;
ssl_certificate_key /config/acme-certs/{{ .Env.LETSENCRYPT_DOMAIN }}/key.pem;
{{ else }}
ssl_certificate /config/keys/cert.crt;
ssl_certificate_key /config/keys/cert.key;
{{ end }}
# protocols
# Mozilla Guideline v5.6, nginx 1.14.2, OpenSSL 1.1.1d, intermediate configuration, no OCSP
# https://ssl-config.mozilla.org/#server=nginx&version=1.14.2&config=intermediate&openssl=1.1.1d&ocsp=false&guideline=5.6
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Diffie-Hellman parameter for DHE cipher suites
ssl_dhparam /defaults/ffdhe2048.txt;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
{{ if .Env.ENABLE_HSTS | default "1" | toBool }}
add_header Strict-Transport-Security "max-age=63072000" always;
{{ end }}

View File

@@ -0,0 +1,71 @@
{{ $CONFIG_PREFIX := .Env.WEB_CONFIG_PREFIX | default "// Jitsi Meet configuration.\n" -}}
{{ $BOSH_RELATIVE := .Env.BOSH_RELATIVE | default "false" | toBool -}}
{{ $ENABLE_AUTH := .Env.ENABLE_AUTH | default "false" | toBool -}}
{{ $ENABLE_AUTH_DOMAIN := .Env.ENABLE_AUTH_DOMAIN | default "true" | toBool -}}
{{ $ENABLE_GUESTS := .Env.ENABLE_GUESTS | default "false" | toBool -}}
{{ $ENABLE_SUBDOMAINS := .Env.ENABLE_SUBDOMAINS | default "true" | toBool -}}
{{ $ENABLE_XMPP_WEBSOCKET := .Env.ENABLE_XMPP_WEBSOCKET | default "1" | toBool -}}
{{ $PUBLIC_URL_DOMAIN := .Env.PUBLIC_URL | default "https://localhost:8443" | trimPrefix "https://" | trimSuffix "/" -}}
{{ $XMPP_AUTH_DOMAIN := .Env.XMPP_AUTH_DOMAIN | default "auth.meet.jitsi" -}}
{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
{{ $XMPP_GUEST_DOMAIN := .Env.XMPP_GUEST_DOMAIN | default "guest.meet.jitsi" -}}
{{ $XMPP_MUC_DOMAIN := .Env.XMPP_MUC_DOMAIN | default "muc.meet.jitsi" -}}
{{ $XMPP_MUC_DOMAIN_PREFIX := (split "." $XMPP_MUC_DOMAIN)._0 -}}
{{ $JVB_PREFER_SCTP := .Env.JVB_PREFER_SCTP | default "1" | toBool -}}
{{ join "\n" (splitList "\\n" $CONFIG_PREFIX) }}
var config = {};
config.hosts = {};
config.hosts.domain = '{{ $XMPP_DOMAIN }}';
{{ if $ENABLE_SUBDOMAINS -}}
var subdir = '<!--# echo var="subdir" default="" -->';
var subdomain = '<!--# echo var="subdomain" default="" -->';
if (subdir.startsWith('<!--')) {
subdir = '';
}
if (subdomain) {
subdomain = subdomain.substring(0,subdomain.length-1).split('.').join('_').toLowerCase() + '.';
}
config.hosts.muc = '{{ $XMPP_MUC_DOMAIN_PREFIX }}.' + subdomain + '{{ $XMPP_DOMAIN }}';
{{ else -}}
config.hosts.muc = '{{ $XMPP_MUC_DOMAIN }}';
{{ end -}}
{{ if $ENABLE_AUTH -}}
{{ if $ENABLE_GUESTS -}}
// When using authentication, domain for guest users.
config.hosts.anonymousdomain = '{{ $XMPP_GUEST_DOMAIN }}';
{{ end -}}
{{ if $ENABLE_AUTH_DOMAIN -}}
// Domain for authenticated users. Defaults to <domain>.
config.hosts.authdomain = '{{ $XMPP_DOMAIN }}';
{{ end -}}
{{ end -}}
{{ if $BOSH_RELATIVE -}}
{{ if $ENABLE_SUBDOMAINS -}}
config.bosh = '/'+ subdir + 'http-bind';
{{ else -}}
config.bosh = '/http-bind';
{{ end -}}
{{ else -}}
{{ if $ENABLE_SUBDOMAINS -}}
config.bosh = 'https://{{ $PUBLIC_URL_DOMAIN}}/' + subdir + 'http-bind';
{{ else -}}
config.bosh = 'https://{{ $PUBLIC_URL_DOMAIN}}/http-bind';
{{ end -}}
{{ end -}}
{{ if $ENABLE_XMPP_WEBSOCKET -}}
{{ if $ENABLE_SUBDOMAINS -}}
config.websocket = 'wss://{{ $PUBLIC_URL_DOMAIN }}/' + subdir + 'xmpp-websocket';
{{ else -}}
config.websocket = 'wss://{{ $PUBLIC_URL_DOMAIN }}/xmpp-websocket';
{{ end -}}
{{ end -}}
config.bridgeChannel = {
preferSctp: {{ $JVB_PREFER_SCTP }}
};

View File

@@ -0,0 +1,142 @@
#!/usr/bin/with-contenv bash
# make our folders
mkdir -p \
/config/{nginx/site-confs,keys} \
/run \
/var/lib/nginx/tmp/client_body \
/var/tmp/nginx
# generate keys (maybe)
if [[ $DISABLE_HTTPS -ne 1 ]]; then
if [[ $ENABLE_LETSENCRYPT -eq 1 ]]; then
mkdir -p /config/acme.sh
pushd /opt
sh ./acme.sh --install --home /config/acme.sh --accountemail $LETSENCRYPT_EMAIL
popd
STAGING=""
if [[ $LETSENCRYPT_USE_STAGING -eq 1 ]]; then
STAGING="--staging"
fi
ACME_SERVER=""
if [[ ! -z $LETSENCRYPT_ACME_SERVER ]]; then
ACME_SERVER="--set-default-ca --server $LETSENCRYPT_ACME_SERVER"
echo "Using custom ACME server: $LETSENCRYPT_ACME_SERVER"
fi
export LE_WORKING_DIR="/config/acme.sh"
# TODO: move away from standalone mode to webroot mode.
/config/acme.sh/acme.sh \
$STAGING \
$ACME_SERVER \
--issue \
--standalone \
--pre-hook "if [[ -d /var/run/s6/services/nginx ]]; then s6-svc -d /var/run/s6/services/nginx; fi" \
--post-hook "if [[ -d /var/run/s6/services/nginx ]]; then s6-svc -u /var/run/s6/services/nginx; fi" \
-d $LETSENCRYPT_DOMAIN
rc=$?
if [[ $rc -eq 1 ]]; then
echo "Failed to obtain a certificate from the Let's Encrypt CA."
# this tries to get the user's attention and to spare the
# authority's rate limit:
sleep 15
echo "Exiting."
exit 1
fi
if [[ $rc -eq 0 ]]; then
mkdir -p /config/acme-certs/$LETSENCRYPT_DOMAIN
if ! /config/acme.sh/acme.sh \
--install-cert -d $LETSENCRYPT_DOMAIN \
--key-file /config/acme-certs/$LETSENCRYPT_DOMAIN/key.pem \
--fullchain-file /config/acme-certs/$LETSENCRYPT_DOMAIN/fullchain.pem ; then
echo "Failed to install certificate."
# this tries to get the user's attention and to spare the
# authority's rate limit:
sleep 15
echo "Exiting."
exit 1
fi
fi
else
# use self-signed certs
if [[ -f /config/keys/cert.key && -f /config/keys/cert.crt ]]; then
echo "using keys found in /config/keys"
else
echo "generating self-signed keys in /config/keys, you can replace these with your own keys if required"
SUBJECT="/C=US/ST=TX/L=Austin/O=jitsi.org/OU=Jitsi Server/CN=*"
openssl req -new -x509 -days 3650 -nodes -out /config/keys/cert.crt -keyout /config/keys/cert.key -subj "$SUBJECT"
fi
fi
fi
# Detect nameserver for Nginx, if not specified.
if [[ -z "$NGINX_RESOLVER" ]]; then
IP_LIST=""
# Parse IPs in /etc/resolv.conf, taking into account IPv6 addresses need to be
# enclosed in square brackets for the Nginx config file.
while read -r line; do
if [[ $line =~ ^nameserver.* ]]; then
IP=$(echo $line | cut -d" " -f2)
COLONS=$(echo $IP | tr -dc ":" | awk '{ print length '})
if [[ $COLONS -ge 2 ]]; then
IP="[$IP]"
fi
if [[ ! "$IP_LIST" = "" ]]; then
IP_LIST+=" "
fi
IP_LIST+="$IP"
fi
done < <(cat /etc/resolv.conf)
export NGINX_RESOLVER=$IP_LIST
fi
echo "Using Nginx resolver: =$NGINX_RESOLVER="
# colibri-ws settings
COLIBRI_WEBSOCKET_UNSAFE_REGEX="[a-zA-Z0-9-\._]+"
# use custom websocket regex if provided
if [ -z "$COLIBRI_WEBSOCKET_REGEX" ]; then
# default to the previous unsafe behavior only if flag is set
if [[ "$ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX" == "1" ]]; then
export COLIBRI_WEBSOCKET_REGEX="$COLIBRI_WEBSOCKET_UNSAFE_REGEX"
else
# default value to the JVB IP, works in compose and anywhere a dns lookup of the JVB reveals the correct IP for proxying
[ -z "$COLIBRI_WEBSOCKET_JVB_LOOKUP_NAME" ] && export COLIBRI_WEBSOCKET_JVB_LOOKUP_NAME="jvb"
if [[ "$DISABLE_COLIBRI_WEBSOCKET_JVB_LOOKUP" == "1" ]]; then
# otherwise value default to the static value in the template 'jvb'
echo "WARNING: DISABLE_COLIBRI_WEBSOCKET_JVB_LOOKUP is set and no value for COLIBRI_WEBSOCKET_REGEX was provided, using static value 'jvb' for COLIBRI_WEBSOCKET_REGEX"
else
export COLIBRI_WEBSOCKET_REGEX="$(dig +short +search $COLIBRI_WEBSOCKET_JVB_LOOKUP_NAME)"
fi
fi
fi
# maintain backward compatibility with older variable
[ -z "${XMPP_HIDDEN_DOMAIN}" ] && export XMPP_HIDDEN_DOMAIN="$XMPP_RECORDER_DOMAIN"
# copy config files
tpl /defaults/nginx.conf > /config/nginx/nginx.conf
tpl /defaults/meet.conf > /config/nginx/meet.conf
if [[ -f /config/nginx/custom-meet.conf ]]; then
cat /config/nginx/custom-meet.conf >> /config/nginx/meet.conf
fi
tpl /defaults/ssl.conf > /config/nginx/ssl.conf
tpl /defaults/default > /config/nginx/site-confs/default
tpl /defaults/system-config.js > /config/config.js
tpl /defaults/settings-config.js >> /config/config.js
if [[ -f /config/custom-config.js ]]; then
cat /config/custom-config.js >> /config/config.js
fi
cp /defaults/interface_config.js /config/interface_config.js
if [[ -f /config/custom-interface_config.js ]]; then
cat /config/custom-interface_config.js >> /config/interface_config.js
fi

View File

@@ -0,0 +1,9 @@
#!/usr/bin/with-contenv bash
if [[ $DISABLE_HTTPS -ne 1 ]] && [[ $ENABLE_LETSENCRYPT -eq 1 ]]; then
exec cron -f
else
# if cron should not be started,
# prevent s6 from restarting this script again and again
s6-svc -O /var/run/s6/services/cron
fi

View File

@@ -0,0 +1,122 @@
#!/usr/bin/with-contenv bash
set -e
EMAIL=$LETSENCRYPT_EMAIL
DOMAIN=$LETSENCRYPT_DOMAIN
JITSI_INSTALLATION="DOCKER"
JAAS_ENDPOINT="https://account-provisioning.cloudflare.jitsi.net/operations"
CHALLENGE_DIR="/usr/share/jitsi-meet/.well-known"
CHALLENGE_FILE="$CHALLENGE_DIR/jitsi-challenge.txt"
SUPPORT_MSG="Reach out to JaaS support at https://jaas.8x8.vc/#components"
JAAS_ACCOUNT_FILE="/config/jaas-account-created.txt"
function stop_service() {
s6-svc -O /var/run/s6/services/jaas-account
exit 0
}
if [[ $DISABLE_HTTPS -ne 1 ]] && [[ $ENABLE_LETSENCRYPT -eq 1 ]] && [[ $ENABLE_JAAS_COMPONENTS -eq 1 ]] && [[ ! -z $EMAIL ]] && [[ ! -z $DOMAIN ]]; then
if [ -f $JAAS_ACCOUNT_FILE ]; then
echo "JaaS account already exists"
stop_service
fi
KEEP_WAITING=true
RETRIES=0
MAX_TRIES=5
SLEEP_INTERVAL=10
# Waiting for nginx to start before creating the JaaS account
while $KEEP_WAITING; do
s6-svwait -u /var/run/s6/services/nginx
NGINX_RESPONSE=$?
if [ $NGINX_RESPONSE -eq 0 ]; then
echo "Nginx started"
KEEP_WAITING=false
else
RETRIES=$((RETRIES + 1))
if [ $RETRIES -ge $MAX_TRIES ]; then
echo "Nginx did not start, exiting..."
KEEP_WAITING=false
else
echo "Waiting for nginx to start, retrying in $SLEEP_INTERVAL seconds... $RETRIES/$MAX_TRIES"
sleep $SLEEP_INTERVAL
fi
fi
done
create_error=0
create_data=$(curl -s -f -X 'POST' "${JAAS_ENDPOINT}" -H 'Content-Type: application/json' -H 'accept: */*' -d "{ \"domain\": \"${DOMAIN}\", \"email\": \"${EMAIL}\", \"jitsiInstallation\": \"${JITSI_INSTALLATION}\" }") || create_error=$?
if [ ${create_error} -ne 0 ]; then
echo "JaaS account creation failed. Status: ${create_error}, response: ${create_data}"
stop_service
fi
echo "${create_data}"
# Creating the challenge dir
mkdir -p ${CHALLENGE_DIR}
# Creating the challenge file
echo "${create_data}" | jq -r .challenge > ${CHALLENGE_FILE}
op_id=$(echo "${create_data}" | jq -r .operationId)
ready_error=0
ready_data=$(curl -s -f -X 'PUT' "${JAAS_ENDPOINT}/${op_id}/ready") || ready_error=$?
if [ ${ready_error} -ne 0 ]; then
echo "Jitsi domain validation failed. Status: ${ready_error}"
echo "Response: "
echo "${ready_data}" | jq -r
echo "${SUPPORT_MSG}"
echo
stop_service
fi
SLEEP_TIME=0
WAIT_BEFORE_CHECK=5
TIMEOUT=60
echo -n "Creating the JaaS account..."
(while true; do
provisioned_data=$(curl -s -f "${JAAS_ENDPOINT}/${op_id}")
status=$(echo "${provisioned_data}" | jq -r .status)
if [ "${status}" == "PROVISIONED" ]; then
echo ""
echo "=================="
echo ""
echo "A JaaS account was created. Please check your email for more details."
echo ""
echo "=================="
# Creating the jaas-account file
touch ${JAAS_ACCOUNT_FILE}
stop_service
elif [ "${status}" == "FAILED" ]; then
echo ""
echo "=================="
echo ""
echo "JaaS account creation failed:${provisioned_data}"
echo ""
echo "=================="
stop_service
fi
if [ ${SLEEP_TIME} -ge ${TIMEOUT} ]; then
echo ""
echo "=================="
echo ""
echo "Timeout creating the JaaS account. ${SUPPORT_MSG}"
echo ""
echo "=================="
stop_service
fi
echo -n "Waiting for the JaaS account to be created..."
sleep ${WAIT_BEFORE_CHECK}
SLEEP_TIME=$((SLEEP_TIME+WAIT_BEFORE_CHECK))
done)
rm ${CHALLENGE_FILE} || true
fi
stop_service

View File

@@ -0,0 +1,3 @@
#!/usr/bin/with-contenv bash
exec nginx -c /config/nginx/nginx.conf