diff --git a/Dockerfile b/Dockerfile index 0134185..54c41d7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,7 +68,7 @@ RUN yum -y updateinfo && \ yum clean all && \ rm -f /var/log/*log COPY --chown=ds:ds config/nginx/nginx.conf /etc/nginx/nginx.conf -COPY --chown=ds:ds proxy-docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh +COPY --chown=ds:ds proxy-docker-entrypoint.py /docker-entrypoint.py COPY --chown=ds:ds --chmod=644 --from=ds-service \ /etc/$COMPANY_NAME/documentserver/nginx/ds.conf \ /etc/nginx/conf.d/ @@ -130,7 +130,7 @@ RUN sed 's|\(application\/zip.*\)|\1\n application\/wasm wasm;|' \ -exec sh -c 'gzip -cf9 $0 > $0.gz && chown ds:ds $0.gz' {} \; VOLUME /var/lib/$COMPANY_NAME USER ds -ENTRYPOINT docker-entrypoint.sh +ENTRYPOINT ["python", "/docker-entrypoint.py"] FROM ds-base AS docservice EXPOSE 8000 @@ -159,9 +159,9 @@ COPY --chown=ds:ds --from=ds-service \ COPY --from=ds-service \ /var/www/$COMPANY_NAME/documentserver/document-templates/new \ /var/www/$COMPANY_NAME/documentserver/document-templates/new -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.py / USER ds -ENTRYPOINT docker-entrypoint.sh /var/www/$COMPANY_NAME/documentserver/server/DocService/docservice +ENTRYPOINT ["python", "/docker-entrypoint.py", "/var/www/$COMPANY_NAME/documentserver/server/DocService/docservice"] HEALTHCHECK --interval=10s --timeout=3s CMD curl -sf http://localhost:8000/index.html FROM ds-base AS converter @@ -196,13 +196,13 @@ COPY --from=ds-service \ COPY --from=ds-service \ /ds/usr/lib64/* \ /usr/lib64/ -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.py / RUN mkdir -p \ /var/lib/$COMPANY_NAME/documentserver/App_Data/cache/files \ /var/lib/$COMPANY_NAME/documentserver/App_Data/docbuilder && \ chown -R ds:ds /var/lib/$COMPANY_NAME/documentserver USER ds -ENTRYPOINT docker-entrypoint.sh /var/www/$COMPANY_NAME/documentserver/server/FileConverter/converter +ENTRYPOINT ["python", "/docker-entrypoint.py", "/var/www/$COMPANY_NAME/documentserver/server/FileConverter/converter"] FROM node:lts-buster-slim AS example LABEL maintainer Ascensio System SIA diff --git a/docker-entrypoint.py b/docker-entrypoint.py new file mode 100644 index 0000000..acda420 --- /dev/null +++ b/docker-entrypoint.py @@ -0,0 +1,173 @@ +import os, json, sys +LOG_LEVEL = os.environ.get("LOG_LEVEL") +LOG_TYPE = os.environ.get("LOG_TYPE") +LOG_PATTERN = os.environ.get("LOG_PATTERN") +COMPANY_NAME = os.environ.get("COMPANY_NAME", "onlyoffice") +REDIS_SERVER_USER = os.environ.get("REDIS_SERVER_USER", "default") +REDIS_SERVER_PWD = os.environ.get("REDIS_SERVER_PWD", "") +REDIS_CLUSTER = os.environ.get("REDIS_CLUSTER") +REDIS_CLUSTER_NODES = os.environ.get("REDIS_CLUSTER_NODES") +REDIS_SENTINEL_GROUP_NAME = os.environ.get("REDIS_SENTINEL_GROUP_NAME", "mymaster") +REDIS_CONNECTOR_NAME = os.environ.get("REDIS_CONNECTOR_NAME", "redis") +AMQP_TYPE = os.environ.get("AMQP_TYPE", "rabbitmq") +AMQP_PORT = os.environ.get("AMQP_PORT", "5672") +AMQP_HOST = os.environ.get("AMQP_HOST", "localhost") +AMQP_USER = os.environ.get("AMQP_USER", "guest") +AMQP_PWD = os.environ.get("AMQP_PWD", "guest") +ACTIVEMQ_TRANSPORT = os.environ.get("ACTIVEMQ_TRANSPORT") +AMQP_PROTO = os.environ.get("AMQP_PROTO", "amqp") +AMQP_VHOST = os.environ.get("AMQP_VHOST", "/") +AMQP_URI = os.environ.get("AMQP_URI", AMQP_PROTO + "://" + AMQP_USER + ":" + AMQP_PWD + "@" + AMQP_HOST + ":" + AMQP_PORT + AMQP_VHOST) + +if LOG_LEVEL or LOG_TYPE or LOG_PATTERN: + filePath = "/etc/{0}/documentserver/log4js/production.json".format(COMPANY_NAME) + with open(filePath, 'r') as json_file: + logConfig = json.load(json_file) + if LOG_LEVEL: + logConfig["categories"]["default"]["level"] = LOG_LEVEL + if LOG_TYPE: + logConfig["appenders"]["default"]["layout"]["type"] = LOG_TYPE + if LOG_PATTERN: + logConfig["appenders"]["default"]["layout"]["pattern"] = LOG_PATTERN + with open(filePath, "w") as json_file: + json.dump(logConfig, json_file, indent=4) + +if REDIS_CLUSTER_NODES: + lst = REDIS_CLUSTER_NODES.split() + nodes = [] + for i in lst: + nodes.append({ "url": "redis://" + i }) + redisConfig = {"optionsCluster": {"rootNodes": nodes, "defaults": { "username": REDIS_SERVER_USER, "password": REDIS_SERVER_PWD }}} +elif REDIS_CONNECTOR_NAME == "ioredis": + redisConfig = { + "iooptions": { + "sentinels": [ + { + "host": os.environ.get("REDIS_SERVER_HOST", "localhost"), + "port": os.environ.get("REDIS_SERVER_PORT", "6379") + } + ], + "name": REDIS_SENTINEL_GROUP_NAME, + "username": REDIS_SERVER_USER, + "password": REDIS_SERVER_PWD, + "db": os.environ.get("REDIS_SERVER_DB_NUM", "0") + } + } +else: + redisConfig = { + "name": os.environ.get("REDIS_CONNECTOR_NAME", "redis"), + "host": os.environ.get("REDIS_SERVER_HOST", "localhost"), + "port": os.environ.get("REDIS_SERVER_PORT", "6379"), + "options": { + "user": REDIS_SERVER_USER, + "password": REDIS_SERVER_PWD, + "db": os.environ.get("REDIS_SERVER_DB_NUM", "0") + } + } + +nodeDict = { + "statsd": { + "useMetrics": os.environ.get("METRICS_ENABLED", "false"), + "host": os.environ.get("METRICS_HOST", "localhost"), + "port": os.environ.get("METRICS_PORT", "8125"), + "prefix": os.environ.get("METRICS_PREFIX", "ds.") + }, + "services": { + "CoAuthoring": { + "sql": { + "type": os.environ.get("DB_TYPE", "postgres"), + "dbHost": os.environ.get("DB_HOST", "localhost"), + "dbPort": os.environ.get("DB_PORT", "5432"), + "dbUser": os.environ.get("DB_USER", "onlyoffice"), + "dbName": os.environ.get("DB_NAME", os.environ.get("DB_USER", "onlyoffice")), + "dbPass": os.environ.get("DB_PWD", "onlyoffice") + }, + "redis": redisConfig, + "token": { + "enable": { + "browser": os.environ.get("JWT_ENABLED", "true"), + "request": { + "inbox": os.environ.get("JWT_ENABLED_INBOX", os.environ.get("JWT_ENABLED", "true")), + "outbox": os.environ.get("JWT_ENABLED_OUTBOX", os.environ.get("JWT_ENABLED", "true")) + } + }, + "inbox": { + "header": os.environ.get("JWT_HEADER_INBOX", os.environ.get("JWT_HEADER", "Authorization")), + "inBody": os.environ.get("JWT_IN_BODY", "false") + }, + "outbox": { + "header": os.environ.get("JWT_HEADER_OUTBOX", os.environ.get("JWT_HEADER", "Authorization")), + "inBody": os.environ.get("JWT_IN_BODY", "false") + } + }, + "secret": { + "inbox": { + "string": os.environ.get("JWT_SECRET_INBOX", "secret") + }, + "outbox": { + "string": os.environ.get("JWT_SECRET_OUTBOX", "secret") + }, + "session": { + "string": os.environ.get("JWT_SECRET", "secret") + } + }, + "request-filtering-agent" : { + "allowPrivateIPAddress": os.environ.get("ALLOW_PRIVATE_IP_ADDRESS", "false"), + "allowMetaIPAddress": os.environ.get("ALLOW_META_IP_ADDRESS", "false"), + "allowIPAddressList": os.environ.get("ALLOW_IP_ADDRESS_LIST", "[]"), + "denyIPAddressList": os.environ.get("DENY_IP_ADDRESS_LIST", "[]") + } + } + }, + "queue": { + "type": AMQP_TYPE + }, + "wopi": { + "enable": os.environ.get("WOPI_ENABLED", "false") + }, + "FileConverter": { + "converter": { + "maxprocesscount": 0.001 + } + }, + "storage": { + "fs": { + "folderPath": "/var/lib/{0}/documentserver/App_Data/cache/files/".format(COMPANY_NAME) + os.environ.get("STORAGE_SUBDIRECTORY_NAME", "latest"), + "secretString": os.environ.get("SECURE_LINK_SECRET", "verysecretstring") + }, + "storageFolderName": "files/" + os.environ.get("STORAGE_SUBDIRECTORY_NAME", "latest") + }, + "persistentStorage": { + "fs": { + "folderPath": "/var/lib/{0}/documentserver/App_Data/cache/files".format(COMPANY_NAME), + "secretString": os.environ.get("SECURE_LINK_SECRET", "verysecretstring") + }, + "storageFolderName": "files" + } +} + +if AMQP_TYPE == "rabbitmq": + amqpConfig = { + "url": AMQP_URI + } + nodeDict['rabbitmq'] = amqpConfig +elif AMQP_TYPE == "activemq": + if AMQP_PROTO == "amqps" or AMQP_PROTO == "amqp+ssl": + ACTIVEMQ_TRANSPORT = "tls" + else: + ACTIVEMQ_TRANSPORT = "tcp" + amqpConfig = { + "connectOptions": { + "port": AMQP_PORT, + "host": AMQP_HOST, + "username": AMQP_USER, + "password": AMQP_PWD, + "transport": ACTIVEMQ_TRANSPORT + } + } + nodeDict['activemq'] = amqpConfig + +NODE_CONFIG = json.dumps(nodeDict, indent=4) +os.environ['NODE_CONFIG'] = NODE_CONFIG +os.system(sys.argv[1]) + diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index c86a847..0000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env bash -set -e - -if [[ -n ${LOG_LEVEL} ]]; then - sed 's/\(^.\+"level":\s*"\).\+\(".*$\)/\1'$LOG_LEVEL'\2/g' -i /etc/$COMPANY_NAME/documentserver/log4js/production.json -fi - -if [[ -n ${LOG_TYPE} ]]; then - sed 's/\("type"\:\) "pattern"/\1 "'$LOG_TYPE'"/' -i /etc/$COMPANY_NAME/documentserver/log4js/production.json -fi - -if [[ -n ${LOG_PATTERN} ]]; then - sed "s/\(\"pattern\"\:\).*/\1 \"$LOG_PATTERN\"/" -i /etc/$COMPANY_NAME/documentserver/log4js/production.json -fi - -ACTIVEMQ_TRANSPORT="" -case $AMQP_PROTO in - amqps | amqp+ssl) - ACTIVEMQ_TRANSPORT="tls" - ;; - *) - ACTIVEMQ_TRANSPORT="tcp" - ;; -esac - -if [[ -n "$REDIS_CLUSTER_NODES" ]]; then - declare -a REDIS_CLUSTER_NODES_ALL=($REDIS_CLUSTER_NODES) - REDIS_CLUSTER_NODES_ARRAY=() - for node in "${REDIS_CLUSTER_NODES_ALL[@]}"; do - REDIS_CLUSTER_NODES_ARRAY+=('{ "url": "redis://'$node'" }') - done - OLD_IFS="$IFS" - IFS="," - NODES=$(echo "${REDIS_CLUSTER_NODES_ARRAY[*]}") - IFS="$OLD_IFS" - REDIS_CLUSTER='"rootNodes": [ '$NODES' ], "defaults": { "username": "'${REDIS_SERVER_USER:-default}'", "password": "'$REDIS_SERVER_PWD'" }' -else - REDIS_CLUSTER='' -fi - -export NODE_CONFIG='{ - "statsd": { - "useMetrics": '${METRICS_ENABLED:-false}', - "host": "'${METRICS_HOST:-localhost}'", - "port": '${METRICS_PORT:-8125}', - "prefix": "'${METRICS_PREFIX:-ds.}'" - }, - "services": { - "CoAuthoring": { - "sql": { - "type": "'${DB_TYPE:-postgres}'", - "dbHost": "'${DB_HOST:-localhost}'", - "dbPort": '${DB_PORT:-5432}', - "dbUser": "'${DB_USER:=onlyoffice}'", - "dbName": "'${DB_NAME:-${DB_USER}}'", - "dbPass": "'${DB_PWD:-onlyoffice}'" - }, - "redis": { - "name": "'${REDIS_CONNECTOR_NAME:-redis}'", - "host": "'${REDIS_SERVER_HOST:-${REDIST_SERVER_HOST:-localhost}}'", - "port": '${REDIS_SERVER_PORT:-${REDIST_SERVER_PORT:-6379}}', - "options": { - "user": "'${REDIS_SERVER_USER:-default}'", - "password": "'${REDIS_SERVER_PWD}'", - "db": "'${REDIS_SERVER_DB_NUM:-0}'" - }, - "optionsCluster": { '${REDIS_CLUSTER}' }, - "iooptions": { - "sentinels": [ - { - "host": "'${REDIS_SERVER_HOST:-localhost}'", - "port": '${REDIS_SERVER_PORT:-6379}' - } - ], - "name": "'${REDIS_SENTINEL_GROUP_NAME:-mymaster}'", - "username": "'${REDIS_SERVER_USER:-default}'", - "password": "'${REDIS_SERVER_PWD}'", - "db": "'${REDIS_SERVER_DB_NUM:-0}'" - } - }, - "token": { - "enable": { - "browser": '${JWT_ENABLED:=true}', - "request": { - "inbox": '${JWT_ENABLED_INBOX:-${JWT_ENABLED}}', - "outbox": '${JWT_ENABLED_OUTBOX:-${JWT_ENABLED}}' - } - }, - "inbox": { - "header": "'${JWT_HEADER_INBOX:-${JWT_HEADER:=Authorization}}'", - "inBody": '${JWT_IN_BODY:=false}' - }, - "outbox": { - "header": "'${JWT_HEADER_OUTBOX:-${JWT_HEADER}}'", - "inBody": '${JWT_IN_BODY}' - } - }, - "secret": { - "inbox": { - "string": "'${JWT_SECRET_INBOX:-${JWT_SECRET:=secret}}'" - }, - "outbox": { - "string": "'${JWT_SECRET_OUTBOX:-${JWT_SECRET}}'" - }, - "session": { - "string": "'${JWT_SECRET}'" - } - }, - "request-filtering-agent" : { - "allowPrivateIPAddress": '${ALLOW_PRIVATE_IP_ADDRESS:-false}', - "allowMetaIPAddress": '${ALLOW_META_IP_ADDRESS:-false}', - "allowIPAddressList": '${ALLOW_IP_ADDRESS_LIST:-[]}', - "denyIPAddressList": '${DENY_IP_ADDRESS_LIST:-[]}' - } - } - }, - "queue": { - "type": "'${AMQP_TYPE:=rabbitmq}'" - }, - "activemq": { - "connectOptions": { - "port": "'${AMQP_PORT:=5672}'", - "host": "'${AMQP_HOST:=localhost}'", - "username": "'${AMQP_USER:=guest}'", - "password": "'${AMQP_PWD:=guest}'", - "transport": "'${ACTIVEMQ_TRANSPORT}'" - } - }, - "rabbitmq": { - "url": "'${AMQP_URI:-${AMQP_PROTO:-amqp}://${AMQP_USER}:${AMQP_PWD}@${AMQP_HOST}:${AMQP_PORT}${AMQP_VHOST:-/}}'" - }, - "wopi": { - "enable": '${WOPI_ENABLED:-false}' - }, - "FileConverter": { - "converter": { - "maxprocesscount": 0.001 - } - }, - "storage": { - "fs": { - "secretString": "'${SECURE_LINK_SECRET:-verysecretstring}'" - } - } -}' - -exec "$@" diff --git a/proxy-docker-entrypoint.py b/proxy-docker-entrypoint.py new file mode 100644 index 0000000..84af87c --- /dev/null +++ b/proxy-docker-entrypoint.py @@ -0,0 +1,59 @@ +import os, re, shutil + +if not os.path.isdir("/tmp/proxy_nginx"): + shutil.copytree("/etc/nginx", "/tmp/proxy_nginx") + +nginxConfPath = "/tmp/proxy_nginx/nginx.conf" +dsConfPath = "/tmp/proxy_nginx/conf.d/ds.conf" +dsCommonPath = "/tmp/proxy_nginx/includes/ds-common.conf" +dsDocservicePath = "/tmp/proxy_nginx/includes/ds-docservice.conf" + +def envsubst(inPath, outPath): + with open(inPath, 'r') as file: + conf = file.read() + for i in re.findall(r'\$[a-zA-Z_]*', conf): + for j in os.environ: + if i[1:] == j: + conf = conf.replace(i, os.environ[j]) + with open(outPath, 'w') as file: + file.write(conf) + +envsubst("/tmp/proxy_nginx/includes/http-upstream.conf", "/tmp/http-upstream.conf") +envsubst("/etc/nginx/includes/ds-common.conf", dsCommonPath) + +with open(nginxConfPath, 'r') as file: + nginx = file.read() +nginx = re.sub(r"worker_connections\s[0-9]+", "worker_connections {0}".format(os.environ.get("NGINX_WORKER_CONNECTIONS")), nginx) +if os.environ.get("NGINX_ACCESS_LOG") != "off" : + nginx = re.sub(r"access_log.*", "access_log {0}".format(os.environ.get("NGINX_ACCESS_LOG")), nginx) +with open(nginxConfPath, 'w') as file: + file.write(nginx) + +with open(dsConfPath, 'r') as file: + ds = file.read() +ds = re.sub(r"set\s\$secure_link_secret.*", "set $secure_link_secret {0};".format(os.environ.get("SECURE_LINK_SECRET", "verysecretstring")), ds) +if not os.path.isfile("/proc/net/if_inet6"): + ds = re.sub(r"listen\s\[::]:[0-9]+.*", "", ds) +with open(dsConfPath, 'w') as file: + file.write(ds) + +with open(dsCommonPath, 'r') as file: + common = file.read() +common = re.sub(r"client_max_body_size.*", "client_max_body_size {0};".format(os.environ.get("NGINX_CLIENT_MAX_BODY_SIZE")), common) +with open(dsCommonPath, 'w') as file: + file.write(common) + +with open(dsDocservicePath, 'r') as file: + docService = file.read() + if os.environ.get("INFO_ALLOWED_IP"): + ip = os.environ.get("INFO_ALLOWED_IP").split() + ipStr = "" + for i in ip: + ipStr = ipStr + " allow {0};\n".format(i) + docService = re.sub(r"(location.*\(info\).*)", r"\1\n" + ipStr[:-1], docService) + if os.environ.get("INFO_ALLOWED_USER"): + os.system('htpasswd -c -b /tmp/auth "${INFO_ALLOWED_USER}" "${INFO_ALLOWED_PASSWORD:-password}"') + docService = re.sub(r"(location.*\(info\).*)", "\1\n auth_basic \"Authentication Required;\"\n auth_basic_user_file /tmp/auth;", docService) +with open(dsDocservicePath, 'w') as file: + file.write(docService) +os.system('exec nginx -c /tmp/proxy_nginx/nginx.conf -g \'daemon off;\'') diff --git a/proxy-docker-entrypoint.sh b/proxy-docker-entrypoint.sh deleted file mode 100755 index c6e2382..0000000 --- a/proxy-docker-entrypoint.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -set -e - -if ! [ -d /tmp/proxy_nginx ]; then - mkdir /tmp/proxy_nginx -fi -cp -r /etc/nginx/* /tmp/proxy_nginx/ -sed 's|\(worker_connections\) [[:digit:]]*;|\1 '$NGINX_WORKER_CONNECTIONS';|g' -i /tmp/proxy_nginx/nginx.conf -if [ $NGINX_ACCESS_LOG != "off" ]; then - sed 's|#*\(\s*access_log\).*;|\1 /var/log/nginx/access.log '$NGINX_ACCESS_LOG';|g' -i /tmp/proxy_nginx/nginx.conf -fi -envsubst < /tmp/proxy_nginx/includes/http-upstream.conf > /tmp/http-upstream.conf -envsubst < /etc/nginx/includes/ds-common.conf | tee /tmp/proxy_nginx/includes/ds-common.conf > /dev/null -sed "s,\(set \+\$secure_link_secret\).*,\1 "${SECURE_LINK_SECRET:-verysecretstring}";," -i /tmp/proxy_nginx/conf.d/ds.conf -sed "s/\(client_max_body_size\).*/\1 $NGINX_CLIENT_MAX_BODY_SIZE;/" -i /tmp/proxy_nginx/includes/ds-common.conf -if [[ ! -f "/proc/net/if_inet6" ]]; then - sed '/listen\s\+\[::[0-9]*\].\+/d' -i /tmp/proxy_nginx/conf.d/ds.conf -fi -if [[ -n "$INFO_ALLOWED_IP" ]]; then - declare -a IP_ALL=($INFO_ALLOWED_IP) - for ip in "${IP_ALL[@]}"; do - sed -i '/(info)/a\ allow '$ip'\;' /tmp/proxy_nginx/includes/ds-docservice.conf - done -fi -if [[ -n "$INFO_ALLOWED_USER" ]]; then - htpasswd -c -b /tmp/auth "${INFO_ALLOWED_USER}" "${INFO_ALLOWED_PASSWORD:-password}" - sed -i '/(info)/a\ auth_basic \"Authentication Required\"\;' /tmp/proxy_nginx/includes/ds-docservice.conf - sed -i '/auth_basic/a\ auth_basic_user_file \/tmp\/auth\;' /tmp/proxy_nginx/includes/ds-docservice.conf -fi -exec nginx -c /tmp/proxy_nginx/nginx.conf -g 'daemon off;'