#!/bin/bash # If EXT_CONFIG is set, use it as a config file. if [ ! -z "$EXT_CONFIG" ] ; then CONFIG="$EXT_CONFIG" # Enable push notifications. if [ ! -z "$FCM_SENDER_ID" ] ; then FCM_PUSH_ENABLED=true fi else CONFIG=working.config : "${REDIS_KEY_PREFIX:=im}" : "${CLUSTER_PROXY_TO_MASTER_BUFFER:=4096}" : "${CLUSTER_PROXY_TO_MASTER_WORKERS:=16}" : "${CLUSTER_PROXY_TO_MASTER_ENQUEUE_TIMEOUT_MS:=300}" : "${CLUSTER_ROUTE_RETRIES:=3}" : "${CLUSTER_ROUTE_RETRY_BACKOFF_MS:=25}" : "${MYSQL_MAX_OPEN_CONNS:=24}" : "${MYSQL_MAX_IDLE_CONNS:=8}" : "${MYSQL_REGISTRY_MAX_OPEN_CONNS:=4}" : "${MYSQL_REGISTRY_MAX_IDLE_CONNS:=2}" if [ -z "$CLUSTER_NODES_JSON" ] ; then CLUSTER_NODES_JSON='[{"name":"tinode-0","addr":"tinode-0:12000"},{"name":"tinode-1","addr":"tinode-1:12001"},{"name":"tinode-2","addr":"tinode-2:12002"}]' fi # Remove the old config. rm -f working.config # The 'alldbs' is not a valid adapter name. if [ "$TARGET_DB" = "alldbs" ] ; then TARGET_DB= fi # Enable email verification if $SMTP_SERVER is defined. if [ ! -z "$SMTP_SERVER" ] ; then EMAIL_VERIFICATION_REQUIRED='"auth"' fi # Enable TLS (httpS). if [ ! -z "$TLS_DOMAIN_NAME" ] ; then TLS_ENABLED=true fi # Enable push notifications. if [ ! -z "$FCM_CRED_FILE" ] ; then FCM_PUSH_ENABLED=true fi if [ ! -z "$TNPG_AUTH_TOKEN" ] ; then TNPG_PUSH_ENABLED=true fi if [ ! -z "$ICE_SERVERS_FILE" ] ; then WEBRTC_ENABLED=true fi # Generate a new 'working.config' from template and environment while IFS='' read -r line || [[ -n $line ]] ; do while [[ "$line" =~ (\$[A-Z_][A-Z_0-9]*) ]] ; do LHS=${BASH_REMATCH[1]} RHS="$(eval echo "\"$LHS\"")" line=${line//$LHS/"$RHS"} done echo "$line" >> working.config done < config.template fi # If external static dir is defined, use it. # Otherwise, fall back to "./static". if [ ! -z "$EXT_STATIC_DIR" ] ; then STATIC_DIR=$EXT_STATIC_DIR else STATIC_DIR="./static" fi # Do not load data when upgrading database. if [ "$UPGRADE_DB" = "true" ] ; then SAMPLE_DATA= fi # If push notifications are enabled, generate client-side firebase config file. if [ ! -z "$FCM_PUSH_ENABLED" ] || [ ! -z "$TNPG_PUSH_ENABLED" ] ; then # Write client config to $STATIC_DIR/firebase-init.js cat > $STATIC_DIR/firebase-init.js <<- EOM const FIREBASE_INIT = { apiKey: "$FCM_API_KEY", appId: "$FCM_APP_ID", messagingSenderId: "$FCM_SENDER_ID", projectId: "$FCM_PROJECT_ID", messagingVapidKey: "$FCM_VAPID_KEY", measurementId: "$FCM_MEASUREMENT_ID" }; EOM else # Create an empty firebase-init.js echo "" > $STATIC_DIR/firebase-init.js fi if [ ! -z "$IOS_UNIV_LINKS_APP_ID" ] ; then # Write config to $STATIC_DIR/apple-app-site-association config file. # See https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html for details. cat > $STATIC_DIR/apple-app-site-association <<- EOM { "applinks": { "apps": [], "details": [ { "appID": "$IOS_UNIV_LINKS_APP_ID", "paths": [ "*" ] } ] } } EOM fi # Wait for database if needed. if [ ! -z "$WAIT_FOR" ] ; then IFS=':' read -ra DB <<< "$WAIT_FOR" if [ ${#DB[@]} -ne 2 ]; then echo "\$WAIT_FOR (${WAIT_FOR}) env var should be in form HOST:PORT" exit 1 fi until nc -z -v -w5 ${DB[0]} ${DB[1]}; do echo "waiting for ${WAIT_FOR}..."; sleep 3; done fi run_with_retries() { local name="$1" shift local attempts="${STARTUP_RETRY_ATTEMPTS:-10}" local delay="${STARTUP_RETRY_DELAY_SECONDS:-3}" local i=1 while [ "$i" -le "$attempts" ]; do "$@" local status=$? if [ "$status" -eq 0 ]; then return 0 fi echo "$name failed with status $status (attempt $i/$attempts)." if [ "$i" -eq "$attempts" ]; then return "$status" fi sleep "$delay" i=$((i + 1)) done } init_db_once() { ./init-db \ --reset=${RESET_DB} \ --upgrade=${UPGRADE_DB} \ --config=${CONFIG} \ --data=${SAMPLE_DATA} \ --no_init=${NO_DB_INIT} \ 1>${init_stdout} } apply_hotgo_tenant_db_once() { IM_MYSQL_DSN="${MYSQL_DSN}" ./apply-hotgo-tenant-db } init_stdout=./init-db-stdout.txt if [ "$NO_DB_INIT" = "true" ] ; then echo "NO_DB_INIT=true: skipping init-db and apply-hotgo-tenant-db." else # Initialize the database if it has not been initialized yet or if data reset/upgrade has been requested. run_with_retries "init-db" init_db_once if [ $? -ne 0 ]; then echo "./init-db failed. Quitting." exit 1 fi # Validate that startup is pointed at the shared meeting_im database. Schema # changes are applied separately and are never performed during pod startup. run_with_retries "apply-hotgo-tenant-db" apply_hotgo_tenant_db_once if [ $? -ne 0 ]; then echo "./apply-hotgo-tenant-db failed. Quitting." exit 1 fi fi # If sample data was provided, try to find Tino password. if [ ! -z "$SAMPLE_DATA" ] ; then grep "usr;tino;" $init_stdout > /botdata/tino-password fi if [ -s /botdata/tino-password ] ; then # Convert Tino's authentication credentials into a cookie file. # /botdata/tino-password could be empty if DB was not updated. In such a case the # /botdata/.tn-cookie will not be modified. ./credentials.sh /botdata/.tn-cookie < /botdata/tino-password fi args=("--config=${CONFIG}" "--static_data=$STATIC_DIR" "--cluster_self=$CLUSTER_SELF" "--pprof_url=$PPROF_URL") # Run the tinode server, mirroring output to both stdout (so kubectl logs/Promtail's # standard container-log collection actually sees it -- confirmed live that the old # file-only redirect meant Loki never received a single real tinode log line, only # this script's own earlier init-db output) and the log file (kept for exec-based # inspection, e.g. `kubectl exec ... -- cat /var/log/tinode.log`). PIPESTATUS[0] is # required here: with output piped through tee, a bare $? would report tee's exit # status (almost always 0) instead of tinode's. ./tinode "${args[@]}" 2>&1 | tee -a /var/log/tinode.log exit "${PIPESTATUS[0]}"