多租户更改
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
# Docker file builds an image with a tinode chat server.
|
||||
#
|
||||
# In order to run the image you have to link it to a running database container. For example, to
|
||||
# to use RethinkDB (named 'rethinkdb') and map the port where the tinode server accepts connections:
|
||||
#
|
||||
# $ docker run -p 6060:6060 -d --link rethinkdb \
|
||||
# --env UID_ENCRYPTION_KEY=base64+encoded+16+bytes= \
|
||||
# --env API_KEY_SALT=base64+encoded+32+bytes \
|
||||
# --env AUTH_TOKEN_KEY=base64+encoded+32+bytes \
|
||||
# tinode-server
|
||||
|
||||
FROM alpine:3.22
|
||||
|
||||
ARG VERSION=0.25
|
||||
ENV VERSION=$VERSION
|
||||
ARG BINVERS=$VERSION
|
||||
|
||||
LABEL maintainer="Tinode Team <info@tinode.co>"
|
||||
LABEL name="TinodeChatServer"
|
||||
LABEL version=$VERSION
|
||||
|
||||
# Build-time options.
|
||||
|
||||
# Database selector. Builds for MySQL by default.
|
||||
# Alternatively use one of: postgres mongodb rethinkdb for a corresponsing
|
||||
# DB backend or alldbs to build a generic Tinode docker image, for example:
|
||||
# `--build-arg TARGET_DB=postgres` to build for PostgreSQL.
|
||||
ARG TARGET_DB=mysql
|
||||
ENV TARGET_DB=$TARGET_DB
|
||||
|
||||
# Runtime options.
|
||||
|
||||
# Specifies the database host:port pair to wait for before running Tinode.
|
||||
# Ignored if empty.
|
||||
ENV WAIT_FOR=
|
||||
|
||||
# An option to reset database.
|
||||
ENV RESET_DB=false
|
||||
|
||||
# An option to upgrade database.
|
||||
ENV UPGRADE_DB=false
|
||||
|
||||
# Option to skip DB initialization when it's missing.
|
||||
ENV NO_DB_INIT=false
|
||||
|
||||
# Load sample data to database from data.json.
|
||||
ARG SAMPLE_DATA=data.json
|
||||
ENV SAMPLE_DATA=$SAMPLE_DATA
|
||||
|
||||
# Default country code to use in communication.
|
||||
ENV DEFAULT_COUNTRY_CODE=US
|
||||
|
||||
# The MySQL DSN connection.
|
||||
ENV MYSQL_DSN='root@tcp(mysql)/tinode?parseTime=true&collation=utf8mb4_0900_ai_ci'
|
||||
|
||||
# The PostgreSQL DSN connection.
|
||||
ENV POSTGRES_DSN='postgresql://postgres:postgres@localhost:5432/tinode?sslmode=disable&connect_timeout=10'
|
||||
|
||||
# Disable chatbot plugin by default.
|
||||
ENV PLUGIN_PYTHON_CHAT_BOT_ENABLED=false
|
||||
|
||||
# Default handler for large files
|
||||
ENV MEDIA_HANDLER=fs
|
||||
|
||||
# Whitelisted domains for file and S3 large media handler.
|
||||
ENV FS_CORS_ORIGINS='["*"]'
|
||||
ENV AWS_CORS_ORIGINS='["*"]'
|
||||
|
||||
# AWS S3 parameters
|
||||
ENV AWS_ACCESS_KEY_ID=
|
||||
ENV AWS_SECRET_ACCESS_KEY=
|
||||
ENV AWS_REGION=
|
||||
ENV AWS_S3_BUCKET=
|
||||
ENV AWS_S3_ENDPOINT=
|
||||
|
||||
# Default externally-visible hostname for email verification.
|
||||
ENV SMTP_HOST_URL='http://localhost:6060'
|
||||
# Email parameters decalarations.
|
||||
ENV SMTP_SERVER=
|
||||
ENV SMTP_PORT=
|
||||
ENV SMTP_SENDER=
|
||||
ENV SMTP_LOGIN=
|
||||
ENV SMTP_PASSWORD=
|
||||
ENV SMTP_AUTH_MECHANISM=
|
||||
ENV SMTP_HELO_HOST=
|
||||
ENV EMAIL_VERIFICATION_REQUIRED=
|
||||
ENV DEBUG_EMAIL_VERIFICATION_CODE=
|
||||
|
||||
# Whitelist of permitted email domains for email verification (empty list means all domains are permitted)
|
||||
ENV SMTP_DOMAINS=''
|
||||
|
||||
# Various encryption and salt keys. Replace with your own in production.
|
||||
|
||||
# Salt used to generate the API key. Don't change it unless you also change the
|
||||
# API key in the webapp & Android.
|
||||
ENV API_KEY_SALT=T713/rYYgW7g4m3vG6zGRh7+FM1t0T8j13koXScOAj4=
|
||||
|
||||
# Key used to sign authentication tokens.
|
||||
ENV AUTH_TOKEN_KEY=wfaY2RgF2S1OQI/ZlK+LSrp1KB2jwAdGAIHQ7JZn+Kc=
|
||||
|
||||
# Key to initialize UID generator
|
||||
ENV UID_ENCRYPTION_KEY=la6YsO+bNX/+XIkOqc5Svw==
|
||||
|
||||
# Disable TLS by default.
|
||||
ENV TLS_ENABLED=false
|
||||
ENV TLS_DOMAIN_NAME=
|
||||
ENV TLS_CONTACT_ADDRESS=
|
||||
|
||||
# Disable push notifications by default.
|
||||
ENV FCM_PUSH_ENABLED=false
|
||||
# Declare FCM-related vars
|
||||
ENV FCM_API_KEY=
|
||||
ENV FCM_APP_ID=
|
||||
ENV FCM_SENDER_ID=
|
||||
ENV FCM_PROJECT_ID=
|
||||
ENV FCM_VAPID_KEY=
|
||||
ENV FCM_MEASUREMENT_ID=
|
||||
|
||||
# Enable Android-specific notifications by default.
|
||||
ENV FCM_INCLUDE_ANDROID_NOTIFICATION=true
|
||||
|
||||
# Disable push notifications via Tinode Push Gateway.
|
||||
ENV TNPG_PUSH_ENABLED=false
|
||||
|
||||
# Tinode Push Gateway authentication token.
|
||||
ENV TNPG_AUTH_TOKEN=
|
||||
|
||||
# Tinode Push Gateway organization name as registered at console.tinode.co
|
||||
ENV TNPG_ORG=
|
||||
|
||||
# Video calls configuration.
|
||||
ENV WEBRTC_ENABLED=false
|
||||
ENV ICE_SERVERS_FILE=
|
||||
|
||||
# Use the target db by default.
|
||||
# When TARGET_DB is "alldbs", it is the user's responsibility
|
||||
# to set STORE_USE_ADAPTER to the desired db adapter correctly.
|
||||
ENV STORE_USE_ADAPTER=$TARGET_DB
|
||||
|
||||
# Url path for exposing the server's internal status. E.g. '/status'
|
||||
ENV SERVER_STATUS_PATH=''
|
||||
|
||||
# Garbage collection of unfinished account registrations.
|
||||
ENV ACC_GC_ENABLED=false
|
||||
|
||||
# Install root certificates, they are needed for email validator to work
|
||||
# with the TLS SMTP servers like Gmail or Mailjet. Also add bash and grep.
|
||||
RUN apk update && \
|
||||
apk add --no-cache ca-certificates bash grep
|
||||
|
||||
WORKDIR /opt/tinode
|
||||
|
||||
# Copy config template to the container.
|
||||
COPY config.template .
|
||||
COPY entrypoint.sh .
|
||||
|
||||
# Get the desired Tinode build.
|
||||
ADD https://github.com/tinode/chat/releases/download/v$BINVERS/tinode-$TARGET_DB.linux-amd64.tar.gz .
|
||||
|
||||
# Unpack the Tinode archive.
|
||||
RUN tar -xzf tinode-$TARGET_DB.linux-amd64.tar.gz \
|
||||
&& rm tinode-$TARGET_DB.linux-amd64.tar.gz
|
||||
|
||||
# Create directory for chatbot data.
|
||||
RUN mkdir /botdata
|
||||
|
||||
# Make scripts runnable
|
||||
RUN chmod +x entrypoint.sh
|
||||
RUN chmod +x credentials.sh
|
||||
|
||||
# Healthcheck: check if port 6060 is open
|
||||
HEALTHCHECK --interval=1m --timeout=3s --start-period=30s \
|
||||
CMD nc -z localhost 6060 || exit 1
|
||||
|
||||
# Generate config from template and run the server.
|
||||
ENTRYPOINT ["./entrypoint.sh"]
|
||||
|
||||
# HTTP, gRPC, cluster ports
|
||||
EXPOSE 6060 16060 12000-12003
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"listen": ":6060",
|
||||
"api_path": "/",
|
||||
"cache_control": 39600,
|
||||
"static_mount": "/",
|
||||
"grpc_listen": ":16060",
|
||||
"grpc_keepalive_enabled": true,
|
||||
"api_key_salt": "$API_KEY_SALT",
|
||||
"max_message_size": 4194304,
|
||||
"max_subscriber_count": 128,
|
||||
"max_tag_count": 16,
|
||||
"expvar": "/stats/expvar/",
|
||||
"server_status": "$SERVER_STATUS_PATH",
|
||||
"use_x_forwarded_for": true,
|
||||
"default_country_code": "$DEFAULT_COUNTRY_CODE",
|
||||
|
||||
"media": {
|
||||
"use_handler": "$MEDIA_HANDLER",
|
||||
"max_size": 33554432,
|
||||
"gc_period": 60,
|
||||
"gc_block_size": 100,
|
||||
"handlers": {
|
||||
"fs": {
|
||||
"upload_dir": "uploads",
|
||||
"cache_control": "max-age=86400",
|
||||
"cors_origins": $FS_CORS_ORIGINS
|
||||
},
|
||||
"s3":{
|
||||
"access_key_id": "$AWS_ACCESS_KEY_ID",
|
||||
"secret_access_key": "$AWS_SECRET_ACCESS_KEY",
|
||||
"region": "$AWS_REGION",
|
||||
"bucket": "$AWS_S3_BUCKET",
|
||||
"endpoint": "$AWS_S3_ENDPOINT",
|
||||
"presign_ttl": 3600,
|
||||
"cache_control": "max-age=86400",
|
||||
"cors_origins": $AWS_CORS_ORIGINS
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"tls": {
|
||||
"enabled": $TLS_ENABLED,
|
||||
"http_redirect": ":80",
|
||||
"strict_max_age": 604800,
|
||||
"autocert": {
|
||||
"cache": "/etc/letsencrypt/live/$TLS_DOMAIN_NAME",
|
||||
"email": "$TLS_CONTACT_ADDRESS",
|
||||
"domains": ["$TLS_DOMAIN_NAME"]
|
||||
}
|
||||
},
|
||||
|
||||
"auth_config": {
|
||||
"logical_names": [],
|
||||
"basic": {
|
||||
"add_to_tags": true,
|
||||
"min_login_length": 3,
|
||||
"min_password_length": 6
|
||||
},
|
||||
"token": {
|
||||
"expire_in": 1209600,
|
||||
"serial_num": 1,
|
||||
"key": "$AUTH_TOKEN_KEY"
|
||||
},
|
||||
"code": {
|
||||
"expire_in": 900,
|
||||
"max_retries": 3,
|
||||
"code_length": 6
|
||||
}
|
||||
},
|
||||
|
||||
"store_config": {
|
||||
"uid_key": "$UID_ENCRYPTION_KEY",
|
||||
"max_results": 1024,
|
||||
"use_adapter": "$STORE_USE_ADAPTER",
|
||||
"adapters": {
|
||||
"mysql": {
|
||||
"database": "tinode",
|
||||
"dsn": "$MYSQL_DSN"
|
||||
},
|
||||
"postgres": {
|
||||
"database": "tinode",
|
||||
"dsn": "$POSTGRES_DSN"
|
||||
},
|
||||
"rethinkdb": {
|
||||
"database": "tinode",
|
||||
"addresses": "rethinkdb"
|
||||
},
|
||||
"mongodb": {
|
||||
"database": "tinode",
|
||||
"addresses": "mongodb",
|
||||
"replica_set": "rs0"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"acc_validation": {
|
||||
"email": {
|
||||
"add_to_tags": true,
|
||||
"required": [$EMAIL_VERIFICATION_REQUIRED],
|
||||
"config": {
|
||||
"host_url": "$SMTP_HOST_URL",
|
||||
"smtp_server": "$SMTP_SERVER",
|
||||
"smtp_port": "$SMTP_PORT",
|
||||
"sender": "$SMTP_SENDER",
|
||||
"login": "$SMTP_LOGIN",
|
||||
"sender_password": "$SMTP_PASSWORD",
|
||||
"auth_mechanism": "$SMTP_AUTH_MECHANISM",
|
||||
"smtp_helo_host": "$SMTP_HELO_HOST",
|
||||
"languages": ["en", "es", "fr", "ru", "vi", "zh"],
|
||||
"validation_templ": "./templ/email-validation-{{.Language}}.templ",
|
||||
"reset_secret_templ": "./templ/email-password-reset-{{.Language}}.templ",
|
||||
"max_retries": 3,
|
||||
"domains": [$SMTP_DOMAINS],
|
||||
"debug_response": "$DEBUG_EMAIL_VERIFICATION_CODE"
|
||||
}
|
||||
},
|
||||
|
||||
"tel": {
|
||||
"add_to_tags": true,
|
||||
"config": {
|
||||
"host_url": "$TEL_HOST_URL",
|
||||
"languages": ["en", "es", "fr", "pt", "ru", "vi", "zh"],
|
||||
"sender": "$TEL_SENDER",
|
||||
"universal_templ": "./templ/sms-universal-{{.Language}}.templ",
|
||||
"max_retries": 3,
|
||||
"debug_response": "$DEBUG_TEL_VERIFICATION_CODE"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"acc_gc_config": {
|
||||
"enabled": $ACC_GC_ENABLED,
|
||||
"gc_period": 3600,
|
||||
"gc_block_size": 10,
|
||||
"gc_min_account_age": 48
|
||||
},
|
||||
|
||||
"push": [
|
||||
{
|
||||
"name":"tnpg",
|
||||
"config": {
|
||||
"enabled": $TNPG_PUSH_ENABLED,
|
||||
"token": "$TNPG_AUTH_TOKEN",
|
||||
"org": "$TNPG_ORG"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"fcm",
|
||||
"config": {
|
||||
"enabled": $FCM_PUSH_ENABLED,
|
||||
"project_id": "$FCM_PROJECT_ID",
|
||||
"credentials_file": "$FCM_CRED_FILE",
|
||||
"time_to_live": 3600,
|
||||
"android": {
|
||||
"enabled": $FCM_INCLUDE_ANDROID_NOTIFICATION,
|
||||
"icon": "ic_logo_push",
|
||||
"icon_color": "#3949AB",
|
||||
"click_action": ".MessageActivity",
|
||||
"msg": {
|
||||
"title_loc_key": "new_message",
|
||||
"title": "",
|
||||
"body_loc_key": "",
|
||||
"body": ""
|
||||
},
|
||||
"sub": {
|
||||
"title_loc_key": "new_chat",
|
||||
"body_loc_key": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"webrtc": {
|
||||
"enabled": $WEBRTC_ENABLED,
|
||||
"call_establishment_timeout": 30,
|
||||
"ice_servers_file": "$ICE_SERVERS_FILE"
|
||||
},
|
||||
|
||||
"cluster_config": {
|
||||
"self": "",
|
||||
"nodes": [
|
||||
{"name": "tinode-0", "addr": "tinode-0:12000"},
|
||||
{"name": "tinode-1", "addr": "tinode-1:12001"},
|
||||
{"name": "tinode-2", "addr": "tinode-2:12002"}
|
||||
],
|
||||
"failover": {
|
||||
"enabled": true,
|
||||
"heartbeat": 100,
|
||||
"vote_after": 8,
|
||||
"node_fail_after": 16
|
||||
}
|
||||
},
|
||||
|
||||
"plugins": [
|
||||
{
|
||||
"enabled": $PLUGIN_PYTHON_CHAT_BOT_ENABLED,
|
||||
"name": "python_chat_bot",
|
||||
"timeout": 20000,
|
||||
"filters": {
|
||||
"account": "C"
|
||||
},
|
||||
"failure_code": 0,
|
||||
"failure_text": null,
|
||||
"service_addr": "tcp://localhost:40051"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/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
|
||||
|
||||
# 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
|
||||
|
||||
# Initialize the database if it has not been initialized yet or if data reset/upgrade has been requested.
|
||||
init_stdout=./init-db-stdout.txt
|
||||
./init-db \
|
||||
--reset=${RESET_DB} \
|
||||
--upgrade=${UPGRADE_DB} \
|
||||
--config=${CONFIG} \
|
||||
--data=${SAMPLE_DATA} \
|
||||
--no_init=${NO_DB_INIT} \
|
||||
1>${init_stdout}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "./init-db failed. Quitting."
|
||||
exit 1
|
||||
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.
|
||||
./tinode "${args[@]}" 2>> /var/log/tinode.log
|
||||
|
||||
Reference in New Issue
Block a user