一、
前言
书接上回,Linux|实用工具|onlyoffice workspace使用docker快速部署(离线和定制化部署)-CSDN博客,如果是小公司或者比如某个项目组内部使用,那么,使用docspace这个文档协同系统是非常合适的,该文档协同系统主要提供了文档安全,文档编辑,文档备份,文档分享,文档协同修改这些功能,其主要功能文档编辑非常强大,支持多种文档格式,比如wps的et文件格式,Microsoft的xlsx等等所有主流文档格式,并且还支持pdf文件的编辑,相信很多同学都知道,pdf文件的编辑功能一般是需要收费的,或者安装破解版软件;其次,更为重要的是多种文档格式间的自由转换功能也非常强大,例如,word格式文件转pdf格式文件,pdf格式文件转word格式文件,相信很多同学也知道,这样的功能一般也是收费的,比如百度网盘的文档格式转换,这个具体怎么收费的,应该是有人了解,在这里我就不过多废话了,但这些功能现在统统集中在了docspace文档协作系统内了,并且还是免费的,可以自由使用的。主要原因是,only office办公软件协同工作系统是开源的,社区版本就已经具备这些高逼格的功能了。
下面开始介绍如何完全离线安装docspace文档协作系统
二、
安装环境准备
全部所需文件下载地址包括dockers镜像文件:
https://download.csdn.net/download/alwaysbefine/91647341
1、docker环境
这里需要强调一下docker的版本,最好是使用27版本以上,主要是本次部署使用的镜像都是比较新的,docker最好安装在系统路径下,一般建议使用二进制安装
docker服务的启动脚本:
cat > /etc/systemd/system/docker.service<<EOF
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TimeoutStartSec=0
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s[Install]
WantedBy=multi-user.target
EOF
根据该脚本,可以得出,docker-27.5.0.tgz二进制安装包解压后,所有二进制文件移动到/usr/bin/目录下即可,然后执行systemctl start docker 即可
[root@centos14 ~]# tar xvf docker-27.5.0.tgz
docker/
docker/runc
docker/containerd
docker/docker-init
docker/dockerd
docker/containerd-shim-runc-v2
docker/docker-proxy
docker/docker
docker/ctr
[root@centos14 ~]# mv docker/* /usr/bin/
2、
docker-compse
该软件主要是docspce要使用,文件编排这些工作都是通过脚本来进行的,版本也需要注意,尽量使用2.0以上的版本,我这里使用的是2.33
docker-compose-linux-x86_64-2.33.0.zip 解压后,给予执行权限后,移动到/usr/bin目录下即可,操记录如下:
[root@centos14 ~]# unzip docker-compose-linux-x86_64-2.33.0.zip
Archive: docker-compose-linux-x86_64-2.33.0.zipinflating: docker-compose-linux-x86_64
[root@centos14 ~]# chmod a+x docker-compose-linux-x86_64
[root@centos14 ~]# ./docker-compose-linux-x86_64 -v
Docker Compose version v2.33.0
[root@centos14 ~]# mv docker-compose-linux-x86_64 /usr/bin/docker-compose
3、
导入离线镜像
操作记录如下:
[root@centos14 ~]# ls onlyoffice-docspace-images-offline/
fluent_fluent-bit_3.0.2.tar onlyoffice_docspace-migration-runner_3.2.1.1.tar
mysql_8.3.0.tar onlyoffice_docspace-notify_3.2.1.1.tar
nginx_latest.tar onlyoffice_docspace-people-server_3.2.1.1.tar
onlyoffice_docspace-api_3.2.1.1.tar onlyoffice_docspace-router_3.2.1.1.tar
onlyoffice_docspace-api-system_3.2.1.1.tar onlyoffice_docspace-sdk_3.2.1.1.tar
onlyoffice_docspace-backup_3.2.1.1.tar onlyoffice_docspace-socket_3.2.1.1.tar
onlyoffice_docspace-backup-background_3.2.1.1.tar onlyoffice_docspace-ssoauth_3.2.1.1.tar
onlyoffice_docspace-clear-events_3.2.1.1.tar onlyoffice_docspace-studio_3.2.1.1.tar
onlyoffice_docspace-doceditor_3.2.1.1.tar onlyoffice_docspace-studio-notify_3.2.1.1.tar
onlyoffice_docspace-files_3.2.1.1.tar onlyoffice_documentserver_9.0.4.1.tar
onlyoffice_docspace-files-services_3.2.1.1.tar onlyoffice_opensearch_2.18.0.tar
onlyoffice_docspace-healthchecks_3.2.1.1.tar opensearchproject_opensearch-dashboards_2.18.0.tar
onlyoffice_docspace-identity-api_3.2.1.1.tar rabbitmq_3.tar
onlyoffice_docspace-identity-authorization_3.2.1.1.tar redis_7.tar
onlyoffice_docspace-login_3.2.1.1.tar
[root@centos14 ~]# for i in `ls /root/onlyoffice-docspace-images-offline/`;do docker load -i /root/onlyoffice-docspace-images-offline/$i ;done
32ae37dc07be: Loading layer 327.7kB/327.7kB
577c8ee06f39: Loading layer 51.2kB/51.2kB
9ed498e122b2: Loading layer 3.379MB/3.379MB
4d049f83d9cf: Loading layer 1.536kB/1.536kB
af5aa97ebe6c: Loading layer 2.56kB/2.56kB
ac805962e479: Loading layer 2.56kB/2.56kB
bbb6cacb8c82: Loading layer 2.56kB/2.56kB
2a92d6ac9e4f: Loading layer 1.536kB/1.536kB
1a73b54f556b: Loading layer 10.24kB/10.24kB
c048279a7d9f: Loading layer 3.072kB/3.072kB
2388d21e8e2b: Loading layer 225.3kB/225.3kB
570759f468b1: Loading layer 12.92MB/12.92MB
24aacbf97031: Loading layer 3.983MB/3.983MB
6835249f577a: Loading layer 1.505MB/1.505MB
f63d186f6e7d: Loading layer 276.5kB/276.5kB
6ea409d80cd8: Loading layer 1.997MB/1.997MB
f3aaf0cdb0a8: Loading layer 112.6kB/112.6kB
。。。。。。。。。。。。。。。。。。。。。。后面略略略
说明:onlyoffice_documentserver_9.0.4.1.tar镜像是docspace最核心的功能,也就是这个镜像是提供文档编辑功能的,那么,可以使用其它版本的onlyoffice_documentserver吗?答案是肯定的,可以!!!
但如果使用其它版本例如onlyoffice_documentserver_6.1.1.tar这样的镜像,pdf文档编辑功能可能就无法使用了,docspace直接就认不到pdf文件,不过随便哪个版本的onlyoffice_documentserver都是可以的,只是在安装的时候需要指定一下版本号即可
4、
yum安装必要的软件
必需的软件是jq和net-tools 配置好centos的ISO仓库就可以安装了,也就是一个本地仓库,这里就不过多介绍了,不明白得同学请看我的另一篇博客:
Linux的完全本地仓库搭建指南(科普扫盲贴)_linux7如何搭建本地cpan库-CSDN博客
5、
docker-compose的编排文件和安装脚本
docker.tar.gz和安装脚本放置在同一个目录下即可
安装脚本如下(已做更改,例如对内存和硬盘存储的要求,由8G限制更改位为3G):
#!/bin/bash## (c) Copyright Ascensio System SIA 2025## This program is a free software product. You can redistribute it and/or# modify it under the terms of the GNU Affero General Public License (AGPL)# version 3 as published by the Free Software Foundation. In accordance with# Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect# that Ascensio System SIA expressly excludes the warranty of non-infringement# of any third-party rights.## This program is distributed WITHOUT ANY WARRANTY; without even the implied# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For# details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html## You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha# street, Riga, Latvia, EU, LV-1050.## The interactive user interfaces in modified source and object code versions# of the Program must display Appropriate Legal Notices, as required under# Section 5 of the GNU AGPL version 3.## Pursuant to Section 7(b) of the License you must retain the original Product# logo when distributing the program. Pursuant to Section 7(e) we decline to# grant you any rights under trademark law for use of our trademarks.## All the Product's GUI elements, including illustrations and icon sets, as# well as technical writing content are licensed under the terms of the# Creative Commons Attribution-ShareAlike 4.0 International. See the License# terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode#PACKAGE_SYSNAME="onlyoffice"
PRODUCT_NAME="DocSpace"
PRODUCT=$(tr '[:upper:]' '[:lower:]' <<< ${PRODUCT_NAME})
BASE_DIR="/app/$PACKAGE_SYSNAME"
PROXY_YML="${BASE_DIR}/proxy.yml"
STATUS=""
DOCKER_TAG=""
INSTALLATION_TYPE="ENTERPRISE"
IMAGE_NAME="${PACKAGE_SYSNAME}/${STATUS}${PRODUCT}-api"
CONTAINER_NAME="${PACKAGE_SYSNAME}-api"
IDENTITY_CONTAINER_NAME="${PACKAGE_SYSNAME}-identity-api"NETWORK_NAME=${PACKAGE_SYSNAME}SWAPFILE="/${PRODUCT}_swapfile"
MAKESWAP="true"DISK_REQUIREMENTS=20960
MEMORY_REQUIREMENTS=3000
CORE_REQUIREMENTS=4DIST=""
REV=""
KERNEL=""INSTALL_REDIS="true"
INSTALL_RABBITMQ="true"
INSTALL_MYSQL_SERVER="true"
INSTALL_DOCUMENT_SERVER="true"
INSTALL_ELASTICSEARCH="true"
INSTALL_FLUENT_BIT="true"
INSTALL_PRODUCT="true"
UNINSTALL="false"
USERNAME=""
PASSWORD=""MYSQL_VERSION=""
MYSQL_DATABASE=""
MYSQL_USER=""
MYSQL_PASSWORD=""
MYSQL_ROOT_PASSWORD=""
MYSQL_HOST=""
MYSQL_PORT=""
DATABASE_MIGRATION="true"ELK_VERSION=""
ELK_SHEME=""
ELK_HOST=""
ELK_PORT=""REDIS_HOST=""
REDIS_PORT=""
REDIS_USER_NAME=""
REDIS_PASSWORD=""RABBIT_PROTOCOL=""
RABBIT_HOST=""
RABBIT_PORT=""
RABBIT_USER_NAME=""
RABBIT_PASSWORD=""DOCUMENT_SERVER_IMAGE_NAME=""
DOCUMENT_SERVER_VERSION=""
DOCUMENT_SERVER_JWT_SECRET=""
DOCUMENT_SERVER_JWT_HEADER=""
DOCUMENT_SERVER_URL_EXTERNAL=""APP_CORE_BASE_DOMAIN=""
APP_CORE_MACHINEKEY=""
ENV_EXTENSION=""
LETS_ENCRYPT_DOMAIN=""
LETS_ENCRYPT_MAIL=""
IDENTITY_ENCRYPTION_SECRET=""HELP_TARGET="install-Docker.sh"
OFFLINE_INSTALLATION="false"SKIP_HARDWARE_CHECK="false"EXTERNAL_PORT="80"while [ "$1" != "" ]; docase $1 in-u | --update )if [ "$2" != "" ]; thenUPDATE=$2shiftfi;;-reg | --registry )if [ "$2" != "" ]; thenREGISTRY_URL=$2shiftfi;;-un | --username )if [ "$2" != "" ]; thenUSERNAME=$2shiftfi;;-p | --password )if [ "$2" != "" ]; thenPASSWORD=$2shiftfi;;-ids | --installdocspace )if [ "$2" != "" ]; thenINSTALL_PRODUCT=$2shiftfi;;-idocs | --installdocs )if [ "$2" != "" ]; thenINSTALL_DOCUMENT_SERVER=$2shiftfi;;-imysql | --installmysql )if [ "$2" != "" ]; thenINSTALL_MYSQL_SERVER=$2shiftfi;; -irbt | --installrabbitmq )if [ "$2" != "" ]; thenINSTALL_RABBITMQ=$2shiftfi;;-irds | --installredis )if [ "$2" != "" ]; thenINSTALL_REDIS=$2shiftfi;;-ht | --helptarget )if [ "$2" != "" ]; thenHELP_TARGET=$2shiftfi;;-mysqld | --mysqldatabase )if [ "$2" != "" ]; thenMYSQL_DATABASE=$2shiftfi;;-mysqlrp | --mysqlrootpassword )if [ "$2" != "" ]; thenMYSQL_ROOT_PASSWORD=$2shiftfi;;-mysqlu | --mysqluser )if [ "$2" != "" ]; thenMYSQL_USER=$2shiftfi;;-mysqlh | --mysqlhost )if [ "$2" != "" ]; thenMYSQL_HOST=$2shiftfi;;-mysqlport | --mysqlport )if [ "$2" != "" ]; thenMYSQL_PORT=$2shiftfi;;-mysqlp | --mysqlpassword )if [ "$2" != "" ]; thenMYSQL_PASSWORD=$2shiftfi;;-espr | --elasticprotocol )if [ "$2" != "" ]; thenELK_SHEME=$2shiftfi;;-esh | --elastichost )if [ "$2" != "" ]; thenELK_HOST=$2shiftfi;;-esp | --elasticport )if [ "$2" != "" ]; thenELK_PORT=$2shiftfi;;-skiphc | --skiphardwarecheck )if [ "$2" != "" ]; thenSKIP_HARDWARE_CHECK=$2shiftfi;;-ep | --externalport )if [ "$2" != "" ]; thenEXTERNAL_PORT=$2shiftfi;;-dsh | --docspacehost )if [ "$2" != "" ]; thenAPP_URL_PORTAL=$2shiftfi;;-mk | --machinekey )if [ "$2" != "" ]; thenAPP_CORE_MACHINEKEY=$2shiftfi;;-env | --environment )if [ "$2" != "" ]; thenENV_EXTENSION=$2shiftfi;;-s | --status )if [ "$2" != "" ]; thenSTATUS=$2IMAGE_NAME="${PACKAGE_SYSNAME}/${STATUS}${PRODUCT}-api"shiftfi;;-ls | --localscripts )if [ "$2" != "" ]; thenshiftfi;;-dsv | --docspaceversion )if [ "$2" != "" ]; thenDOCKER_TAG=$2shiftfi;;-gb | --gitbranch )if [ "$2" != "" ]; thenPARAMETERS="$PARAMETERS ${1}"GIT_BRANCH=$2shiftfi;;-docsi | --docsimage )if [ "$2" != "" ]; thenDOCUMENT_SERVER_IMAGE_NAME=$2shiftfi;;-docsv | --docsversion )if [ "$2" != "" ]; thenDOCUMENT_SERVER_VERSION=$2shiftfi;;-docsurl | --docsurl )if [ "$2" != "" ]; thenDOCUMENT_SERVER_URL_EXTERNAL=$2shiftfi;;-dbm | --databasemigration )if [ "$2" != "" ]; thenDATABASE_MIGRATION=$2shiftfi;;-jh | --jwtheader )if [ "$2" != "" ]; thenDOCUMENT_SERVER_JWT_HEADER=$2shiftfi;;-js | --jwtsecret )if [ "$2" != "" ]; thenDOCUMENT_SERVER_JWT_SECRET=$2shiftfi;;-it | --installation_type )if [ "$2" != "" ]; thenINSTALLATION_TYPE="${2^^}"shiftfi;;-ms | --makeswap )if [ "$2" != "" ]; thenMAKESWAP=$2shiftfi;;-ies | --installelastic )if [ "$2" != "" ]; thenINSTALL_ELASTICSEARCH=$2shiftfi;;-ifb | --installfluentbit )if [ "$2" != "" ]; thenINSTALL_FLUENT_BIT=$2shiftfi;;-rdsh | --redishost )if [ "$2" != "" ]; thenREDIS_HOST=$2shiftfi;;-rdsp | --redisport )if [ "$2" != "" ]; thenREDIS_PORT=$2shiftfi;;-rdsu | --redisusername )if [ "$2" != "" ]; thenREDIS_USER_NAME=$2shiftfi;;-rdspass | --redispassword )if [ "$2" != "" ]; thenREDIS_PASSWORD=$2shiftfi;;-rbpr | --rabbitmqprotocol )if [ "$2" != "" ]; thenRABBIT_PROTOCOL=$2shiftfi;;-rbth | --rabbitmqhost )if [ "$2" != "" ]; thenRABBIT_HOST=$2shiftfi;;-rbtp | --rabbitmqport )if [ "$2" != "" ]; thenRABBIT_PORT=$2shiftfi;;-rbtu | --rabbitmqusername )if [ "$2" != "" ]; thenRABBIT_USER_NAME=$2shiftfi;;-rbtpass | --rabbitmqpassword )if [ "$2" != "" ]; thenRABBIT_PASSWORD=$2shiftfi;;-rbtvh | --rabbitmqvirtualhost )if [ "$2" != "" ]; thenRABBIT_VIRTUAL_HOST=$2shiftfi;;-led | --letsencryptdomain )if [ "$2" != "" ]; thenLETS_ENCRYPT_DOMAIN=$2shiftfi;;-lem | --letsencryptmail )if [ "$2" != "" ]; thenLETS_ENCRYPT_MAIL=$2shiftfi;;-cf | --certfile )if [ "$2" != "" ]; thenCERTIFICATE_PATH="$2"[[ "$CERTIFICATE_PATH" != /* ]] && CERTIFICATE_PATH="$(cd "$(dirname "$CERTIFICATE_PATH")" && pwd)/$(basename "$CERTIFICATE_PATH")"[ -f "$CERTIFICATE_PATH" ] || { echo "Error: Certificate file not found: ${CERTIFICATE_PATH}" >&2; exit 1; }shiftfi;;-ckf | --certkeyfile )if [ "$2" != "" ]; thenCERTIFICATE_KEY_PATH="$2"[[ "$CERTIFICATE_KEY_PATH" != /* ]] && CERTIFICATE_KEY_PATH="$(cd "$(dirname "$CERTIFICATE_KEY_PATH")" && pwd)/$(basename "$CERTIFICATE_KEY_PATH")"[ -f "$CERTIFICATE_KEY_PATH" ] || { echo "Error: Certificate key file not found: ${CERTIFICATE_KEY_PATH}" >&2; exit 1; }shiftfi;;-dhf | --dhparamfile )if [ "$2" != "" ]; thenDHPARAM_PATH="$2"[[ "$DHPARAM_PATH" != /* ]] && DHPARAM_PATH="$(cd "$(dirname "$DHPARAM_PATH")" && pwd)/$(basename "$DHPARAM_PATH")"[ -f "$DHPARAM_PATH" ] || { echo "Error: DHParam file not found: ${DHPARAM_PATH}" >&2; exit 1; }shiftfi;;-du | --dashboardsusername )if [ "$2" != "" ]; thenDASHBOARDS_USERNAME=$2shiftfi;;-dp | --dashboardspassword )if [ "$2" != "" ]; thenDASHBOARDS_PASSWORD=$2shiftfi;;-noni | --noninteractive )if [ "$2" != "" ]; thenNON_INTERACTIVE=$2shiftfi;;-uni | --uninstall)if [ "$2" != "" ]; thenUNINSTALL=$2shiftfi;;-off | --offline )if [ "$2" != "" ]; thenOFFLINE_INSTALLATION=$2shiftfi;;-vd | --volumesdir )if [ "$2" != "" ]; thenVOLUMES_DIR=$2[[ "$VOLUMES_DIR" != /* ]] && VOLUMES_DIR="$(cd "$(dirname "$VOLUMES_DIR")" && pwd)/$(basename "$VOLUMES_DIR")"[ ! -d "$VOLUMES_DIR" ] || { echo "Error: Volumes directory not found: ${VOLUMES_DIR}" >&2; exit 1; }[[ "$VOLUMES_DIR" == "$BASE_DIR"* ]] && { echo "Warning: Please change the volumes directory, as $BASE_DIR will be removed during an update."; exit 1; }shiftfi;;-h | -? | --help )echo " Usage: bash $HELP_TARGET [PARAMETER] [[PARAMETER], ...]"echoecho " Parameters:"echo " -reg, --registry docker registry URL (e.g., https://myregistry.com:5000)"echo " -un, --username docker registry login"echo " -p, --password docker registry password"echo " -it, --installation_type installation type (community|developer|enterprise)"echo " -skiphc, --skiphardwarecheck skip hardware check (true|false)"echo " -u, --update use to update existing components (true|false)"echo " -ids, --installdocspace install or update $PRODUCT (true|false)"echo " -dsv, --docspaceversion select the $PRODUCT version"echo " -dsh, --docspacehost $PRODUCT host"echo " -env, --environment $PRODUCT environment"echo " -mk, --machinekey setting for core.machinekey"echo " -ep, --externalport external $PRODUCT port (default value 80)"echo " -vd, --volumesdir directory for storing Docker volumes (default value /var/lib/docker/volumes)"echo " -idocs, --installdocs install or update document server (true|false)"echo " -docsi, --docsimage document server image name"echo " -docsv, --docsversion document server version"echo " -docsurl, --docsurl $PACKAGE_SYSNAME docs server address (example http://$PACKAGE_SYSNAME-docs-address:8083)"echo " -jh, --jwtheader defines the http header that will be used to send the JWT"echo " -js, --jwtsecret defines the secret key to validate the JWT in the request" echo " -irbt, --installrabbitmq install or update rabbitmq (true|false)" echo " -irds, --installredis install or update redis (true|false)"echo " -imysql, --installmysql install or update mysql (true|false)" echo " -ies, --installelastic install or update elasticsearch (true|false)"echo " -ifb, --installfluentbit install or update fluent-bit (true|false)"echo " -du, --dashboardsusername login for authorization in /dashboards/"echo " -dp, --dashboardspassword password for authorization in /dashboards/"echo " -espr, --elasticprotocol the protocol for the connection to elasticsearch (default value http)"echo " -esh, --elastichost the IP address or hostname of the elasticsearch"echo " -esp, --elasticport elasticsearch port number (default value 9200)"echo " -rdsh, --redishost the IP address or hostname of the redis server"echo " -rdsp, --redisport redis server port number (default value 6379)"echo " -rdsu, --redisusername redis user name"echo " -rdspass, --redispassword password set for redis account"echo " -rbpr, --rabbitmqprotocol the protocol for the connection to rabbitmq server (default value amqp)"echo " -rbth, --rabbitmqhost the IP address or hostname of the rabbitmq server"echo " -rbtp, --rabbitmqport rabbitmq server port number (default value 5672)"echo " -rbtu, --rabbitmqusername username for rabbitmq server account"echo " -rbtpass, --rabbitmqpassword password set for rabbitmq server account"echo " -rbtvh, --rabbitmqvirtualhost rabbitmq virtual host (default value \"/\")"echo " -mysqlrp, --mysqlrootpassword mysql server root password"echo " -mysqld, --mysqldatabase $PRODUCT database name"echo " -mysqlu, --mysqluser $PRODUCT database user"echo " -mysqlp, --mysqlpassword $PRODUCT database password"echo " -mysqlh, --mysqlhost mysql server host"echo " -mysqlport, --mysqlport mysql server port number (default value 3306)"echo " -led, --letsencryptdomain defines the domain for Let's Encrypt certificate"echo " -lem, --letsencryptmail defines the domain administrator mail address for Let's Encrypt certificate"echo " -cf, --certfile path to the certificate file for the domain"echo " -ckf, --certkeyfile path to the private key file for the certificate"echo " -dhf, --dhparamfile path to the dhparam file for the certificate"echo " -off, --offline set the script for offline installation (true|false)"echo " -noni, --noninteractive auto confirm all questions (true|false)"echo " -dbm, --databasemigration database migration (true|false)"echo " -ms, --makeswap make swap file (true|false)"echo " -uni, --uninstall uninstall existing installation (true|false)"echo " -?, -h, --help this help"echoecho " Install all the components without document server:"echo " bash $HELP_TARGET -idocs false"echoecho " Install Document Server only. Skip the installation of mysql, $PRODUCT, rabbitmq, redis:"echo " bash $HELP_TARGET -ids false -idocs true -imysql false -irbt false -irds false"echoecho " Update all installed components. Stop the containers that need to be updated, remove them and run the latest versions of the corresponding components."echo " The portal data should be picked up automatically:"echo " bash $HELP_TARGET -u true"echoecho " Update Document Server only to version 7.2.1.34 and skip the update for all other components:"echo " bash $HELP_TARGET -u true -docsi ${PACKAGE_SYSNAME}/documentserver-ee -docsv 7.2.1.34 -idocs true -ids false -irbt false -irds false"echoecho " Update $PRODUCT only to version 1.2.0 and skip the update for all other components:"echo " bash $HELP_TARGET -u true -dsv v1.2.0 -idocs false -irbt false -irds false"echoexit 0;;* )echo "Unknown parameter $1" 1>&2exit 1;;esacshift
doneuninstall() {read -p "Uninstall all dependencies (mysql, opensearch and others)? (Y/n): " REMOVE_DATA_SERVICESif [[ "${REMOVE_DATA_SERVICES,,}" =~ ^(y|yes)?$ ]]; thenSERVICES=("db" "rabbitmq" "redis" "opensearch" "dashboards" "fluent")fiSERVICES+=("${PRODUCT}" "ds" "identity" "proxy" "healthchecks" "notify" "migration-runner")for SERVICE in "${SERVICES[@]}"; doif [[ -f "$BASE_DIR/$SERVICE.yml" ]]; thenecho "Uninstallation of $SERVICE and its volumes..."docker-compose -f "$BASE_DIR/$SERVICE.yml" down -v || echo "Failed to remove $SERVICE."fidonedocker network rm "${NETWORK_NAME}" 2>/dev/null && NETWORK_REMOVED=true || echo "Failed to remove network ${NETWORK_NAME}."read -p "Do you want to retain data (keep .env file)? (Y/n): " KEEP_DATAif [[ "$NETWORK_REMOVED" == "true" && -d "$BASE_DIR" ]]; thenif [[ "${KEEP_DATA,,}" =~ ^(y|yes)?$ ]]; thenfind "$BASE_DIR" -mindepth 1 ! -name ".env" -exec rm -rf {} +elserm -rf "$BASE_DIR" || echo "Failed to remove directory $BASE_DIR."fifiecho -e "Uninstallation of $PRODUCT_NAME" \"$( [[ "${REMOVE_DATA_SERVICES,,}" =~ ^(y|yes)?$ ]] && echo "and all dependencies" ) \e[32mcompleted.\e[0m"
}root_checking () {PID=$$[[ $EUID -eq 0 ]] || { echo "To perform this action you must be logged in with root rights"; exit 1; }
}is_command_exists () {type "$1" &> /dev/null
}get_random_str () {local LENGTH=${1:-12}tr -dc 'A-Za-z0-9' < /dev/urandom | head -c "$LENGTH"
}get_os_info () {OS="$(uname -s | tr '[:upper:]' '[:lower:]')"case "$OS" inwindowsnt|darwin|sunos|aix)echo "Not supported OS"exit 1;;esacif [ "$OS" == "linux" ]; thenMACH=$(uname -m)if [ "${MACH}" != "x86_64" ]; thenecho "Currently only supports 64bit OS's"exit 1fiKERNEL=$(uname -r)if [ -f /etc/redhat-release ]; thenif grep -qsw release /etc/redhat-release; thenDIST=$(sed 's/ release.*//' /etc/redhat-release)REV=$(grep -oP '(?<=release )\d+' /etc/redhat-release)elseDIST=$(grep -sw 'ID' /etc/os-release | cut -d= -f2 | tr -d '"')REV=$(grep -sw 'VERSION_ID' /etc/os-release | cut -d= -f2 | tr -d '"')fielif [ -f /etc/SuSE-release ]; thenDIST='SuSe'REV=$(grep '^VERSION_ID' /etc/os-release | cut -d= -f2 | tr -d '"')elif [ -f /etc/debian_version ]; thenDIST='Debian'REV=$(cat /etc/debian_version)if [ -f /etc/lsb-release ]; thenDIST=$(grep '^DISTRIB_ID' /etc/lsb-release | cut -d= -f2 | tr -d '"')REV=$(grep '^DISTRIB_RELEASE' /etc/lsb-release | cut -d= -f2 | tr -d '"')elif command -v lsb_release > /dev/null 2>&1; thenDIST=$(lsb_release -si)REV=$(lsb_release -sr)fielif [ -f /etc/VERSION ]; thenDIST=$(grep -oP 'os_name="\K[^"]+' /etc/VERSION)REV=$(grep -oP 'majorversion="\K[^"]+' /etc/VERSION)elif [ -f /etc/os-release ]; thenDIST=$(grep -sw 'ID' /etc/os-release | cut -d= -f2 | tr -d '"')REV=$(grep -sw 'VERSION_ID' /etc/os-release | cut -d= -f2 | tr -d '"')fiDIST=$(echo "$DIST" | xargs)REV=$(echo "$REV" | xargs)fi
}check_os_info () {if [[ -z ${KERNEL} || -z ${DIST} || -z ${REV} ]]; thenecho "$KERNEL, $DIST, $REV"echo "Not supported OS"exit 1fiif [ -f /etc/needrestart/needrestart.conf ]; thensed -e "s_#\$nrconf{restart}_\$nrconf{restart}_" -e "s_\(\$nrconf{restart} =\).*_\1 'a';_" -i /etc/needrestart/needrestart.conffi
}check_kernel () {MIN_NUM_ARR=(3 10 0)CUR_NUM_ARR=()CUR_STR_ARR=$(echo "$KERNEL" | grep -Po "[0-9]+\.[0-9]+\.[0-9]+" | tr "." " ")for CUR_STR_ITEM in $CUR_STR_ARR; doCUR_NUM_ARR+=("$CUR_STR_ITEM")doneINDEX=0while [[ $INDEX -lt 3 ]]; doif [ ${CUR_NUM_ARR[INDEX]} -lt ${MIN_NUM_ARR[INDEX]} ]; thenecho "Not supported OS Kernel"exit 1elif [ ${CUR_NUM_ARR[INDEX]} -gt ${MIN_NUM_ARR[INDEX]} ]; thenINDEX=3fi(( INDEX++ ))done
}check_hardware () {AVAILABLE_DISK_SPACE=$(df -m / | tail -1 | awk '{ print $4 }')if [ ${AVAILABLE_DISK_SPACE} -lt ${DISK_REQUIREMENTS} ]; thenecho "Minimal requirements are not met: need at least $DISK_REQUIREMENTS MB of free HDD space"exit 1fiTOTAL_MEMORY=$(free --mega | grep -oP '\d+' | head -n 1)if [ ${TOTAL_MEMORY} -lt ${MEMORY_REQUIREMENTS} ]; thenecho "Minimal requirements are not met: need at least $MEMORY_REQUIREMENTS MB of RAM"exit 1fiCPU_CORES_NUMBER=$(grep -c ^processor /proc/cpuinfo)if [ ${CPU_CORES_NUMBER} -lt ${CORE_REQUIREMENTS} ]; thenecho "The system does not meet the minimal hardware requirements. CPU with at least $CORE_REQUIREMENTS cores is required"exit 1fi
}install_package () {if ! is_command_exists $1; thenlocal COMMAND_NAME=$1local PACKAGE_NAME=${2:-"$COMMAND_NAME"}local PACKAGE_NAME_APT=${PACKAGE_NAME%%|*}local PACKAGE_NAME_YUM=${PACKAGE_NAME##*|}if is_command_exists apt-get; thenapt-get -y -q install ${PACKAGE_NAME_APT:-$PACKAGE_NAME}elif is_command_exists yum; thenyum -y install ${PACKAGE_NAME_YUM:-$PACKAGE_NAME}fiis_command_exists $COMMAND_NAME || { echo "Command $COMMAND_NAME not found"; exit 1; }fi
}install_docker_compose () {curl -sL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/bin/docker-composechmod +x /usr/bin/docker-compose
}check_ports () {RESERVED_PORTS=()ARRAY_PORTS=()USED_PORTS=""if [ "${EXTERNAL_PORT//[0-9]}" = "" ]; thenfor RESERVED_PORT in "${RESERVED_PORTS[@]}"doif [ "$RESERVED_PORT" -eq "$EXTERNAL_PORT" ] ; thenecho "External port $EXTERNAL_PORT is reserved. Select another port"exit 1fidoneelseecho "Invalid external port $EXTERNAL_PORT"exit 1fiif [ "$INSTALL_PRODUCT" == "true" ]; thenARRAY_PORTS+=("$EXTERNAL_PORT")fifor PORT in "${ARRAY_PORTS[@]}"doREGEXP=":$PORT$"CHECK_RESULT=$(netstat -lnt | awk '{print $4}' | { grep $REGEXP || true; })if [[ $CHECK_RESULT != "" ]]; thenif [[ $USED_PORTS != "" ]]; thenUSED_PORTS="$USED_PORTS, $PORT"elseUSED_PORTS="$PORT"fifidoneif [[ $USED_PORTS != "" ]]; thenecho "The following TCP Ports must be available: $USED_PORTS"exit 1fi
}install_docker () {if [ "${DIST}" == "Ubuntu" ] || [ "${DIST}" == "Debian" ] || [[ "${DIST}" == CentOS* ]] || [ "${DIST}" == "Fedora" ]; thencurl -fsSL https://get.docker.com | bashsystemctl start dockersystemctl enable dockerelif [[ "${DIST}" == Red\ Hat\ Enterprise\ Linux* ]]; thenif [[ "${REV}" -gt "7" ]]; thenyum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine podman runc > nullyum install -y yum-utilsyum-config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repoyum install -y docker-ce docker-ce-cli containerd.io docker-buildx-pluginsystemctl start dockersystemctl enable dockerelseecho ""echo "Your operating system does not allow Docker CE installation."echo "You can install Docker EE using the manual here - https://docs.docker.com/engine/installation/linux/rhel/"echo ""exit 1fielif [ "${DIST}" == "SuSe" ]; thenecho ""echo "Your operating system does not allow Docker CE installation."echo "You can install Docker EE using the manual here - https://docs.docker.com/engine/installation/linux/suse/"echo ""exit 1elif [ "${DIST}" == "altlinux" ]; thenapt-get -y install docker-iochkconfig docker onservice docker startsystemctl enable dockerelif [ "${DIST}" == "DSM" ]; thensynopkg install_from_server ContainerManagersynopkg start ContainerManagerelseecho ""echo "Docker could not be installed automatically."echo "Please use this official instruction https://docs.docker.com/engine/installation/linux/other/ for its manual installation."echo ""exit 1fiif ! is_command_exists docker ; thenecho "error while installing docker"exit 1fi
}docker_login() {if [[ -n "$USERNAME" && -n "$PASSWORD" ]]; thenecho "$PASSWORD" | docker login "$REGISTRY_URL" --username "$USERNAME" --password-stdin || { echo "Docker authentication failed"; exit 1; }fi
}create_network () {NETWORK_EXIST=$(docker network ls | awk '{print $2;}' | { grep -x ${NETWORK_NAME} || true; })if [[ -z ${NETWORK_EXIST} ]]; thendocker network create --driver bridge ${NETWORK_NAME}fi
}read_continue_installation () {[ "$NON_INTERACTIVE" = "true" ] && INSTALLATION_CHOICE="Y" && return 0while true; doread -p "Continue installation [Y/C/N]? " CHOICEcase "$CHOICE" in[yY]) INSTALLATION_CHOICE="Y"; return 0 ;;[cC]) INSTALLATION_CHOICE="C"; return 0 ;;[nN]) exit 0 ;;*) echo "Please, enter Y, C or N" ;;esacdone
}domain_check () {APP_DOMAIN_PORTAL=$(cut -d ',' -f 1 <<< "$LETS_ENCRYPT_DOMAIN")APP_DOMAIN_PORTAL=${APP_DOMAIN_PORTAL:-${APP_URL_PORTAL:-$(get_env_parameter "APP_URL_PORTAL" "${PACKAGE_SYSNAME}-files" | awk -F[/:] '{if ($1 == "https") print $4; else print ""}')}}while IFS= read -r DOMAIN; doIP_ADDRESS=$( [ -n "${DOMAIN}" ] && ping -c 1 -W 1 ${DOMAIN} | grep -oP '(\d+\.\d+\.\d+\.\d+)' | head -n 1 )if [[ -n "$IP_ADDRESS" && "$IP_ADDRESS" =~ ^(10\.|127\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|192\.168\.) ]]; thenLOCAL_RESOLVED_DOMAINS+="$DOMAIN"fidone <<< "${APP_DOMAIN_PORTAL:-$(dig +short -x "$(curl -s -4 ifconfig.me)" | sed 's/\.$//')}"# check if the domain is a loopback IP or NATif [[ -n "${LOCAL_RESOLVED_DOMAINS}" ]] || [[ $(ip route get 8.8.8.8 | awk '{print $7}') != $(curl -s -4 ifconfig.me) ]]; then DOCKER_DAEMON_FILE="/etc/docker/daemon.json"if ! grep -q '"dns"' "$DOCKER_DAEMON_FILE" 2>/dev/null; thenecho "DNS issue detected for ${APP_DOMAIN_PORTAL:-$LOCAL_RESOLVED_DOMAINS} (loopback IP or NAT)."echo "[Y] Use Google DNS | [C] Use custom DNS | [N] Cancel installation"if read_continue_installation; thencase "$INSTALLATION_CHOICE" inY) DNS=("8.8.8.8" "8.8.4.4") ;;C) while true; doread -p "Enter custom DNS (e.g. 8.8.8.8 8.8.4.4): " INPUT; IFS=' ' read -ra DNS <<< "$INPUT"for IP in "${DNS[@]}"; do [[ $IP =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || { echo "Invalid DNS: $IP"; continue 2; }done && breakdone ;;esacif ((${#DNS[@]})); thenecho "Updating Docker DNS config with: ${DNS[*]}"jq -e . "${DOCKER_DAEMON_FILE}" > /dev/null 2>&1 || echo '{}' > "${DOCKER_DAEMON_FILE}"echo "$(jq --argjson dns "$(printf '%s\n' "${DNS[@]}" | jq -R . | jq -s .)" '.dns = $dns' "${DOCKER_DAEMON_FILE}")" > "${DOCKER_DAEMON_FILE}"systemctl restart docker || { echo "Failed to restart Docker service"; exit 1; }fifififiAPP_URL_PORTAL=${APP_DOMAIN_PORTAL:+http://${APP_DOMAIN_PORTAL}:${EXTERNAL_PORT}}
}establish_conn() {echo -n "Trying to establish $3 connection... "exec {FD}<> /dev/tcp/${1}/${2} && { exec {FD}>&-; echo "OK"; } || { echo "FAILURE"; exit 1; }
}get_env_parameter () {local PARAMETER_NAME=$1local CONTAINER_NAME=$2if [[ -z ${PARAMETER_NAME} ]]; thenecho "Empty parameter name"exit 1fiif is_command_exists docker ; then[ -n "$CONTAINER_NAME" ] && CONTAINER_EXIST=$(docker ps -aqf "name=$CONTAINER_NAME")if [[ -n ${CONTAINER_EXIST} ]]; thenVALUE=$(docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' ${CONTAINER_NAME} | grep "${PARAMETER_NAME}=" | sed 's/^.*=//')fifiif [ -z ${VALUE} ] && [ -f ${BASE_DIR}/.env ]; thenVALUE=$(awk -F= "/${PARAMETER_NAME}/ {print \$2}" ${BASE_DIR}/.env | tr -d '\r')fiecho ${VALUE//\"}
}get_tag_from_registry () {if [[ -n ${REGISTRY_URL} ]]; thenif [[ -n ${USERNAME} && -n ${PASSWORD} ]]; thenCREDENTIALS=$(echo -n "$USERNAME:$PASSWORD" | base64)elif [[ -f "$HOME/.docker/config.json" ]]; thenCREDENTIALS=$(jq -r --arg registry "${REGISTRY_URL}" '.auths | to_entries[] | select(.key | contains($registry)).value.auth // empty' "$HOME/.docker/config.json")fiAUTH_HEADER=${CREDENTIALS:+Authorization: Basic $CREDENTIALS}REGISTRY_TAGS_URL="${REGISTRY_URL%/}/v2/${1}/tags/list"JQ_FILTER='.tags | join("\n")'elseif [[ -n ${USERNAME} && -n ${PASSWORD} ]]; thenCREDENTIALS="{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}"TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d "$CREDENTIALS" https://hub.docker.com/v2/users/login/ | jq -r '.token')AUTH_HEADER="Authorization: JWT $TOKEN"sleep 1fiREGISTRY_TAGS_URL="https://hub.docker.com/v2/repositories/${1}/tags/"JQ_FILTER='.results[].name // empty'fimapfile -t TAGS_RESP < <(curl -s -H "${AUTH_HEADER}" -X GET "${REGISTRY_TAGS_URL}" | jq -r "${JQ_FILTER}")
}get_available_version () {[ "${OFFLINE_INSTALLATION}" = "false" ] && get_tag_from_registry ${1} || mapfile -t TAGS_RESP < <(docker images --format "{{.Tag}}" "${1}")VERSION_REGEX='^[0-9]+\.[0-9]+(\.[0-9]+){0,2}$'[ ${#TAGS_RESP[@]} -eq 1 ] && LATEST_TAG="${TAGS_RESP[0]}" || LATEST_TAG=$(printf "%s\n" "${TAGS_RESP[@]}" | grep -E "$VERSION_REGEX" | sort -V | tail -n 1)LATEST_TAG=${LATEST_TAG:-${STATUS:+$(printf "%s\n" "${TAGS_RESP[@]}" | sort -V | tail -n 1)}} #Fix for 4testing develop tagsif [ ! -z "${LATEST_TAG}" ]; thenecho "${LATEST_TAG}" | sed "s/\"//g"elseif [ "${OFFLINE_INSTALLATION}" = "false" ]; thenecho "Unable to retrieve tag from ${1} repository" >&2elseecho "Error: The image '${1}' is not found in the local Docker registry." >&2fikill -s TERM $PIDfi
}set_docs_url_external () {DOCUMENT_SERVER_URL_EXTERNAL=${DOCUMENT_SERVER_URL_EXTERNAL:-$(get_env_parameter "DOCUMENT_SERVER_URL_EXTERNAL" "${CONTAINER_NAME}")}if [[ ! -z ${DOCUMENT_SERVER_URL_EXTERNAL} ]] && [[ $DOCUMENT_SERVER_URL_EXTERNAL =~ ^(https?://)?([^:/]+)(:([0-9]+))?(/.*)?$ ]]; then[[ -z ${BASH_REMATCH[1]} ]] && DOCUMENT_SERVER_URL_EXTERNAL="http://$DOCUMENT_SERVER_URL_EXTERNAL"DOCUMENT_SERVER_PROTOCOL="${BASH_REMATCH[1]}"DOCUMENT_SERVER_HOST="${BASH_REMATCH[2]}"DOCUMENT_SERVER_PORT="${BASH_REMATCH[4]:-"80"}"fi
}set_jwt_secret () {DOCUMENT_SERVER_JWT_SECRET="${DOCUMENT_SERVER_JWT_SECRET:-$(get_env_parameter "JWT_SECRET" "${PACKAGE_SYSNAME}-document-server")}"DOCUMENT_SERVER_JWT_SECRET="${DOCUMENT_SERVER_JWT_SECRET:-$(get_env_parameter "DOCUMENT_SERVER_JWT_SECRET" "${CONTAINER_NAME}")}"DOCUMENT_SERVER_JWT_SECRET="${DOCUMENT_SERVER_JWT_SECRET:-$(get_random_str 32)}"
}set_jwt_header () {DOCUMENT_SERVER_JWT_HEADER="${DOCUMENT_SERVER_JWT_HEADER:-$(get_env_parameter "JWT_HEADER" "${PACKAGE_SYSNAME}-document-server")}"DOCUMENT_SERVER_JWT_HEADER="${DOCUMENT_SERVER_JWT_HEADER:-$(get_env_parameter "DOCUMENT_SERVER_JWT_HEADER" "${CONTAINER_NAME}")}"DOCUMENT_SERVER_JWT_HEADER="${DOCUMENT_SERVER_JWT_HEADER:-"AuthorizationJwt"}"
}set_secrets () {APP_CORE_MACHINEKEY="${APP_CORE_MACHINEKEY:-$(get_env_parameter "APP_CORE_MACHINEKEY" "${CONTAINER_NAME}")}"[ "$UPDATE" != "true" ] && APP_CORE_MACHINEKEY="${APP_CORE_MACHINEKEY:-$(get_random_str 12)}"IDENTITY_ENCRYPTION_SECRET="${IDENTITY_ENCRYPTION_SECRET:-$(get_env_parameter "IDENTITY_ENCRYPTION_SECRET" "${IDENTITY_CONTAINER_NAME}")}"[ "${UPDATE}" = "true" ] && IDENTITY_ENCRYPTION_SECRET="${IDENTITY_ENCRYPTION_SECRET:-"secret"}" # (DS v3.1.0) fix encryption key generation issueIDENTITY_ENCRYPTION_SECRET="${IDENTITY_ENCRYPTION_SECRET:-$(get_random_str 12)}"
}set_mysql_params () {MYSQL_PASSWORD="${MYSQL_PASSWORD:-$(get_env_parameter "MYSQL_PASSWORD" "${CONTAINER_NAME}")}"MYSQL_PASSWORD="${MYSQL_PASSWORD:-$(get_random_str 20)}"MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-$(get_env_parameter "MYSQL_ROOT_PASSWORD" "${CONTAINER_NAME}")}"MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-$(get_random_str 20)}"MYSQL_DATABASE="${MYSQL_DATABASE:-$(get_env_parameter "MYSQL_DATABASE" "${CONTAINER_NAME}")}"MYSQL_USER="${MYSQL_USER:-$(get_env_parameter "MYSQL_USER" "${CONTAINER_NAME}")}"MYSQL_HOST="${MYSQL_HOST:-$(get_env_parameter "MYSQL_HOST" "${CONTAINER_NAME}")}"MYSQL_PORT="${MYSQL_PORT:-$(get_env_parameter "MYSQL_PORT" "${CONTAINER_NAME}")}"
}set_docspace_params() {REGISTRY=${REGISTRY:-$(get_env_parameter "REGISTRY")}ENV_EXTENSION=${ENV_EXTENSION:-$(get_env_parameter "ENV_EXTENSION" "${CONTAINER_NAME}")}VOLUMES_DIR=${VOLUMES_DIR:-$(get_env_parameter "VOLUMES_DIR")}APP_CORE_BASE_DOMAIN=${APP_CORE_BASE_DOMAIN:-$(get_env_parameter "APP_CORE_BASE_DOMAIN" "${CONTAINER_NAME}")}EXTERNAL_PORT=${EXTERNAL_PORT:-$(get_env_parameter "EXTERNAL_PORT" "${CONTAINER_NAME}")}PREVIOUS_ELK_VERSION=$(get_env_parameter "ELK_VERSION")ELK_SHEME=${ELK_SHEME:-$(get_env_parameter "ELK_SHEME" "${CONTAINER_NAME}")}ELK_HOST=${ELK_HOST:-$(get_env_parameter "ELK_HOST" "${CONTAINER_NAME}")}ELK_PORT=${ELK_PORT:-$(get_env_parameter "ELK_PORT" "${CONTAINER_NAME}")}REDIS_HOST=${REDIS_HOST:-$(get_env_parameter "REDIS_HOST" "${CONTAINER_NAME}")}REDIS_PORT=${REDIS_PORT:-$(get_env_parameter "REDIS_PORT" "${CONTAINER_NAME}")}REDIS_USER_NAME=${REDIS_USER_NAME:-$(get_env_parameter "REDIS_USER_NAME" "${CONTAINER_NAME}")}REDIS_PASSWORD=${REDIS_PASSWORD:-$(get_env_parameter "REDIS_PASSWORD" "${CONTAINER_NAME}")}RABBIT_HOST=${RABBIT_HOST:-$(get_env_parameter "RABBIT_HOST" "${CONTAINER_NAME}")}RABBIT_PORT=${RABBIT_PORT:-$(get_env_parameter "RABBIT_PORT" "${CONTAINER_NAME}")}RABBIT_USER_NAME=${RABBIT_USER_NAME:-$(get_env_parameter "RABBIT_USER_NAME" "${CONTAINER_NAME}")}RABBIT_PASSWORD=${RABBIT_PASSWORD:-$(get_env_parameter "RABBIT_PASSWORD" "${CONTAINER_NAME}")}RABBIT_VIRTUAL_HOST=${RABBIT_VIRTUAL_HOST:-$(get_env_parameter "RABBIT_VIRTUAL_HOST" "${CONTAINER_NAME}")}DASHBOARDS_USERNAME=${DASHBOARDS_USERNAME:-$(get_env_parameter "DASHBOARDS_USERNAME" "${CONTAINER_NAME}")}DASHBOARDS_PASSWORD=${DASHBOARDS_PASSWORD:-$(get_env_parameter "DASHBOARDS_PASSWORD" "${CONTAINER_NAME}")}CERTIFICATE_PATH=${CERTIFICATE_PATH:-$(get_env_parameter "CERTIFICATE_PATH")}CERTIFICATE_KEY_PATH=${CERTIFICATE_KEY_PATH:-$(get_env_parameter "CERTIFICATE_KEY_PATH")}DHPARAM_PATH=${DHPARAM_PATH:-$(get_env_parameter "DHPARAM_PATH")}
}set_installation_type_data () {is_command_exists docker && UPDATE=${UPDATE:-$(test -n "$(docker ps -aqf name=${CONTAINER_NAME})" && echo true)}if [ -z "${DOCUMENT_SERVER_IMAGE_NAME}" ]; thenDOCUMENT_SERVER_IMAGE_NAME="${PACKAGE_SYSNAME}/${STATUS}documentserver"case "${INSTALLATION_TYPE}" in"DEVELOPER") DOCUMENT_SERVER_IMAGE_NAME+="-de" ;;"ENTERPRISE") DOCUMENT_SERVER_IMAGE_NAME+="-ee" ;;esacfi
}download_files () {[ "${OFFLINE_INSTALLATION}" = "false" ] && echo -n "Downloading configuration files to ${BASE_DIR}..." || echo "Unzip docker.tar.gz to ${BASE_DIR}..."rm -rf "${BASE_DIR:?}"mkdir -p ${BASE_DIR}if [ "${OFFLINE_INSTALLATION}" = "false" ]; thenif [ -z "${GIT_BRANCH}" ]; thenDOWNLOAD_URL="https://download.${PACKAGE_SYSNAME}.com/${PRODUCT}/docker.tar.gz"elseDOWNLOAD_URL="https://github.com/${PACKAGE_SYSNAME}/${PRODUCT}-buildtools/archive/${GIT_BRANCH}.tar.gz"STRIP_COMPONENTS="--strip-components=3 --wildcards */install/docker/*"ficurl -sL "${DOWNLOAD_URL}" | tar -xzf - -C "${BASE_DIR}" ${STRIP_COMPONENTS}elseif [ -f "$(dirname "$0")/docker.tar.gz" ]; thentar -xf "$(dirname "$0")/docker.tar.gz" -C "${BASE_DIR}"elseecho "Error: docker.tar.gz not found in the same directory as the script."echo "You need to download the docker.tar.gz file from https://download.${PACKAGE_SYSNAME}.com/${PRODUCT}/docker.tar.gz"exit 1fifiecho "OK"
}reconfigure () {local VARIABLE_NAME="$1"local VARIABLE_VALUE="$2"if [[ -n ${VARIABLE_VALUE} ]]; thensed -i "s~${VARIABLE_NAME}=.*~${VARIABLE_NAME}=${VARIABLE_VALUE}~g" $BASE_DIR/.envfi
}install_mysql_server () {reconfigure DATABASE_MIGRATION ${DATABASE_MIGRATION}reconfigure MYSQL_DATABASE ${MYSQL_DATABASE}reconfigure MYSQL_USER ${MYSQL_USER}reconfigure MYSQL_PASSWORD ${MYSQL_PASSWORD}reconfigure MYSQL_ROOT_PASSWORD ${MYSQL_ROOT_PASSWORD}if [[ -z ${MYSQL_HOST} ]] && [ "$INSTALL_MYSQL_SERVER" == "true" ]; thenif [ -n "${VOLUMES_DIR}" ]; thenmkdir -p "${VOLUMES_DIR}/mysql_data"chown $(docker run --rm "$(docker-compose -f ${BASE_DIR}/db.yml config | awk '/image:/ {print $2; exit}')" stat -c '%u:%g' /var/lib/mysql) "${VOLUMES_DIR}/mysql_data"chmod $(docker run --rm "$(docker-compose -f ${BASE_DIR}/db.yml config | awk '/image:/ {print $2; exit}')" stat -c '%a' /var/lib/mysql) "${VOLUMES_DIR}/mysql_data"fidocker-compose -f $BASE_DIR/db.yml up -d --force-recreateelif [ "$INSTALL_MYSQL_SERVER" == "pull" ]; thendocker-compose -f $BASE_DIR/db.yml pullfi
}install_document_server () {reconfigure DOCUMENT_SERVER_JWT_HEADER ${DOCUMENT_SERVER_JWT_HEADER}reconfigure DOCUMENT_SERVER_JWT_SECRET ${DOCUMENT_SERVER_JWT_SECRET}if [[ -z ${DOCUMENT_SERVER_HOST} ]] && [ "$INSTALL_DOCUMENT_SERVER" == "true" ]; thendocker-compose -f $BASE_DIR/ds.yml up -delif [ "$INSTALL_DOCUMENT_SERVER" == "pull" ]; thendocker-compose -f $BASE_DIR/ds.yml pullfi
}install_rabbitmq () {if [[ -z ${RABBIT_HOST} ]] && [ "$INSTALL_RABBITMQ" == "true" ]; thendocker-compose -f $BASE_DIR/rabbitmq.yml up -delif [ "$INSTALL_RABBITMQ" == "pull" ]; thendocker-compose -f $BASE_DIR/rabbitmq.yml pullfi
}install_redis () {if [[ -z ${REDIS_HOST} ]] && [ "$INSTALL_REDIS" == "true" ]; thendocker-compose -f $BASE_DIR/redis.yml up -delif [ "$INSTALL_REDIS" == "pull" ]; thendocker-compose -f $BASE_DIR/redis.yml pullfi
}install_elasticsearch () {if [[ -z ${ELK_HOST} ]] && [ "$INSTALL_ELASTICSEARCH" == "true" ]; thenif [ -n "${VOLUMES_DIR}" ]; thenmkdir -p "${VOLUMES_DIR}/os_data"chown $(docker run --rm "$(docker-compose -f ${BASE_DIR}/opensearch.yml config | awk '/image:/ {print $2; exit}')" stat -c '%u:%g' /usr/share/opensearch/data) "${VOLUMES_DIR}/os_data"fiSAFE_MEMORY=$(( ( $(free --mega | grep -oP '\d+' | head -n 1) - 1024 ) / 2 )) # half of the remaining memory after the 1 GB reserve for the OSHEAP=$(( SAFE_MEMORY < 2048 ? 1 : SAFE_MEMORY < 4096 ? 2 : 4 )) #if <2GB → 1GB; <4GB → 2GB; otherwise → 4GBsed -i "s/Xms[0-9]g/Xms${HEAP}g/g; s/Xmx[0-9]g/Xmx${HEAP}g/g" $BASE_DIR/opensearch.ymldocker-compose -f $BASE_DIR/opensearch.yml up -delif [ "$INSTALL_ELASTICSEARCH" == "pull" ]; thendocker-compose -f $BASE_DIR/opensearch.yml pullfi
}install_fluent_bit () {if [ "$INSTALL_FLUENT_BIT" == "true" ]; then[ ! -z "$ELK_HOST" ] && sed -i "s/ELK_CONTAINER_NAME/ELK_HOST/g" $BASE_DIR/fluent.yml ${BASE_DIR}/dashboards.ymlOPENSEARCH_INDEX="${OPENSEARCH_INDEX:-"${PACKAGE_SYSNAME}-fluent-bit"}"if crontab -l | grep -q "${OPENSEARCH_INDEX}"; thencrontab -l | grep -v "${OPENSEARCH_INDEX}" | crontab -fi(crontab -l 2>/dev/null; echo "0 0 */1 * * curl -s -X POST $(get_env_parameter 'ELK_SHEME')://${ELK_HOST:-127.0.0.1}:$(get_env_parameter 'ELK_PORT')/${OPENSEARCH_INDEX}/_delete_by_query -H 'Content-Type: application/json' -d '{\"query\": {\"range\": {\"@timestamp\": {\"lt\": \"now-30d\"}}}}'") | crontab -sed -i "s/OPENSEARCH_HOST/${ELK_HOST:-"${PACKAGE_SYSNAME}-opensearch"}/g" "${BASE_DIR}/config/fluent-bit.conf"sed -i "s/OPENSEARCH_PORT/$(get_env_parameter "ELK_PORT")/g" ${BASE_DIR}/config/fluent-bit.confsed -i "s/OPENSEARCH_INDEX/${OPENSEARCH_INDEX}/g" ${BASE_DIR}/config/fluent-bit.confreconfigure DASHBOARDS_USERNAME "${DASHBOARDS_USERNAME:-"${PACKAGE_SYSNAME}"}"reconfigure DASHBOARDS_PASSWORD "${DASHBOARDS_PASSWORD:-$(get_random_str 20)}"docker-compose -f ${BASE_DIR}/fluent.yml -f ${BASE_DIR}/dashboards.yml up -delif [ "$INSTALL_FLUENT_BIT" == "pull" ]; thendocker-compose -f ${BASE_DIR}/fluent.yml -f ${BASE_DIR}/dashboards.yml pullfi
}install_product () {if [ "$INSTALL_PRODUCT" == "true" ]; then[ "${UPDATE}" = "true" ] && LOCAL_CONTAINER_TAG="$(docker inspect --format='{{index .Config.Image}}' ${CONTAINER_NAME} | awk -F':' '{print $2}')"if [ "${UPDATE}" = "true" ] && [ "${LOCAL_CONTAINER_TAG}" != "${DOCKER_TAG}" ]; thendocker-compose -f $BASE_DIR/build.yml pulldocker-compose -f $BASE_DIR/migration-runner.yml -f $BASE_DIR/identity.yml -f $BASE_DIR/notify.yml -f $BASE_DIR/healthchecks.yml -f ${PROXY_YML} downdocker-compose -f $BASE_DIR/${PRODUCT}.yml downfireconfigure ENV_EXTENSION ${ENV_EXTENSION}reconfigure IDENTITY_PROFILE "${IDENTITY_PROFILE:-"prod,server"}"reconfigure APP_CORE_MACHINEKEY ${APP_CORE_MACHINEKEY}reconfigure IDENTITY_ENCRYPTION_SECRET ${IDENTITY_ENCRYPTION_SECRET}reconfigure APP_CORE_BASE_DOMAIN ${APP_CORE_BASE_DOMAIN}reconfigure APP_URL_PORTAL "${APP_URL_PORTAL:-"http://${PACKAGE_SYSNAME}-router:8092"}"reconfigure EXTERNAL_PORT ${EXTERNAL_PORT}if [[ -z ${MYSQL_HOST} ]] && [ "$INSTALL_MYSQL_SERVER" == "true" ] && [[ -n $(docker ps -q --filter "name=${PACKAGE_SYSNAME}-mysql-server") ]]; thenecho -n "Waiting for MySQL container to become healthy..."(timeout 30 bash -c "while ! docker inspect --format '{{json .State.Health.Status }}' ${PACKAGE_SYSNAME}-mysql-server | grep -q 'healthy'; do sleep 1; done") && echo "OK" || (echo "FAILED")fidocker-compose -f $BASE_DIR/migration-runner.yml up -dif [[ -n $(docker ps -q --filter "name=${PACKAGE_SYSNAME}-migration-runner") ]]; thenecho -n "Waiting for database migration to complete..."timeout 30 bash -c "while [ $(docker wait ${PACKAGE_SYSNAME}-migration-runner) -ne 0 ]; do sleep 1; done;" && echo "OK" || echo "FAILED"fidocker-compose -f $BASE_DIR/identity.yml up -ddocker-compose -f $BASE_DIR/${PRODUCT}.yml up -ddocker-compose -f ${PROXY_YML} up -ddocker-compose -f $BASE_DIR/notify.yml up -ddocker-compose -f $BASE_DIR/healthchecks.yml up -dif [[ -n "${PREVIOUS_ELK_VERSION}" && "$(get_env_parameter "ELK_VERSION")" != "${PREVIOUS_ELK_VERSION}" ]]; thendocker ps -q -f name=${PACKAGE_SYSNAME}-elasticsearch | xargs -r docker stopMYSQL_TAG=$(docker images --format "{{.Tag}}" mysql | head -n1)MYSQL_CONTAINER_NAME=$(get_env_parameter "MYSQL_CONTAINER_NAME" | sed "s/\${CONTAINER_PREFIX}/${PACKAGE_SYSNAME}-/g")docker run --rm --network="$(get_env_parameter "NETWORK_NAME")" mysql:${MYSQL_TAG:-latest} mysql -h "${MYSQL_HOST:-${MYSQL_CONTAINER_NAME}}" -P "${MYSQL_PORT:-3306}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" -e "TRUNCATE webstudio_index;"fiif [ ! -z "${CERTIFICATE_PATH}" ] && [[ ! -z "${APP_DOMAIN_PORTAL}" ]]; thenenv ${DHPARAM_PATH:+DHPARAM_PATH="$DHPARAM_PATH"} \bash $BASE_DIR/config/${PRODUCT}-ssl-setup -f "${APP_DOMAIN_PORTAL}" "${CERTIFICATE_PATH}" "${CERTIFICATE_KEY_PATH}"elif [ ! -z "${LETS_ENCRYPT_DOMAIN}" ] && [ ! -z "${LETS_ENCRYPT_MAIL}" ]; thenenv ${DHPARAM_PATH:+DHPARAM_PATH="$DHPARAM_PATH"} \bash $BASE_DIR/config/${PRODUCT}-ssl-setup "${LETS_ENCRYPT_MAIL}" "${LETS_ENCRYPT_DOMAIN}"#Fix for bug 70537 to ensure proper migration to version 3.0.0fiif [ "${UPDATE}" = "true" ] && [ -f "/etc/cron.d/${PRODUCT}-letsencrypt" ]; thenbash $BASE_DIR/config/${PRODUCT}-ssl-setup -relif [[ -n "$CERTIFICATE_KEY_PATH" || -n "$CERTIFICATE_PATH" || -n "$LETS_ENCRYPT_DOMAIN" || -n "$LETS_ENCRYPT_MAIL" ]]; thenecho -e "\e[31mERROR:\e[0m Missing required parameters for SSL setup"echo "Run 'bash $BASE_DIR/config/${PRODUCT}-ssl-setup --help' for usage information."fielif [ "$INSTALL_PRODUCT" == "pull" ]; thendocker-compose -f $BASE_DIR/identity.yml pulldocker-compose -f $BASE_DIR/migration-runner.yml pulldocker-compose -f $BASE_DIR/${PRODUCT}.yml pulldocker-compose -f ${PROXY_YML} pulldocker-compose -f $BASE_DIR/notify.yml pulldocker-compose -f $BASE_DIR/healthchecks.yml pullfi
}make_swap () {DISK_REQUIREMENTS=6144 #6Gb free spaceMEMORY_REQUIREMENTS=12000 #RAM ~12GbAVAILABLE_DISK_SPACE=$(df -m / | tail -1 | awk '{ print $4 }')TOTAL_MEMORY=$(free --mega | grep -oP '\d+' | head -n 1)EXIST=$(swapon -s | awk '{ print $1 }' | { grep -x ${SWAPFILE} || true; })if [[ -z $EXIST ]] && [ ${TOTAL_MEMORY} -lt ${MEMORY_REQUIREMENTS} ] && [ ${AVAILABLE_DISK_SPACE} -gt ${DISK_REQUIREMENTS} ]; thenif [ "${DIST}" == "Ubuntu" ] || [ "${DIST}" == "Debian" ]; thenfallocate -l 6G ${SWAPFILE}elsedd if=/dev/zero of=${SWAPFILE} count=6144 bs=1MiBfichmod 600 ${SWAPFILE}mkswap ${SWAPFILE}swapon ${SWAPFILE}echo "$SWAPFILE none swap sw 0 0" >> /etc/fstabfi
}offline_check_docker_image() {[ ! -f "$1" ] && { echo "Error: File '$1' does not exist."; exit 1; }docker-compose -f "$1" config | grep -oP 'image:\s*\K\S+' | while IFS= read -r IMAGE_TAG; dodocker images "${IMAGE_TAG}" | grep -q "${IMAGE_TAG%%:*}" || { echo "Error: The image '${IMAGE_TAG}' is not found in the local Docker registry."; kill -s TERM $PID; }done
}check_registry_connection() {get_tag_from_registry ${IMAGE_NAME}[ -z "${TAGS_RESP[*]}" ] && { echo -e "Unable to download tags from ${REGISTRY_URL:-https://hub.docker.com}.\nTry specifying another docker registry URL using -reg"; exit 1; }
}dependency_installation() {is_command_exists apt-get && apt-get -y update -qqinstall_package tarinstall_package curlinstall_package netstat net-toolsif [ "${OFFLINE_INSTALLATION}" = "false" ]; theninstall_package dig "dnsutils|bind-utils"install_package ping "iputils-ping|iputils"install_package ip "iproute2|iproute"fi[ "$INSTALL_FLUENT_BIT" = "true" ] && install_package crontab "cron|cronie"if ! is_command_exists jq ; thenif is_command_exists yum && ! rpm -q epel-release > /dev/null 2>&1; then[ "${OFFLINE_INSTALLATION}" = "false" ] && rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-${REV}.noarch.rpmfiinstall_package jqfiif ! is_command_exists docker || [ "$(docker --version | awk -F'[ ,.]' '{print $3}')" -lt 18 ]; then[ "${OFFLINE_INSTALLATION}" = "false" ] && install_docker || { echo "docker not installed or outdated version"; exit 1; }elsesystemctl start dockerfiif ! is_command_exists docker-compose || [ $(docker-compose -v | awk '{sub(/^v/,"",$NF);split($NF,a,".");printf "%d%03d%03d",a[1],a[2],a[3]}') -lt 2018000 ]; then[ "${OFFLINE_INSTALLATION}" = "false" ] && install_docker_compose || { echo "docker-compose not installed or outdated version"; exit 1; }fi
}check_docker_image () {reconfigure REGISTRY "${REGISTRY_URL:+$(sed -E 's~^https?://~~; s~/*$~~' <<< "$REGISTRY_URL")/}"reconfigure STATUS ${STATUS}reconfigure INSTALLATION_TYPE ${INSTALLATION_TYPE}reconfigure NETWORK_NAME ${NETWORK_NAME}reconfigure VOLUMES_DIR ${VOLUMES_DIR}reconfigure MYSQL_VERSION ${MYSQL_VERSION}reconfigure ELK_VERSION ${ELK_VERSION}reconfigure DOCUMENT_SERVER_IMAGE_NAME "${DOCUMENT_SERVER_IMAGE_NAME}:\${DOCUMENT_SERVER_VERSION}"reconfigure DOCUMENT_SERVER_VERSION ${DOCUMENT_SERVER_VERSION:-$(get_available_version "$DOCUMENT_SERVER_IMAGE_NAME")}DOCKER_TAG="${DOCKER_TAG:-$(get_available_version ${IMAGE_NAME})}"reconfigure DOCKER_TAG ${DOCKER_TAG}if [ "${OFFLINE_INSTALLATION}" != "false" ]; then[ "$INSTALL_RABBITMQ" == "true" ] && offline_check_docker_image ${BASE_DIR}/db.yml[ "$INSTALL_RABBITMQ" == "true" ] && offline_check_docker_image ${BASE_DIR}/rabbitmq.yml[ "$INSTALL_REDIS" == "true" ] && offline_check_docker_image ${BASE_DIR}/redis.yml[ "$INSTALL_FLUENT_BIT" == "true" ] && offline_check_docker_image ${BASE_DIR}/fluent.yml[ "$INSTALL_FLUENT_BIT" == "true" ] && offline_check_docker_image ${BASE_DIR}/dashboards.yml[ "$INSTALL_ELASTICSEARCH" == "true" ] && offline_check_docker_image ${BASE_DIR}/opensearch.yml[ "$INSTALL_DOCUMENT_SERVER" == "true" ] && offline_check_docker_image ${BASE_DIR}/ds.ymlif [ "$INSTALL_PRODUCT" == "true" ]; thenoffline_check_docker_image ${BASE_DIR}/migration-runner.ymloffline_check_docker_image ${BASE_DIR}/identity.ymloffline_check_docker_image ${BASE_DIR}/${PRODUCT}.ymloffline_check_docker_image ${BASE_DIR}/notify.ymloffline_check_docker_image ${BASE_DIR}/healthchecks.ymloffline_check_docker_image ${PROXY_YML}fifi
}services_check_connection () {# Fixes issues with variables when upgrading to v1.1.3HOSTS=("ELK_HOST" "REDIS_HOST" "RABBIT_HOST" "MYSQL_HOST")for HOST in "${HOSTS[@]}"; do [[ "${!HOST}" == *CONTAINER_PREFIX* || "${!HOST}" == *$PACKAGE_SYSNAME* ]] && export "$HOST="; done[[ "${APP_URL_PORTAL}" == *${PACKAGE_SYSNAME}-proxy* ]] && APP_URL_PORTAL=""if [[ ! -z "$MYSQL_HOST" ]]; thenestablish_conn ${MYSQL_HOST} "${MYSQL_PORT:-3306}" "MySQL"reconfigure MYSQL_HOST ${MYSQL_HOST}reconfigure MYSQL_PORT "${MYSQL_PORT:-3306}"fiif [[ ! -z "$DOCUMENT_SERVER_HOST" ]]; thenAPP_URL_PORTAL=${APP_URL_PORTAL:-"http://$(curl -s -4 ifconfig.me):${EXTERNAL_PORT}"}establish_conn ${DOCUMENT_SERVER_HOST} ${DOCUMENT_SERVER_PORT} "${PACKAGE_SYSNAME^^} Docs"reconfigure DOCUMENT_SERVER_URL_EXTERNAL ${DOCUMENT_SERVER_URL_EXTERNAL}reconfigure DOCUMENT_SERVER_URL_PUBLIC ${DOCUMENT_SERVER_URL_EXTERNAL}fiif [[ ! -z "$RABBIT_HOST" ]]; thenestablish_conn ${RABBIT_HOST} "${RABBIT_PORT:-5672}" "RabbitMQ"reconfigure RABBIT_PROTOCOL ${RABBIT_PROTOCOL:-amqp}reconfigure RABBIT_HOST ${RABBIT_HOST}reconfigure RABBIT_PORT "${RABBIT_PORT:-5672}"reconfigure RABBIT_USER_NAME ${RABBIT_USER_NAME}reconfigure RABBIT_PASSWORD ${RABBIT_PASSWORD}reconfigure RABBIT_VIRTUAL_HOST "${RABBIT_VIRTUAL_HOST:-/}"fiif [[ ! -z "$REDIS_HOST" ]]; thenestablish_conn ${REDIS_HOST} "${REDIS_PORT:-6379}" "Redis"reconfigure REDIS_HOST ${REDIS_HOST}reconfigure REDIS_PORT "${REDIS_PORT:-6379}"reconfigure REDIS_USER_NAME ${REDIS_USER_NAME}reconfigure REDIS_PASSWORD ${REDIS_PASSWORD}fiif [[ ! -z "$ELK_HOST" ]]; thenestablish_conn ${ELK_HOST} "${ELK_PORT:-9200}" "search engine"reconfigure ELK_SHEME "${ELK_SHEME:-http}"reconfigure ELK_HOST ${ELK_HOST}reconfigure ELK_PORT "${ELK_PORT:-9200}"fi
}start_installation () {root_checkingset_installation_type_dataget_os_infocheck_os_infocheck_kerneldependency_installationif [ "$UPDATE" != "true" ]; thencheck_portsfiif [ "$SKIP_HARDWARE_CHECK" != "true" ]; thencheck_hardwarefiif [ "$MAKESWAP" == "true" ]; thenmake_swapfidocker_login[ "${OFFLINE_INSTALLATION}" = "false" ] && check_registry_connectioncreate_network[ "${OFFLINE_INSTALLATION}" = "false" ] && domain_checkif [ "$UPDATE" = "true" ]; thenset_docspace_paramsfiset_docs_url_externalset_jwt_secretset_jwt_headerset_secretsset_mysql_paramsdownload_filescheck_docker_imageservices_check_connectioninstall_elasticsearchinstall_fluent_bitinstall_mysql_serverinstall_rabbitmqinstall_redisinstall_document_serverinstall_productecho ""echo "Thank you for installing ${PACKAGE_SYSNAME^^} ${PRODUCT_NAME}."echo "In case you have any questions contact us via http://support.${PACKAGE_SYSNAME}.com or visit our forum at http://forum.${PACKAGE_SYSNAME}.com"echo ""exit 0
}[[ $UNINSTALL != true ]] && start_installation || uninstall
三、
正式安装docspace
安装命令
也可以指定onlyoffice_documentserver的版本来安装,例如:
bash install-Docker.sh -off true -skiphc true -docsv 9.0.4.1 -ep 1888 -it community
这个时候是使用本地已经有的onlyoffice_documentserver镜像,版本为9.0.4.1,如果想使用onlyoffice_documentserver版本为6.1.1,那么,本地导入此版本镜像就可以了
上面的命令修改为:
bash install-Docker.sh -off true -skiphc true -docsv 6.1.1 -ep 1888 -it community
本次案例导入的所有镜像:
[root@centos14 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
onlyoffice/documentserver 9.0.4.1 de16e948ccf0 6 days ago 3.79GB
onlyoffice/docspace-socket 3.2.1.1 c322bd9f2169 3 weeks ago 763MB
onlyoffice/docspace-ssoauth 3.2.1.1 078970f7a3bc 3 weeks ago 783MB
onlyoffice/docspace-router 3.2.1.1 2b2eab2b6848 3 weeks ago 1.5GB
onlyoffice/docspace-studio 3.2.1.1 33c9b4fcc49e 3 weeks ago 1.26GB
onlyoffice/docspace-doceditor 3.2.1.1 65c1f4a636c2 3 weeks ago 886MB
onlyoffice/docspace-sdk 3.2.1.1 6c9ba0364a0f 3 weeks ago 869MB
onlyoffice/docspace-login 3.2.1.1 3aae39c67b1f 3 weeks ago 866MB
onlyoffice/docspace-clear-events 3.2.1.1 74ef3e609bb1 3 weeks ago 1.24GB
onlyoffice/docspace-files-services 3.2.1.1 40949f262568 3 weeks ago 2.02GB
onlyoffice/docspace-people-server 3.2.1.1 9d33d36e51de 3 weeks ago 1.26GB
onlyoffice/docspace-notify 3.2.1.1 11ec78f2ac95 3 weeks ago 1.26GB
onlyoffice/docspace-healthchecks 3.2.1.1 d54be73e29fd 3 weeks ago 759MB
onlyoffice/docspace-studio-notify 3.2.1.1 77ef2662e5c9 3 weeks ago 1.26GB
onlyoffice/docspace-api-system 3.2.1.1 4579050a4497 3 weeks ago 1.26GB
onlyoffice/docspace-migration-runner 3.2.1.1 d9809042cf51 3 weeks ago 1.35GB
onlyoffice/docspace-files 3.2.1.1 803378bdca73 3 weeks ago 1.88GB
onlyoffice/docspace-backup 3.2.1.1 c8fe64497ab8 3 weeks ago 1.32GB
onlyoffice/docspace-api 3.2.1.1 4e325b007e5f 3 weeks ago 1.32GB
onlyoffice/docspace-backup-background 3.2.1.1 4df34859ed9c 3 weeks ago 1.32GB
onlyoffice/docspace-identity-api 3.2.1.1 eae690280790 3 weeks ago 322MB
onlyoffice/docspace-identity-authorization 3.2.1.1 57f3c88dae9e 3 weeks ago 319MB
rabbitmq 3 3b6af313a9b0 3 weeks ago 215MB
nginx latest 2cd1d97f893f 3 weeks ago 192MB
redis 7 e3684da61b7c 5 weeks ago 117MB
opensearchproject/opensearch-dashboards 2.18.0 3eaec85eebf5 6 months ago 1.49GB
onlyoffice/opensearch 2.18.0 9bb96cda5fe5 7 months ago 1.47GB
fluent/fluent-bit 3.0.2 200723166746 16 months ago 99MB
mysql 8.3.0 6f343283ab56 16 months ago 632MB
这个命令是启用离线安装模式,跳过硬件检测,docspace最终对外端口指定为1888,安装模式为安装社区版docspace
输出如下;
[root@centos14 ~]# bash install-Docker.sh -off true -docsv 9.0.4.1 -ep 1888 -it community
Loaded plugins: fastestmirror
Determining fastest mirrors
base_x86_64 | 2.9 kB 00:00:00
dsfdsf | 3.6 kB 00:00:00
epel_x86_64 | 2.9 kB 00:00:00
libvirt_x86_64 | 2.9 kB 00:00:00
pg_all | 2.9 kB 00:00:00
pg_extras_x86_64 | 2.9 kB 00:00:00
remi-php74 | 2.9 kB 00:00:00
remi-safe | 2.9 kB 00:00:00
sclo-rh-x86_64 | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
virt_x86_64 | 2.9 kB 00:00:00
Resolving Dependencies
--> Running transaction check
---> Package net-tools.x86_64 0:2.0-0.25.20131004git.el7 will be installed
--> Finished Dependency ResolutionDependencies Resolved============================================================================================================================================================================================================================================================================================================================================Package Arch Version Repository Size
============================================================================================================================================================================================================================================================================================================================================
Installing:net-tools x86_64 2.0-0.25.20131004git.el7 base_x86_64 306 kTransaction Summary
============================================================================================================================================================================================================================================================================================================================================
Install 1 PackageTotal download size: 306 k
Installed size: 917 k
Downloading packages:
net-tools-2.0-0.25.20131004git.el7.x86_64.rpm | 306 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transactionInstalling : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1 Verifying : net-tools-2.0-0.25.20131004git.el7.x86_64 1/1 Installed:net-tools.x86_64 0:2.0-0.25.20131004git.el7 Complete!
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package jq.x86_64 0:1.6-2.el7 will be installed
--> Processing Dependency: libonig.so.5()(64bit) for package: jq-1.6-2.el7.x86_64
--> Running transaction check
---> Package oniguruma.x86_64 0:6.8.2-2.el7 will be installed
--> Finished Dependency ResolutionDependencies Resolved============================================================================================================================================================================================================================================================================================================================================Package Arch Version Repository Size
============================================================================================================================================================================================================================================================================================================================================
Installing:jq x86_64 1.6-2.el7 epel_x86_64 167 k
Installing for dependencies:oniguruma x86_64 6.8.2-2.el7 epel_x86_64 181 kTransaction Summary
============================================================================================================================================================================================================================================================================================================================================
Install 1 Package (+1 Dependent package)Total download size: 348 k
Installed size: 1.0 M
Downloading packages:
(1/2): jq-1.6-2.el7.x86_64.rpm | 167 kB 00:00:00
(2/2): oniguruma-6.8.2-2.el7.x86_64.rpm | 181 kB 00:00:00
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 5.5 MB/s | 348 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transactionInstalling : oniguruma-6.8.2-2.el7.x86_64 1/2 Installing : jq-1.6-2.el7.x86_64 2/2 Verifying : oniguruma-6.8.2-2.el7.x86_64 1/2 Verifying : jq-1.6-2.el7.x86_64 2/2 Installed:jq.x86_64 0:1.6-2.el7 Dependency Installed:oniguruma.x86_64 0:6.8.2-2.el7 Complete!
6144+0 records in
6144+0 records out
6442450944 bytes (6.4 GB) copied, 8.29127 s, 777 MB/s
Setting up swapspace version 1, size = 6291452 KiB
no label, UUID=3cc57613-e9d1-4915-abf4-0537a5179ff8
ee8fe93c08a7a3297751cbb56ce93507b5b00b9c60a3dcc5ecdb2c1bd1b6d65e
Unzip docker.tar.gz to /app/onlyoffice...
OK
[+] Running 2/2✔ Volume "onlyoffice_os_data" Created 0.0s ✔ Container onlyoffice-opensearch Started 0.8s
no crontab for root
[+] Running 3/3✔ Volume "onlyoffice_log_data" Created 0.0s ✔ Container onlyoffice-fluent-bit Started 0.4s ✔ Container onlyoffice-opensearch-dashboards Started 0.3s
[+] Running 2/2✔ Volume "onlyoffice_mysql_data" Created 0.0s ✔ Container onlyoffice-mysql-server Started 0.4s
[+] Running 1/1✔ Container onlyoffice-rabbitmq Started 0.8s
[+] Running 1/1✔ Container onlyoffice-redis Started 0.6s
[+] Running 2/2✔ Volume "onlyoffice_app_data" Created 0.0s ✔ Container onlyoffice-document-server Started 2.0s
Waiting for MySQL container to become healthy...OK
[+] Running 1/1✔ Container onlyoffice-migration-runner Started 0.4s
Waiting for database migration to complete...OK
[+] Running 2/2✔ Container onlyoffice-identity-authorization Started 0.6s ✔ Container onlyoffice-identity-api Started 0.6s
[+] Running 16/16✔ Container onlyoffice-doceditor Started 5.5s ✔ Container onlyoffice-files-services Started 5.4s ✔ Container onlyoffice-people-server Started 5.4s ✔ Container onlyoffice-socket Started 5.5s ✔ Container onlyoffice-studio Started 5.4s ✔ Container onlyoffice-backup-background-tasks Started 5.4s ✔ Container onlyoffice-sdk Started 5.4s ✔ Container onlyoffice-api Started 5.5s ✔ Container onlyoffice-clear-events Started 5.5s ✔ Container onlyoffice-login Started 5.4s ✔ Container onlyoffice-files Started 5.4s ✔ Container onlyoffice-api-system Started 5.4s ✔ Container onlyoffice-ssoauth Started 5.4s ✔ Container onlyoffice-studio-notify Started 5.5s ✔ Container onlyoffice-backup Started 5.5s ✔ Container onlyoffice-router Started 6.2s
[+] Running 2/2✔ Volume "onlyoffice_webroot_path" Created 0.0s ✔ Container onlyoffice-proxy Started 33.9s
[+] Running 1/1✔ Container onlyoffice-notify Started 9.8s
[+] Running 1/1✔ Container onlyoffice-healthchecks Started 8.0s Thank you for installing ONLYOFFICE DocSpace.
In case you have any questions contact us via http://support.onlyoffice.com or visit our forum at http://forum.onlyoffice.com
看到谢谢后,打开浏览器,输入IP+端口1888即可开始onlyoffice之旅了
其实在正式使用前,最好还是看下所有镜像是否正常,所有持久数据是否正常:
这个时候,其实是有一个容器没有准备好,退出了,日志如下:
[root@centos14 ~]# docker logs onlyoffice-migration-runner
Migrations applied
[root@centos14 ~]# docker logs onlyoffice-migration-runner
Migrations applied
这个时候不用慌,等待一段时间,数据同步好后,就可以进入web界面了,此容器会一直保持exited状态,onlyoffice/docspace-healthchecks:3.2.1.1这个容器会保证整个系统正常运行的
整个系统的数据都存放在/app目录下
四、
卸载docspace
卸载非常简单,docspace感觉在安装部署方面比workspace要好很多,执行以下命令即可:
bash install-Docker.sh -uni true
输出如下:
[root@centos14 ~]# bash install-Docker.sh -uni true
Uninstall all dependencies (mysql, opensearch and others)? (Y/n): y
Uninstallation of db and its volumes...
[+] Running 2/2✔ Container onlyoffice-mysql-server Removed 6.6s ✔ Volume onlyoffice_mysql_data Removed 0.0s
Uninstallation of rabbitmq and its volumes...
[+] Running 1/1✔ Container onlyoffice-rabbitmq Removed 2.0s
Uninstallation of redis and its volumes...
[+] Running 1/1✔ Container onlyoffice-redis Removed 0.3s
Uninstallation of opensearch and its volumes...
[+] Running 2/2✔ Container onlyoffice-opensearch Removed 0.7s ✔ Volume onlyoffice_os_data Removed 0.0s
Uninstallation of dashboards and its volumes...
[+] Running 1/1✔ Container onlyoffice-opensearch-dashboards Removed 0.5s
Uninstallation of fluent and its volumes...
[+] Running 2/2✔ Container onlyoffice-fluent-bit Removed 0.9s ! Volume onlyoffice_log_data Resource is still in use 0.0s
Uninstallation of docspace and its volumes...
[+] Running 18/18✔ Container onlyoffice-router Removed 0.2s ✔ Container onlyoffice-clear-events Removed 10.6s ✔ Container onlyoffice-studio Removed 10.6s ✔ Container onlyoffice-files Removed 10.5s ✔ Container onlyoffice-people-server Removed 10.6s ✔ Container onlyoffice-ssoauth Removed 10.4s ✔ Container onlyoffice-studio-notify Removed 10.6s ✔ Container onlyoffice-api Removed 10.5s ✔ Container onlyoffice-files-services Removed 10.5s ✔ Container onlyoffice-socket Removed 10.6s ✔ Container onlyoffice-sdk Removed 10.5s ✔ Container onlyoffice-api-system Removed 10.3s ✔ Container onlyoffice-login Removed 10.6s ✔ Container onlyoffice-backup Removed 10.6s ✔ Container onlyoffice-backup-background-tasks Removed 10.5s ✔ Container onlyoffice-doceditor Removed 10.3s ! Volume onlyoffice_app_data Resource is still in use 0.0s ! Volume onlyoffice_log_data Resource is still in use 0.0s
Uninstallation of ds and its volumes...
[+] Running 3/3✔ Container onlyoffice-document-server Removed 60.4s ! Volume onlyoffice_log_data Resource is still in use 0.0s ! Volume onlyoffice_app_data Resource is still in use 0.0s
Uninstallation of identity and its volumes...
[+] Running 3/3✔ Container onlyoffice-identity-authorization Removed 10.2s ✔ Container onlyoffice-identity-api Removed 10.2s ! Volume onlyoffice_log_data Resource is still in use 0.0s
Uninstallation of proxy and its volumes...
[+] Running 3/3✔ Container onlyoffice-proxy Removed 0.1s ✔ Volume onlyoffice_webroot_path Removed 0.0s ! Volume onlyoffice_log_data Resource is still in use 0.0s
Uninstallation of healthchecks and its volumes...
[+] Running 2/2✔ Container onlyoffice-healthchecks Removed 10.1s ! Volume onlyoffice_app_data Resource is still in use 0.0s
Uninstallation of notify and its volumes...
[+] Running 3/3✔ Container onlyoffice-notify Removed 10.1s ✔ Volume onlyoffice_log_data Removed 0.0s ✔ Volume onlyoffice_app_data Removed 0.0s
Uninstallation of migration-runner and its volumes...
[+] Running 1/1✔ Container onlyoffice-migration-runner Removed 0.0s
onlyoffice
Do you want to retain data (keep .env file)? (Y/n): n
Uninstallation of DocSpace and all dependencies completed.
ok,现在docspace文档协作空间系统的完全离线化部署就介绍到这了,如有不明白的地方,请私信我