Pārlūkot izejas kodu

web: build config.js on each boot

Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
Aaron van Meerten 5 gadi atpakaļ
vecāks
revīzija
c149463

+ 62 - 15
docker-compose.yml

@@ -13,32 +13,79 @@ services:
             - ${CONFIG}/web/letsencrypt:/etc/letsencrypt:Z
             - ${CONFIG}/transcripts:/usr/share/jitsi-meet/transcripts:Z
         environment:
-            - ENABLE_AUTH
-            - ENABLE_GUESTS
             - ENABLE_LETSENCRYPT
             - ENABLE_HTTP_REDIRECT
-            - ENABLE_TRANSCRIPTIONS
             - DISABLE_HTTPS
-            - JICOFO_AUTH_USER
             - LETSENCRYPT_DOMAIN
             - LETSENCRYPT_EMAIL
             - PUBLIC_URL
-            - XMPP_DOMAIN
+            - TZ
+            - AMPLITUDE_ID
+            - ANALYTICS_SCRIPT_URLS
+            - ANALYTICS_WHITELISTED_EVENTS
+            - BRIDGE_CHANNEL
+            - CALLSTATS_CUSTOM_SCRIPT_URL
+            - CALLSTATS_ID
+            - CALLSTATS_SECRET
+            - CHROME_EXTENSION_BANNER_JSON
+            - CONFCODE_URL
+            - CONFIG_BOSH_HOST
+            - CONFIG_EXTERNAL_CONNECT
+            - DEPLOYMENTINFO_ENVIRONMENT
+            - DEPLOYMENTINFO_ENVIRONMENT_TYPE
+            - DEPLOYMENTINFO_USERREGION
+            - DIALIN_NUMBERS_URL
+            - DIALOUT_AUTH_URL
+            - DIALOUT_CODES_URL
+            - DROPBOX_APPKEY
+            - DROPBOX_REDIRECT_URI
+            - ENABLE_AUDIO_PROCESSING
+            - ENABLE_AUTH
+            - ENABLE_BRIDGE_CHANNEL
+            - ENABLE_CALENDAR
+            - ENABLE_FILE_RECORDING_SERVICE
+            - ENABLE_FILE_RECORDING_SERVICE_SHARING
+            - ENABLE_GUESTS
+            - ENABLE_IPV6
+            - ENABLE_LIPSYNC
+            - ENABLE_NO_AUDIO_DETECTION
+            - ENABLE_P2P
+            - ENABLE_RECORDING
+            - ENABLE_REMB
+            - ENABLE_REQUIRE_DISPLAY_NAME
+            - ENABLE_SIMULCAST
+            - ENABLE_STATS_ID
+            - ENABLE_STEREO
+            - ENABLE_SUBDOMAINS
+            - ENABLE_TALK_WHILE_MUTED
+            - ENABLE_TCC
+            - ENABLE_TRANSCRIPTIONS
+            - ENABLE_WEBSOCKETS
+            - ETHERPAD_PUBLIC_URL
+            - ETHERPAD_URL_BASE
+            - GOOGLE_ANALYTICS_ID
+            - GOOGLE_API_APP_CLIENT_ID
+            - INVITE_SERVICE_URL
+            - JICOFO_AUTH_USER
+            - MICROSOFT_API_APP_CLIENT_ID
+            - P2P_USE_STUN_TURN
+            - PEOPLE_SEARCH_URL
+            - RESOLUTION
+            - RESOLUTION_MIN
+            - RESOLUTION_WIDTH
+            - RESOLUTION_WIDTH_MIN
+            - START_AUDIO_MUTED
+            - START_BITRATE
+            - START_VIDEO_MUTED
+            - TESTING_CAP_SCREENSHARE_BITRATE
+            - TESTING_OCTO_PROBABILITY
+            - USE_STUN_TURN
             - XMPP_AUTH_DOMAIN
             - XMPP_BOSH_URL_BASE
+            - XMPP_DOMAIN
             - XMPP_GUEST_DOMAIN
             - XMPP_MUC_DOMAIN
             - XMPP_RECORDER_DOMAIN
-            - ETHERPAD_URL_BASE
-            - ETHERPAD_PUBLIC_URL
-            - TZ
-            - JIBRI_BREWERY_MUC
-            - JIBRI_PENDING_TIMEOUT
-            - JIBRI_XMPP_USER
-            - JIBRI_XMPP_PASSWORD
-            - JIBRI_RECORDER_USER
-            - JIBRI_RECORDER_PASSWORD
-            - ENABLE_RECORDING
         networks:
             meet.jitsi:
                 aliases:

+ 270 - 0
web/rootfs/defaults/settings-config.js

@@ -0,0 +1,270 @@
+{{ $DEPLOYMENTINFO_USERREGION := .Env.DEPLOYMENTINFO_USERREGION | default "" -}}
+{{ $BRIDGE_CHANNEL := .Env.BRIDGE_CHANNEL | default "datachannel" -}}
+{{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}}
+{{ $ENABLE_BRIDGE_CHANNEL := .Env.ENABLE_BRIDGE_CHANNEL | default "true" -}}
+{{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}}
+{{ $ENABLE_FILE_RECORDING_SERVICE := .Env.ENABLE_FILE_RECORDING_SERVICE | default "false" | toBool -}}
+{{ $ENABLE_FILE_RECORDING_SERVICE_SHARING := .Env.ENABLE_FILE_RECORDING_SERVICE_SHARING | default "false" | toBool -}}
+{{ $ENABLE_IPV6 := .Env.ENABLE_IPV6 | default "true" | toBool -}}
+{{ $ENABLE_LIPSYNC := .Env.ENABLE_LIPSYNC | default "false" | toBool -}}
+{{ $ENABLE_NO_AUDIO_DETECTION := .Env.ENABLE_NO_AUDIO_DETECTION | default "false" | toBool -}}
+{{ $ENABLE_P2P := .Env.ENABLE_P2P | default "true" | toBool -}}
+{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "false" | toBool -}}
+{{ $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_STATS_ID := .Env.ENABLE_STATS_ID | default "false" | toBool -}}
+{{ $ENABLE_STEREO := .Env.ENABLE_STEREO | 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 -}}
+{{ $P2P_USE_STUN_TURN := .Env.P2P_USE_STUN_TURN | default "true" | toBool -}}
+{{ $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_MUTED := .Env.START_AUDIO_MUTED | default 10 -}}
+{{ $START_VIDEO_MUTED := .Env.START_VIDEO_MUTED | default 10 -}}
+{{ $TESTING_OCTO_PROBABILITY := .Env.TESTING_OCTO_PROBABILITY | default "0" -}}
+{{ $TESTING_CAP_SCREENSHARE_BITRATE := .Env.TESTING_CAP_SCREENSHARE_BITRATE | default "1" -}}
+{{ $USE_STUN_TURN := .Env.USE_STUN_TURN | default "true" | toBool -}}
+{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN -}}
+{{ $XMPP_RECORDER_DOMAIN := .Env.XMPP_RECORDER_DOMAIN -}}
+
+
+// Video configuration.
+//
+
+if (!config.hasOwnProperty('constraints')) config.constraints = {};
+if (!config.constraints.hasOwnProperty('video')) config.constraints.video = {};
+
+config.resolution = {{ $RESOLUTION }};
+config.constraints.video.height = { ideal: {{ $RESOLUTION }}, max: {{ $RESOLUTION }}, min: {{ $RESOLUTION_MIN }} };
+config.constraints.video.width = { ideal: {{ $RESOLUTION_WIDTH }}, max: {{ $RESOLUTION_WIDTH }}, min: {{ $RESOLUTION_WIDTH_MIN }}};
+config.disableSimulcast = {{ not $ENABLE_SIMULCAST }};
+config.startVideoMuted = {{ $START_VIDEO_MUTED }};
+
+{{ if .Env.START_BITRATE -}}
+config.startBitrate = '{{ .Env.START_BITRATE }}';
+{{ end -}}
+
+
+// Audio configuration.
+//
+
+config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }};
+config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }};
+config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }};
+config.stereo = {{ $ENABLE_STEREO }};
+config.startAudioMuted = {{ $START_AUDIO_MUTED }};
+
+
+// Peer-to-Peer options.
+//
+
+if (!config.hasOwnProperty('p2p')) config.p2p = {};
+
+config.p2p.enabled = {{ $ENABLE_P2P }};
+config.p2p.useStunTurn = {{ $P2P_USE_STUN_TURN }};
+
+
+// Etherpad
+//
+
+{{ if .Env.ETHERPAD_PUBLIC_URL -}}
+config.etherpad_base = '{{ .Env.ETHERPAD_PUBLIC_URL }}';
+{{ else if .Env.ETHERPAD_URL_BASE -}}
+config.etherpad_base = '{{.Env.PUBLIC_URL}}/etherpad/p/';
+{{ end -}}
+
+
+// Recording.
+//
+
+{{ if $ENABLE_RECORDING -}}
+
+config.hiddenDomain = '{{ $XMPP_RECORDER_DOMAIN }}';
+
+// Whether to enable file recording or not
+config.fileRecordingsEnabled = true;
+
+// Whether to enable live streaming or not.
+config.liveStreamingEnabled = true;
+
+{{ if .Env.DROPBOX_APPKEY -}}
+// Enable the dropbox integration.
+if (!config.hasOwnProperty('dropbox')) config.dropbox = {};
+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 -}}
+
+{{ if $ENABLE_FILE_RECORDING_SERVICE -}}
+// When integrations like dropbox are enabled only that will be shown,
+// by enabling fileRecordingsServiceEnabled, we show both the integrations
+// and the generic recording service (its configuration and storage type
+// depends on jibri configuration)
+config.fileRecordingsServiceEnabled = true;
+{{ end -}}
+{{ if $ENABLE_FILE_RECORDING_SERVICE_SHARING -}}
+// Whether to show the possibility to share file recording with other people
+// (e.g. meeting participants), based on the actual implementation
+// on the backend.
+config.fileRecordingsServiceSharingEnabled = true;
+{{ end -}}
+{{ end -}}
+
+
+// Analytics.
+//
+
+if (!config.hasOwnProperty('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.ANALYTICS_SCRIPT_URLS -}}
+// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
+config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS) }}' ];
+{{ end -}}
+
+{{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}}
+config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS) }}' ];
+{{ end -}}
+
+{{ if .Env.CALLSTATS_CUSTOM_SCRIPT_URL -}}
+config.callStatsCustomScriptUrl = '{{ .Env.CALLSTATS_CUSTOM_SCRIPT_URL }}';
+{{ end -}}
+
+{{ if .Env.CALLSTATS_ID -}}
+// To enable sending statistics to callstats.io you must provide the
+// Application ID and Secret.
+config.callStatsID = '{{ .Env.CALLSTATS_ID }}';
+{{ end -}}
+
+{{ if .Env.CALLSTATS_ID -}}
+config.callStatsSecret = '{{ .Env.CALLSTATS_SECRET }}';
+{{ end -}}
+
+// Enables callstatsUsername to be reported as statsId and used
+// by callstats as repoted remote id.
+config.enableStatsID = {{ $ENABLE_STATS_ID }};
+
+
+// Dial in/out services.
+//
+
+{{ if .Env.CONFCODE_URL -}}
+config.dialInConfCodeUrl = '{{ .Env.CONFCODE_URL }}';
+{{ end -}}
+
+{{ if .Env.DIALIN_NUMBERS_URL -}}
+config.dialInNumbersUrl = '{{ .Env.DIALIN_NUMBERS_URL }}';
+{{ 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.
+//
+
+// 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 -}}
+
+
+// Advanced.
+//
+
+// Lipsync hack in jicofo, may not be safe.
+config.enableLipSync = {{ $ENABLE_LIPSYNC }};
+
+config.enableRemb = {{ $ENABLE_REMB }};
+config.enableTcc = {{ $ENABLE_TCC }};
+
+config.openBridgeChannel = '{{ $ENABLE_BRIDGE_CHANNEL }}';
+
+// Enable IPv6 support.
+config.useIPv6 = {{ $ENABLE_IPV6 }};
+
+// Use XEP-0215 to fetch STUN and TURN servers.
+config.useStunTurn = {{ $USE_STUN_TURN }};
+
+// Transcriptions (subtitles and buttons can be configured in interface_config)
+config.transcribingEnabled = {{ $ENABLE_TRANSCRIPTIONS }};
+
+
+// Deployment information.
+//
+
+if (!config.hasOwnProperty('deploymentInfo')) config.deploymentInfo = {};
+
+{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT -}}
+config.deploymentInfo.environment = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT }}';
+{{ end -}}
+
+{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE -}}
+config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}';
+{{ end -}}
+
+{{ if $DEPLOYMENTINFO_USERREGION -}}
+config.deploymentInfo.userRegion = '{{ $DEPLOYMENTINFO_USERREGION }}';
+{{ end -}}
+
+
+// Testing
+//
+
+if (!config.hasOwnProperty('testing')) config.testing = {};
+if (!config.testing.hasOwnProperty('octo')) config.testing.octo = {};
+
+config.testing.capScreenshareBitrate = {{ $TESTING_CAP_SCREENSHARE_BITRATE }};
+config.testing.octo.probability = {{ $TESTING_OCTO_PROBABILITY }};

+ 50 - 0
web/rootfs/defaults/system-config.js

@@ -0,0 +1,50 @@
+{{ $CONFIG_BOSH_HOST := .Env.CONFIG_BOSH_HOST | default "" -}}
+{{ $CONFIG_EXTERNAL_CONNECT := .Env.CONFIG_EXTERNAL_CONNECT | default "false" | toBool -}}
+{{ $ENABLE_AUTH := .Env.ENABLE_AUTH | default "false" | toBool -}}
+{{ $ENABLE_GUESTS := .Env.ENABLE_GUESTS | default "false" | toBool -}}
+{{ $ENABLE_SUBDOMAINS := .Env.ENABLE_SUBDOMAINS | default "false" | toBool -}}
+{{ $ENABLE_WEBSOCKETS := .Env.ENABLE_WEBSOCKETS | default "false" | toBool -}}
+{{ $JICOFO_AUTH_USER := .Env.JICOFO_AUTH_USER | default "focus" }}
+{{ $XMPP_AUTH_DOMAIN := .Env.XMPP_AUTH_DOMAIN -}}
+{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN -}}
+{{ $XMPP_MUC_DOMAIN := .Env.XMPP_MUC_DOMAIN -}}
+{{ $XMPP_MUC_DOMAIN_PREFIX := (split "." .Env.XMPP_MUC_DOMAIN)._0  -}}
+
+// Begin default config overrides.
+
+if (!config.hasOwnProperty('hosts')) config.hosts = {};
+
+config.hosts.domain = '{{ $XMPP_DOMAIN }}';
+config.focusUserJid = '{{$JICOFO_AUTH_USER}}@{{$XMPP_AUTH_DOMAIN}}';
+
+{{ if $ENABLE_SUBDOMAINS -}}
+var subdomain = "<!--# echo var="subdomain" default="" -->";
+if (subdomain) {
+    subdomain = subdomain.substr(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 = '{{ .Env.XMPP_GUEST_DOMAIN }}';
+{{ end -}}
+// Domain for authenticated users. Defaults to <domain>.
+config.hosts.authdomain = '{{ $XMPP_DOMAIN }}';
+{{ end -}}
+
+config.bosh = '{{ if $CONFIG_BOSH_HOST }}https://{{ $CONFIG_BOSH_HOST }}{{ end }}/http-bind';
+{{ if $ENABLE_WEBSOCKETS -}}
+config.websocket = 'wss://{{ if $CONFIG_BOSH_HOST }}{{ $CONFIG_BOSH_HOST }}{{end}}/xmpp-websocket';
+{{ end -}}
+
+{{ if $CONFIG_EXTERNAL_CONNECT -}}
+{{ if $ENABLE_SUBDOMAINS -}}
+config.externalConnectUrl = '//{{ if .Env.CONFIG_BOSH_HOST }}{{ .Env.CONFIG_BOSH_HOST }}{{ end }}/<!--# echo var="subdir" default="" -->http-pre-bind';
+{{ else -}}
+config.externalConnectUrl = '//{{ if .Env.CONFIG_BOSH_HOST }}{{ .Env.CONFIG_BOSH_HOST }}{{ end }}/http-pre-bind';
+{{ end -}}
+{{ end -}}

+ 5 - 47
web/rootfs/etc/cont-init.d/10-config

@@ -68,52 +68,11 @@ if [[ ! -f /config/nginx/site-confs/default ]]; then
     tpl /defaults/default > /config/nginx/site-confs/default
 fi
 
-if [[ ! -f /config/config.js ]]; then
-    cp /defaults/config.js /config/config.js
-    sed -i \
-        -e "s#jitsi-meet.example.com#$XMPP_DOMAIN#g" \
-        -e "s#bosh:.*#bosh: '/http-bind',#" \
-        -e "s#muc:.*#muc: '${XMPP_MUC_DOMAIN}',#" \
-        -e "s#// focusUserJid:.*#focusUserJid: '${JICOFO_AUTH_USER}@${XMPP_AUTH_DOMAIN}',#" \
-        /config/config.js
-
-    if [[ $ENABLE_RECORDING -eq 1 || x$ENABLE_RECORDING == xtrue ]]; then
-        sed -i \
-            -e "/\/\/ Recording.*/a hiddenDomain: '$XMPP_RECORDER_DOMAIN'," \
-            -e "s#// fileRecordingsEnabled:.*#fileRecordingsEnabled: true,#" \
-            -e "s#// liveStreamingEnabled:.*#liveStreamingEnabled: true,#" \
-        /config/config.js
-    fi
-
-    if [[ $ENABLE_AUTH -eq 1 ]]; then
-        if [[ $ENABLE_GUESTS -eq 1 ]]; then
-            sed -i \
-                -e "s#// anonymousdomain:.*#anonymousdomain: '${XMPP_GUEST_DOMAIN}',#" \
-                /config/config.js
-        fi
-
-        sed -i \
-            -e "s#// authdomain:.*#authdomain: '${XMPP_DOMAIN}',#" \
-            /config/config.js
-    fi
-
-    if [[ -z "$(grep -om1 'etherpad_base:' /config/config.js)" ]]; then
-        if [[ ! -z "${ETHERPAD_PUBLIC_URL}" ]]; then
-            sed -i \
-                -e "/enableWelcomePage/a\    etherpad_base: '${ETHERPAD_PUBLIC_URL}/p/'," \
-                /config/config.js
-        elif [[ ! -z "${ETHERPAD_URL_BASE}" ]]; then
-            sed -i \
-                -e "/enableWelcomePage/a\    etherpad_base: '${PUBLIC_URL}/etherpad/p/'," \
-                /config/config.js
-        fi
-    fi
-
-    if [[ $ENABLE_TRANSCRIPTIONS -eq 1 || "$ENABLE_TRANSCRIPTIONS" == "true" ]]; then
-        sed -i \
-             -e "s#// transcribingEnabled:.*#transcribingEnabled: true,#" \
-             /config/config.js
-    fi
+cp /defaults/config.js /config/config.js
+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
 
 if [[ ! -f /config/interface_config.js ]]; then
@@ -126,5 +85,4 @@ if [[ ! -f /config/interface_config.js ]]; then
             -e "s#'closedcaptions', ##" \
             /config/interface_config.js
     fi
-
 fi