| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005 | #!/usr/bin/env bashPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATH# System Required: CentOS 7+/Ubuntu 18+/Debian 10+# Version: v2.2.0# Description: One click Install Trojan Panel server# Author: jonssonyan <https://jonssonyan.com># Github: https://github.com/trojanpanel/install-scriptinit_var() {  ECHO_TYPE="echo -e"  package_manager=""  release=""  get_arch=""  can_google=0  # Docker  DOCKER_MIRROR='"https://hub-mirror.c.163.com","https://ccr.ccs.tencentyun.com","https://mirror.baidubce.com","https://dockerproxy.com"'  # Project directory  TP_DATA="/tpdata/"  STATIC_HTML="https://github.com/trojanpanel/install-script/releases/download/v1.0/html.tar.gz"  # Web  WEB_PATH="/tpdata/web/"  # Cert  CERT_PATH="/tpdata/cert/"  DOMAIN_FILE="/tpdata/domain.lock"  domain=""  crt_path=""  key_path=""  # Caddy2  CADDY_DATA="/tpdata/caddy/"  CADDY_CONFIG="${CADDY_DATA}config.json"  CADDY_LOG="${CADDY_DATA}logs/"  CADDY_CERT_DIR="${CERT_PATH}certificates/acme-v02.api.letsencrypt.org-directory/"  caddy_port=80  caddy_remote_port=8863  your_email=""  ssl_option=1  ssl_module_type=1  ssl_module="acme"  # Nginx  NGINX_DATA="/tpdata/nginx/"  NGINX_CONFIG="${NGINX_DATA}default.conf"  nginx_port=80  nginx_remote_port=8863  nginx_https=1  # MariaDB  MARIA_DATA="/tpdata/mariadb/"  mariadb_ip="127.0.0.1"  mariadb_port=9507  mariadb_user="root"  mariadb_pas=""  # Redis  REDIS_DATA="/tpdata/redis/"  redis_host="127.0.0.1"  redis_port=6378  redis_pass=""  # Trojan Panel Frontend  TROJAN_PANEL_UI_DATA="/tpdata/trojan-panel-ui/"  # Nginx  UI_NGINX_DATA="${TROJAN_PANEL_UI_DATA}nginx/"  UI_NGINX_CONFIG="${UI_NGINX_DATA}default.conf"  trojan_panel_ui_port=8888  ui_https=1  trojan_panel_ip="127.0.0.1"  trojan_panel_server_port=8081  # Trojan Panel Backend  TROJAN_PANEL_DATA="/tpdata/trojan-panel/"  TROJAN_PANEL_WEBFILE="${TROJAN_PANEL_DATA}webfile/"  TROJAN_PANEL_LOGS="${TROJAN_PANEL_DATA}logs/"  TROJAN_PANEL_CONFIG="${TROJAN_PANEL_DATA}config/"  trojan_panel_config_path="${TROJAN_PANEL_DATA}config/config.ini"  trojan_panel_port=8081  # Trojan Panel Core  TROJAN_PANEL_CORE_DATA="/tpdata/trojan-panel-core/"  TROJAN_PANEL_CORE_LOGS="${TROJAN_PANEL_CORE_DATA}logs/"  TROJAN_PANEL_CORE_CONFIG="${TROJAN_PANEL_CORE_DATA}config/"  trojan_panel_core_config_path="${TROJAN_PANEL_CORE_DATA}config/config.ini"  database="trojan_panel_db"  account_table="account"  grpc_port=8100  trojan_panel_core_port=8082  # Version  trojan_panel_ui_current_version=""  trojan_panel_ui_latest_version="v2.1.6"  trojan_panel_current_version=""  trojan_panel_latest_version="v2.2.0"  trojan_panel_core_current_version=""  trojan_panel_core_latest_version="v2.2.0"  # SQL  sql_215="alter table account change validity_period preset_expire int unsigned default 0 not null comment '预设过期时长';alter table account add preset_quota bigint default 0 not null comment '预设配额' after preset_expire;update account set preset_quota = quota where last_login_time = 0;update account set quota = 0 where last_login_time = 0;alter table node add priority int default 100 not null comment '优先级' after port;INSERT INTO casbin_rule (p_type, v0, v1, v2, v3, v4, v5) VALUES ('p', 'sysadmin', '/api/account/clashSubscribeForSb', 'GET', 'default', 'default', 'default');alter table node_hysteria add server_name varchar(64) default '' not null comment '用于验证服务端证书的 hostname' after down_mbps;alter table node_hysteria add insecure tinyint(1) default 0 not null comment '忽略一切证书错误' after server_name;alter table node_hysteria add fast_open tinyint(1) default 0 not null comment '启用 Fast Open (降低连接建立延迟)' after insecure;"}echo_content() {  case $1 in  "red")    ${ECHO_TYPE} "\033[31m$2\033[0m"    ;;  "green")    ${ECHO_TYPE} "\033[32m$2\033[0m"    ;;  "yellow")    ${ECHO_TYPE} "\033[33m$2\033[0m"    ;;  "blue")    ${ECHO_TYPE} "\033[34m$2\033[0m"    ;;  "purple")    ${ECHO_TYPE} "\033[35m$2\033[0m"    ;;  "skyBlue")    ${ECHO_TYPE} "\033[36m$2\033[0m"    ;;  "white")    ${ECHO_TYPE} "\033[37m$2\033[0m"    ;;  esac}mkdir_tools() {  # Project directory  mkdir -p ${TP_DATA}  # Web  mkdir -p ${WEB_PATH}  # Cert  mkdir -p ${CERT_PATH}  touch ${DOMAIN_FILE}  # Caddy2  mkdir -p ${CADDY_DATA}  touch ${CADDY_CONFIG}  mkdir -p ${CADDY_LOG}  # Nginx  mkdir -p ${NGINX_DATA}  touch ${NGINX_CONFIG}  # MariaDB  mkdir -p ${MARIA_DATA}  # Redis  mkdir -p ${REDIS_DATA}  # Trojan Panel Frontend  mkdir -p ${TROJAN_PANEL_UI_DATA}  # Nginx  mkdir -p ${UI_NGINX_DATA}  touch ${UI_NGINX_CONFIG}  # Trojan Panel Backend  mkdir -p ${TROJAN_PANEL_DATA}  mkdir -p ${TROJAN_PANEL_LOGS}  # Trojan Panel Core  mkdir -p ${TROJAN_PANEL_CORE_DATA}  mkdir -p ${TROJAN_PANEL_CORE_LOGS}}can_connect() {  ping -c2 -i0.3 -W1 "$1" &>/dev/null  if [[ "$?" == "0" ]]; then    return 0  else    return 1  fi}# query .ini configuration file informationget_ini_value() {  local config_file="$1"  local key="$2"  local section=""  local section_flag=0  # split group and key names  IFS='.' read -r group_name key_name <<<"$key"  while IFS='=' read -r name val; do    # processing section name    if [[ $name =~ ^\[(.*)\]$ ]]; then      section="${BASH_REMATCH[1]}"      if [[ $section == $group_name ]]; then        section_flag=1      else        section_flag=0      fi      continue    fi    # extract the value of the configuration item    if [[ $section_flag -eq 1 && $name == $key_name ]]; then      echo "$val"      return    fi  done <"$config_file"}# Version number comparison greater than or equal toversion_ge() {  local v1=${1#v}  local v2=${2#v}  local v1_parts=(${v1//./ })  local v2_parts=(${v2//./ })  for ((i = 0; i < 3; i++)); do    if ((${v1_parts[i]} < ${v2_parts[i]})); then      echo false      return 0    elif ((${v1_parts[i]} > ${v2_parts[i]})); then      echo true      return 0    fi  done  echo true}check_sys() {  if [[ $(command -v yum) ]]; then    package_manager='yum'  elif [[ $(command -v dnf) ]]; then    package_manager='dnf'  elif [[ $(command -v apt) ]]; then    package_manager='apt'  elif [[ $(command -v apt-get) ]]; then    package_manager='apt-get'  fi  if [[ -z "${package_manager}" ]]; then    echo_content red "The system is not currently supported"    exit 0  fi  if [[ -n $(find /etc -name "redhat-release") ]] || grep </proc/version -q -i "centos"; then    release="centos"  elif grep </etc/issue -q -i "debian" && [[ -f "/etc/issue" ]] || grep </etc/issue -q -i "debian" && [[ -f "/proc/version" ]]; then    release="debian"  elif grep </etc/issue -q -i "ubuntu" && [[ -f "/etc/issue" ]] || grep </etc/issue -q -i "ubuntu" && [[ -f "/proc/version" ]]; then    release="ubuntu"  fi  if [[ -z "${release}" ]]; then    echo_content red "The operating system only supports CentOS 7+/Ubuntu 18+/Debian 10+"    exit 0  fi  if [[ $(arch) =~ ("x86_64"|"amd64"|"arm64"|"aarch64"|"arm"|"s390x") ]]; then    get_arch=$(arch)  fi  if [[ -z "${get_arch}" ]]; then    echo_content red "The processor architecture only supports amd64/arm64/arm/s390x"    exit 0  fi  can_connect www.google.com  [[ "$?" == "0" ]] && can_google=1}depend_install() {  if [[ "${package_manager}" != 'yum' && "${package_manager}" != 'dnf' ]]; then    ${package_manager} update -y  fi  ${package_manager} install -y \    curl \    wget \    tar \    lsof \    systemd}# Install Dockerinstall_docker() {  if [[ ! $(docker -v 2>/dev/null) ]]; then    echo_content green "---> Install Docker"    # turn off firewall    if [[ "${release}" == "centos" ]]; then      systemctl disable firewalld    elif [[ "${release}" == "debian" || "${release}" == "ubuntu" ]]; then      sudo ufw disable    fi    # set time zone    timedatectl set-timezone Asia/Shanghai    if [[ ${can_google} == 0 ]]; then      sh <(curl -sL https://get.docker.com) --mirror Aliyun      mkdir -p /etc/docker &&        cat >/etc/docker/daemon.json <<EOF{  "registry-mirrors":[${DOCKER_MIRROR}],  "log-driver":"json-file",  "log-opts":{      "max-size":"50m",      "max-file":"3"  }}EOF    else      sh <(curl -sL https://get.docker.com)      mkdir -p /etc/docker &&        cat >/etc/docker/daemon.json <<EOF{  "log-driver":"json-file",  "log-opts":{      "max-size":"50m",      "max-file":"3"  }}EOF    fi    systemctl enable docker &&      systemctl restart docker    if [[ $(docker -v 2>/dev/null) ]]; then      echo_content skyBlue "---> Docker installation completed"    else      echo_content red "---> Docker installation failed"      exit 0    fi  else    echo_content skyBlue "---> You have installed Docker"  fi}# Custom Settings Certificateinstall_custom_cert() {  if [[ -z "$(cat "${DOMAIN_FILE}")" ]]; then    while read -r -p "Please enter the file path of the .crt certificate (required): " crt_path; do      if [[ -z "${crt_path}" ]]; then        echo_content red "Path cannot be empty"      else        if [[ ! -f "${crt_path}" ]]; then          echo_content red "The file path for the .crt certificate does not exist"        else          cp "${crt_path}" "${CERT_PATH}$1.crt"          break        fi      fi    done    while read -r -p "Please enter the file path of the .key certificate (required): " key_path; do      if [[ -z "${key_path}" ]]; then        echo_content red "Path cannot be empty"      else        if [[ ! -f "${key_path}" ]]; then          echo_content red "The file path for the .key certificate does not exist"        else          cp "${key_path}" "${CERT_PATH}$1.key"          break        fi      fi    done    cat >${DOMAIN_FILE} <<EOF$1EOF    echo_content red "\n=============================================================="    echo_content skyBlue "---> Custom settings certificate installation completed"    echo_content yellow "Certificate Directory: ${CERT_PATH}"    echo_content red "\n=============================================================="  fi}# Caddy2 https custom settings certificate configuration filecaddy2_https_config() {  domain=$1  cat >${CADDY_CONFIG} <<EOF{    "admin":{        "disabled":true    },    "logging":{        "logs":{            "default":{                "writer":{                    "output":"file",                    "filename":"${CADDY_LOG}error.log"                },                "level":"ERROR"            }        }    },    "storage":{        "module":"file_system",        "root":"${CERT_PATH}"    },    "apps":{        "http":{            "http_port": ${caddy_port},            "servers":{                "srv0":{                    "listen":[                        ":${caddy_port}"                    ],                    "routes":[                        {                            "match":[                                {                                    "host":[                                        "${domain}"                                    ]                                }                            ],                            "handle":[                                {                                    "handler":"static_response",                                    "headers":{                                        "Location":[                                            "https://{http.request.host}:${caddy_remote_port}{http.request.uri}"                                        ]                                    },                                    "status_code":301                                }                            ]                        }                    ]                },                "srv1":{                    "listen":[                        ":${caddy_remote_port}"                    ],                    "routes":[                        {                            "handle":[                                {                                    "handler":"subroute",                                    "routes":[                                        {                                            "match":[                                                {                                                    "host":[                                                        "${domain}"                                                    ]                                                }                                            ],                                            "handle":[                                                {                                                    "handler":"file_server",                                                    "root":"${WEB_PATH}",                                                    "index_names":[                                                        "index.html",                                                        "index.htm"                                                    ]                                                }                                            ],                                            "terminal":true                                        }                                    ]                                }                            ]                        }                    ],                    "tls_connection_policies":[                        {                            "match":{                                "sni":[                                    "${domain}"                                ]                            }                        }                    ],                    "automatic_https":{                        "disable":true                    }                }            }        },        "tls":{            "certificates":{                "automate":[                    "${domain}"                ],                "load_files":[                    {                        "certificate":"${CADDY_CERT_DIR}${domain}/${domain}.crt",                        "key":"${CADDY_CERT_DIR}${domain}/${domain}.key"                    }                ]            },            "automation":{                "policies":[                    {                        "issuers":[                            {                                "module":"${ssl_module}",                                "email":"${your_email}"                            }                        ]                    }                ]            }        }    }}EOF}# Caddy2 https automatic application and renewal certificate configuration filecaddy2_https_auto_config() {  domain=$1  cat >${CADDY_CONFIG} <<EOF{    "admin":{        "disabled":true    },    "logging":{        "logs":{            "default":{                "writer":{                    "output":"file",                    "filename":"${CADDY_LOG}error.log"                },                "level":"ERROR"            }        }    },    "storage":{        "module":"file_system",        "root":"${CERT_PATH}"    },    "apps":{        "http":{            "http_port": ${caddy_port},            "servers":{                "srv0":{                    "listen":[                        ":${caddy_port}"                    ],                    "routes":[                        {                            "match":[                                {                                    "host":[                                        "${domain}"                                    ]                                }                            ],                            "handle":[                                {                                    "handler":"static_response",                                    "headers":{                                        "Location":[                                            "https://{http.request.host}:${caddy_remote_port}{http.request.uri}"                                        ]                                    },                                    "status_code":301                                }                            ]                        }                    ]                },                "srv1":{                    "listen":[                        ":${caddy_remote_port}"                    ],                    "routes":[                        {                            "handle":[                                {                                    "handler":"subroute",                                    "routes":[                                        {                                            "match":[                                                {                                                    "host":[                                                        "${domain}"                                                    ]                                                }                                            ],                                            "handle":[                                                {                                                    "handler":"file_server",                                                    "root":"${WEB_PATH}",                                                    "index_names":[                                                        "index.html",                                                        "index.htm"                                                    ]                                                }                                            ],                                            "terminal":true                                        }                                    ]                                }                            ]                        }                    ],                    "tls_connection_policies":[                        {                            "match":{                                "sni":[                                    "${domain}"                                ]                            }                        }                    ],                    "automatic_https":{                        "disable":true                    }                }            }        },        "tls":{            "certificates":{                "automate":[                    "${domain}"                ]            },            "automation":{                "policies":[                    {                        "issuers":[                            {                                "module":"${ssl_module}",                                "email":"${your_email}"                            }                        ]                    }                ]            }        }    }}EOF}# Install Caddy2install_caddy2() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-caddy$") ]]; then    echo_content green "---> Install Caddy2+https"    wget --no-check-certificate -O ${WEB_PATH}html.tar.gz -N ${STATIC_HTML} &&      tar -zxvf ${WEB_PATH}html.tar.gz -k -C ${WEB_PATH}    read -r -p "Please enter the port of Caddy2 (default: 80): " caddy_port    [[ -z "${caddy_port}" ]] && caddy_port=80    read -r -p "Please enter the forwarding port of Caddy2 (default: 8863): " caddy_remote_port    [[ -z "${caddy_remote_port}" ]] && caddy_remote_port=8863    echo_content yellow "Tip: Please confirm that the domain name has been resolved to this machine, otherwise the installation may fail"    while read -r -p "Please enter your domain name (required): " domain; do      if [[ -z "${domain}" ]]; then        echo_content red "Domain name cannot be empty"      else        break      fi    done    read -r -p "Please enter your email (optional): " your_email    while read -r -p "Please choose the way to set up the certificate? (1/automatically apply for and renew the certificate 2/manually set the certificate path default: 1: " ssl_option; do      if [[ -z ${ssl_option} || ${ssl_option} == 1 ]]; then        while read -r -p "Please choose the way to apply for the certificate (1/acme 2/zerossl default: 1: " ssl_module_type; do          if [[ -z "${ssl_module_type}" || ${ssl_module_type} == 1 ]]; then            ssl_module="acme"            CADDY_CERT_DIR="${CERT_PATH}certificates/acme-v02.api.letsencrypt.org-directory/"            break          elif [[ ${ssl_module_type} == 2 ]]; then            ssl_module="zerossl"            CADDY_CERT_DIR="${CERT_PATH}certificates/acme.zerossl.com-v2-dv90/"            break          else            echo_content red "Cannot enter other characters except 1 and 2"          fi        done        caddy2_https_auto_config "${domain}"        break      elif [[ ${ssl_option} == 2 ]]; then        install_custom_cert "${domain}"        caddy2_https_config "${domain}"        break      else        echo_content red "Cannot enter other characters except 1 and 2"      fi    done    # Caddy2 temporary listening port for automatic certificate application    if [[ -n $(lsof -i:${caddy_port},${caddy_remote_port} -t) ]]; then      kill -9 "$(lsof -i:${caddy_port},${caddy_remote_port} -t)"    fi    docker pull caddy:2.6.2 &&      docker run -d --name trojan-panel-caddy --restart always \        --network=host \        -v "${CADDY_CONFIG}":"${CADDY_CONFIG}" \        -v ${CERT_PATH}:"${CADDY_CERT_DIR}${domain}/" \        -v ${WEB_PATH}:${WEB_PATH} \        -v ${CADDY_LOG}:${CADDY_LOG} \        caddy:2.6.2 caddy run --config ${CADDY_CONFIG}    cat >${DOMAIN_FILE} <<EOF${domain}EOF    if [[ -n $(docker ps -q -f "name=^trojan-panel-caddy$" -f "status=running") ]]; then      echo_content red "\n=============================================================="      echo_content skyBlue "---> Caddy2+https installation completed"      echo_content yellow "Certificate Directory: ${CERT_PATH}"      echo_content red "\n=============================================================="    else      echo_content red "---> Caddy2+https installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed Caddy2+https"  fi}# Nginx http configuration filenginx_http_config() {  cat >${NGINX_CONFIG} <<-EOFserver {    listen       ${nginx_port};    server_name  localhost;    location / {        root   ${WEB_PATH};        index  index.html index.htm;    }    error_page  497               http://\$host:${nginx_port}\$request_uri;    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /usr/share/nginx/html;    }}EOF}# Nginx https configuration filenginx_https_config() {  domain=$1  cat >${NGINX_CONFIG} <<-EOFserver {    listen ${nginx_port};    server_name localhost;    return 301 http://\$host:${nginx_remote_port}\$request_uri;}server {    listen       ${nginx_remote_port} ssl;    server_name  localhost;    # force ssl    ssl on;    ssl_certificate      ${CERT_PATH}${domain}.crt;    ssl_certificate_key  ${CERT_PATH}${domain}.key;    # cache validity period    ssl_session_timeout  5m;    # secure link optional encryption protocol    ssl_protocols  TLSv1.3;    # encryption algorithm    ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    # use server-side preferred algorithm    ssl_prefer_server_ciphers  on;    #access_log  /var/log/nginx/host.access.log  main;    location / {        root   ${WEB_PATH};        index  index.html index.htm;    }    #error_page  404              /404.html;    #497 http->https    error_page  497               https://\$host:${nginx_remote_port}\$request_uri;    # redirect server error pages to the static page /50x.html    #    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /usr/share/nginx/html;    }}EOF}# Install Nginxinstall_nginx() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-nginx$") ]]; then    echo_content green "---> Install Nginx"    wget --no-check-certificate -O ${WEB_PATH}html.tar.gz -N ${STATIC_HTML} &&      tar -zxvf ${WEB_PATH}html.tar.gz -k -C ${WEB_PATH}    read -r -p "Please enter the port of Nginx (default: 80): " nginx_port    [[ -z "${nginx_port}" ]] && nginx_port=80    read -r -p "Please enter the forwarding port of Nginx (default: 8863): " nginx_remote_port    [[ -z "${nginx_remote_port}" ]] && nginx_remote_port=8863    while read -r -p "Please choose whether to enable https in Nginx? (0/off 1/on default: 1): " nginx_https; do      if [[ -z ${nginx_https} || ${nginx_https} == 1 ]]; then        install_custom_cert "custom_cert"        nginx_https_config "custom_cert"        break      elif [[ ${nginx_https} == 0 ]]; then        nginx_http_config        break      else        echo_content red "Cannot enter other characters except 1 and 2"      fi    done    docker pull nginx:1.20-alpine &&      docker run -d --name trojan-panel-nginx --restart always \        --network=host \        -v "${NGINX_CONFIG}":"/etc/nginx/conf.d/default.conf" \        -v ${CERT_PATH}:${CERT_PATH} \        -v ${WEB_PATH}:${WEB_PATH} \        nginx:1.20-alpine    if [[ -n $(docker ps -q -f "name=^trojan-panel-nginx$" -f "status=running") ]]; then      echo_content skyBlue "---> Nginx installation completed"    else      echo_content red "---> Nginx installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed Nginx"  fi}# Install a web serverinstall_reverse_proxy() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-caddy$|^trojan-panel-nginx$") ]]; then    echo_content green "---> Install a web server"    while :; do      echo_content yellow "1. Install Caddy2+https (recommend)"      echo_content yellow "2. Install Nginx"      echo_content yellow "3. Not install"      read -r -p "Please select (default: 1): " whether_install_reverse_proxy      [[ -z "${whether_install_reverse_proxy}" ]] && whether_install_reverse_proxy=1      case ${whether_install_reverse_proxy} in      1)        install_caddy2        break        ;;      2)        install_nginx        break        ;;      3)        break        ;;      *)        echo_content red "No such option"        continue        ;;      esac    done    echo_content skyBlue "---> Web server installation completed"  fi}# Set certificateinstall_cert() {  if [[ -z "$(cat "${DOMAIN_FILE}")" ]]; then    echo_content green "---> Set certificate"    while :; do      echo_content yellow "1. Custom certificate"      echo_content yellow "2. Not set"      read -r -p "Please select (default: 1): " whether_install_cert      [[ -z "${whether_install_cert}" ]] && whether_install_cert=1      case ${whether_install_cert} in      1)        install_custom_cert "custom_cert"        break        ;;      2)        break        ;;      *)        echo_content red "No such option"        continue        ;;      esac    done    echo_content green "---> Certificate setup completed"  fi}# Install MariaDBinstall_mariadb() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-mariadb$") ]]; then    echo_content green "---> Install MariaDB"    read -r -p "Please enter the port of MariaDB (default: 9507): " mariadb_port    [[ -z "${mariadb_port}" ]] && mariadb_port=9507    read -r -p "Please enter the username of MariaDB (default: root): " mariadb_user    [[ -z "${mariadb_user}" ]] && mariadb_user="root"    while read -r -p "Please enter the password of MariaDB (required): " mariadb_pas; do      if [[ -z "${mariadb_pas}" ]]; then        echo_content red "Password can not be empty"      else        break      fi    done    if [[ "${mariadb_user}" == "root" ]]; then      docker pull mariadb:10.7.3 &&        docker run -d --name trojan-panel-mariadb --restart always \          --network=host \          -e MYSQL_DATABASE="trojan_panel_db" \          -e MYSQL_ROOT_PASSWORD="${mariadb_pas}" \          -e TZ=Asia/Shanghai \          mariadb:10.7.3 \          --port ${mariadb_port} \          --character-set-server=utf8mb4 \          --collation-server=utf8mb4_unicode_ci    else      docker pull mariadb:10.7.3 &&        docker run -d --name trojan-panel-mariadb --restart always \          --network=host \          -e MYSQL_DATABASE="trojan_panel_db" \          -e MYSQL_ROOT_PASSWORD="${mariadb_pas}" \          -e MYSQL_USER="${mariadb_user}" \          -e MYSQL_PASSWORD="${mariadb_pas}" \          -e TZ=Asia/Shanghai \          mariadb:10.7.3 \          --port ${mariadb_port} \          --character-set-server=utf8mb4 \          --collation-server=utf8mb4_unicode_ci    fi    if [[ -n $(docker ps -q -f "name=^trojan-panel-mariadb$" -f "status=running") ]]; then      echo_content skyBlue "---> MariaDB installation completed"      echo_content yellow "---> The MariaDB password of root (please keep it safe): ${mariadb_pas}"      if [[ "${mariadb_user}" != "root" ]]; then        echo_content yellow "---> The MariaDB password of ${mariadb_user} (please keep it safe): ${mariadb_pas}"      fi    else      echo_content red "---> MariaDB installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed MariaDB"  fi}# Install Redisinstall_redis() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-redis$") ]]; then    echo_content green "---> Install Redis"    read -r -p "Please enter the port of Redis (default: 6378): " redis_port    [[ -z "${redis_port}" ]] && redis_port=6378    while read -r -p "Please enter the Redis password (required): " redis_pass; do      if [[ -z "${redis_pass}" ]]; then        echo_content red "Password can not be empty"      else        break      fi    done    docker pull redis:6.2.7 &&      docker run -d --name trojan-panel-redis --restart always \        --network=host \        redis:6.2.7 \        redis-server --requirepass "${redis_pass}" --port "${redis_port}"    if [[ -n $(docker ps -q -f "name=^trojan-panel-redis$" -f "status=running") ]]; then      echo_content skyBlue "---> Redis installation completed"      echo_content yellow "---> Redis password (please keep it safe): ${redis_pass}"    else      echo_content red "---> Redis installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed Redis"  fi}# Trojan Panel Frontend Nginx http configuration fileui_http_config() {  cat >${UI_NGINX_CONFIG} <<-EOFserver {    listen       ${trojan_panel_ui_port};    server_name  localhost;    location / {        root   ${TROJAN_PANEL_UI_DATA};        index  index.html index.htm;    }    location /api {        proxy_pass http://${trojan_panel_ip}:${trojan_panel_server_port};    }    error_page  497               http://\$host:${trojan_panel_ui_port}\$request_uri;    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /usr/share/nginx/html;    }}EOF}# Trojan Panel Frontend Nginx https configuration fileui_https_config() {  cat >${UI_NGINX_CONFIG} <<-EOFserver {    listen       ${trojan_panel_ui_port} ssl;    server_name  localhost;    # force ssl    ssl on;    ssl_certificate      ${CERT_PATH}${domain}.crt;    ssl_certificate_key  ${CERT_PATH}${domain}.key;    # cache validity period    ssl_session_timeout  5m;    # secure link optional encryption protocol    ssl_protocols  TLSv1.3;    # encryption algorithm    ssl_ciphers  ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    # use server-side preferred algorithm    ssl_prefer_server_ciphers  on;    #access_log  /var/log/nginx/host.access.log  main;    location / {        root   ${TROJAN_PANEL_UI_DATA};        index  index.html index.htm;    }    location /api {        proxy_pass http://${trojan_panel_ip}:${trojan_panel_server_port};    }    #error_page  404              /404.html;    #497 http->https    error_page  497               https://\$host:${trojan_panel_ui_port}\$request_uri;    # redirect server error pages to the static page /50x.html    #    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /usr/share/nginx/html;    }}EOF}# Install Trojan Panel Frontendinstall_trojan_panel_ui() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-ui$") ]]; then    echo_content green "---> Install Trojan Panel Frontend"    read -r -p "Please enter the IP address of the Trojan Panel Backend (default: local host): " trojan_panel_ip    [[ -z "${trojan_panel_ip}" ]] && trojan_panel_ip="127.0.0.1"    read -r -p "Please enter the service port of the Trojan Panel Backend (default: 8081): " trojan_panel_server_port    [[ -z "${trojan_panel_server_port}" ]] && trojan_panel_server_port=8081    read -r -p "Please enter the port of the Trojan Panel Frontend (default: 8888): " trojan_panel_ui_port    [[ -z "${trojan_panel_ui_port}" ]] && trojan_panel_ui_port="8888"    while read -r -p "Please choose whether to enable https on the Trojan Panel Frontend? (0/off 1/on default: 1): " ui_https; do      if [[ -z ${ui_https} || ${ui_https} == 1 ]]; then        install_custom_cert "custom_cert"        domain=$(cat "${DOMAIN_FILE}")        ui_https_config        break      elif [[ ${ui_https} == 0 ]]; then        ui_http_config        break      else        echo_content red "Cannot enter other characters except 1 and 2"      fi    done    docker pull jonssonyan/trojan-panel-ui:2.1.6 &&      docker run -d --name trojan-panel-ui --restart always \        --network=host \        -v "${UI_NGINX_CONFIG}":"/etc/nginx/conf.d/default.conf" \        -v ${CERT_PATH}:${CERT_PATH} \        jonssonyan/trojan-panel-ui:2.1.6    if [[ -n $(docker ps -q -f "name=^trojan-panel-ui$" -f "status=running") ]]; then      echo_content skyBlue "---> Trojan Panel Frontend installation completed"      https_flag=$([[ -z ${ui_https} || ${ui_https} == 1 ]] && echo "https" || echo "http")      domain_or_ip=$([[ -z ${domain} || "${domain}" == "custom_cert" ]] && echo "ip" || echo "${domain}")      echo_content red "\n=============================================================="      echo_content skyBlue "Trojan Panel Frontend installed successfully"      echo_content yellow "Web management panel address: ${https_flag}://${domain_or_ip}:${trojan_panel_ui_port}"      echo_content red "\n=============================================================="    else      echo_content red "---> Trojan Panel Frontend installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed the Trojan Panel Frontend"  fi}# Install Trojan Panel Backendinstall_trojan_panel() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel$") ]]; then    echo_content green "---> Install Trojan Panel Backend"    read -r -p "Please enter the service port of the Trojan Panel Backend (default: 8081): " trojan_panel_port    [[ -z "${trojan_panel_port}" ]] && trojan_panel_port=8081    read -r -p "Please enter the IP address of MariaDB (default: local host): " mariadb_ip    [[ -z "${mariadb_ip}" ]] && mariadb_ip="127.0.0.1"    read -r -p "Please enter the port of MariaDB (default: 9507): " mariadb_port    [[ -z "${mariadb_port}" ]] && mariadb_port=9507    read -r -p "Please enter the username of MariaDB (default: root): " mariadb_user    [[ -z "${mariadb_user}" ]] && mariadb_user="root"    while read -r -p "Please enter the password of MariaDB (required): " mariadb_pas; do      if [[ -z "${mariadb_pas}" ]]; then        echo_content red "Password can not be empty"      else        break      fi    done    docker exec trojan-panel-mariadb mysql --default-character-set=utf8 -h"${mariadb_ip}" -P"${mariadb_port}" -u"${mariadb_user}" -p"${mariadb_pas}" -e "create database if not exists trojan_panel_db;" &>/dev/null    read -r -p "Please enter the IP address of Redis (default: local host): " redis_host    [[ -z "${redis_host}" ]] && redis_host="127.0.0.1"    read -r -p "Please enter the port of Redis (default: 6378): " redis_port    [[ -z "${redis_port}" ]] && redis_port=6378    while read -r -p "Please enter the Redis password (required): " redis_pass; do      if [[ -z "${redis_pass}" ]]; then        echo_content red "Password can not be empty"      else        break      fi    done    docker exec trojan-panel-redis redis-cli -h "${redis_host}" -p "${redis_port}" -a "${redis_pass}" -e "flushall" &>/dev/null    docker pull jonssonyan/trojan-panel:2.2.0 &&      docker run -d --name trojan-panel --restart always \        --network=host \        -v ${WEB_PATH}:${TROJAN_PANEL_WEBFILE} \        -v ${TROJAN_PANEL_LOGS}:${TROJAN_PANEL_LOGS} \        -v ${TROJAN_PANEL_CONFIG}:${TROJAN_PANEL_CONFIG} \        -v /etc/localtime:/etc/localtime \        -e GIN_MODE=release \        -e "mariadb_ip=${mariadb_ip}" \        -e "mariadb_port=${mariadb_port}" \        -e "mariadb_user=${mariadb_user}" \        -e "mariadb_pas=${mariadb_pas}" \        -e "redis_host=${redis_host}" \        -e "redis_port=${redis_port}" \        -e "redis_pass=${redis_pass}" \        -e "server_port=${trojan_panel_port}" \        jonssonyan/trojan-panel:2.2.0    if [[ -n $(docker ps -q -f "name=^trojan-panel$" -f "status=running") ]]; then      echo_content skyBlue "---> Trojan Panel Backend installation completed"      echo_content red "\n=============================================================="      echo_content skyBlue "Trojan Panel Backend installed successfully"      echo_content yellow "MariaDB ${mariadb_user} password (please keep it safe): ${mariadb_pas}"      echo_content yellow "Redis password (please keep it safe): ${redis_pass}"      echo_content yellow "System administrator Default username: sysadmin Default password: 123456"      echo_content yellow "Please log in to the management panel to change the password in time"      echo_content red "\n=============================================================="    else      echo_content red "---> Trojan Panel Backend installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed the Trojan Panel Backend"  fi}# Install Trojan Panel Coreinstall_trojan_panel_core() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-core$") ]]; then    echo_content green "---> Install Trojan Panel Core"    read -r -p "Please enter the service port of the Trojan Panel Core (default: 8082): " trojan_panel_core_port    [[ -z "${trojan_panel_core_port}" ]] && trojan_panel_core_port=8082    read -r -p "Please enter the IP address of MariaDB (default: local host): " mariadb_ip    [[ -z "${mariadb_ip}" ]] && mariadb_ip="127.0.0.1"    read -r -p "Please enter the port of MariaDB (default: 9507): " mariadb_port    [[ -z "${mariadb_port}" ]] && mariadb_port=9507    read -r -p "Please enter the username of MariaDB (default: root): " mariadb_user    [[ -z "${mariadb_user}" ]] && mariadb_user="root"    while read -r -p "Please enter the password of MariaDB (required): " mariadb_pas; do      if [[ -z "${mariadb_pas}" ]]; then        echo_content red "Password can not be empty"      else        break      fi    done    read -r -p "Please enter the database name (default: trojan_panel_db): " database    [[ -z "${database}" ]] && database="trojan_panel_db"    read -r -p "Please enter the user table name of the database (default: account): " account_table    [[ -z "${account_table}" ]] && account_table="account"    read -r -p "Please enter the IP address of Redis (default: local host): " redis_host    [[ -z "${redis_host}" ]] && redis_host="127.0.0.1"    read -r -p "Please enter the port of Redis (default: 6378): " redis_port    [[ -z "${redis_port}" ]] && redis_port=6378    while read -r -p "Please enter the Redis password (required): " redis_pass; do      if [[ -z "${redis_pass}" ]]; then        echo_content red "Password can not be empty"      else        break      fi    done    read -r -p "Please enter the API port (default: 8100): " grpc_port    [[ -z "${grpc_port}" ]] && grpc_port=8100    domain=$(cat "${DOMAIN_FILE}")    docker pull jonssonyan/trojan-panel-core:2.2.0 &&      docker run -d --name trojan-panel-core --restart always \        --network=host \        -v ${TROJAN_PANEL_CORE_DATA}bin/xray/config/:${TROJAN_PANEL_CORE_DATA}bin/xray/config/ \        -v ${TROJAN_PANEL_CORE_DATA}bin/trojango/config/:${TROJAN_PANEL_CORE_DATA}bin/trojango/config/ \        -v ${TROJAN_PANEL_CORE_DATA}bin/hysteria/config/:${TROJAN_PANEL_CORE_DATA}bin/hysteria/config/ \        -v ${TROJAN_PANEL_CORE_DATA}bin/naiveproxy/config/:${TROJAN_PANEL_CORE_DATA}bin/naiveproxy/config/ \        -v ${TROJAN_PANEL_CORE_LOGS}:${TROJAN_PANEL_CORE_LOGS} \        -v ${TROJAN_PANEL_CORE_CONFIG}:${TROJAN_PANEL_CORE_CONFIG} \        -v ${CERT_PATH}:${CERT_PATH} \        -v ${WEB_PATH}:${WEB_PATH} \        -v /etc/localtime:/etc/localtime \        -e GIN_MODE=release \        -e "mariadb_ip=${mariadb_ip}" \        -e "mariadb_port=${mariadb_port}" \        -e "mariadb_user=${mariadb_user}" \        -e "mariadb_pas=${mariadb_pas}" \        -e "database=${database}" \        -e "account-table=${account_table}" \        -e "redis_host=${redis_host}" \        -e "redis_port=${redis_port}" \        -e "redis_pass=${redis_pass}" \        -e "crt_path=${CERT_PATH}${domain}.crt" \        -e "key_path=${CERT_PATH}${domain}.key" \        -e "grpc_port=${grpc_port}" \        -e "server_port=${trojan_panel_core_port}" \        jonssonyan/trojan-panel-core:2.2.0    if [[ -n $(docker ps -q -f "name=^trojan-panel-core$" -f "status=running") ]]; then      echo_content skyBlue "---> Trojan Panel Core installation completed"    else      echo_content red "---> Trojan Panel Core installation fails or runs abnormally, please try to repair or uninstall and reinstall"      exit 0    fi  else    echo_content skyBlue "---> You have installed the Trojan Panel Core"  fi}# Update Trojan Panel database structureupdate_trojan_panel_database() {  echo_content skyBlue "---> Update Trojan Panel database structure"  version_214_215=("v2.1.4")  if [[ "${version_214_215[*]}" =~ "${trojan_panel_current_version}" ]]; then    docker exec trojan-panel-mariadb mysql --default-character-set=utf8 -h"${mariadb_ip}" -P"${mariadb_port}" -u"${mariadb_user}" -p"${mariadb_pas}" -Dtrojan_panel_db -e "${sql_215}" &>/dev/null &&      trojan_panel_current_version="v2.1.5"  fi  echo_content skyBlue "---> Trojan Panel database structure update completed"}# Update Trojan Panel Core database structureupdate_trojan_panel_core_database() {  echo_content skyBlue "---> Update Trojan Panel Core database structure"  echo_content skyBlue "---> Trojan Panel Core database structure update completed"}# Update Trojan Panel Frontendupdate_trojan_panel_ui() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-ui$") ]]; then    echo_content red "---> Please install the Trojan Panel Frontend first"    exit 0  fi  trojan_panel_ui_current_version=$(docker exec trojan-panel-ui cat ${TROJAN_PANEL_UI_DATA}version)  if [[ -z "${trojan_panel_ui_current_version}" || ! "${trojan_panel_ui_current_version}" =~ ^v.* ]]; then    echo_content red "---> The current version does not support online updates"    exit 0  fi  echo_content yellow "Tip: The current version of the Trojan Panel Frontend (trojan-panel-ui) is ${trojan_panel_ui_current_version} the latest version is ${trojan_panel_ui_latest_version}"  if [[ "${trojan_panel_ui_current_version}" != "${trojan_panel_ui_latest_version}" ]]; then    echo_content green "---> Update Trojan Panel Frontend"    docker rm -f trojan-panel-ui &&      docker rmi -f jonssonyan/trojan-panel-ui:2.1.6    docker pull jonssonyan/trojan-panel-ui:2.1.6 &&      docker run -d --name trojan-panel-ui --restart always \        --network=host \        -v "${UI_NGINX_CONFIG}":"/etc/nginx/conf.d/default.conf" \        -v ${CERT_PATH}:${CERT_PATH} \        jonssonyan/trojan-panel-ui:2.1.6    if [[ -n $(docker ps -q -f "name=^trojan-panel-ui$" -f "status=running") ]]; then      echo_content skyBlue "---> Trojan Panel Frontend update completed"    else      echo_content red "---> Trojan Panel Frontend update fails or runs abnormally, please try to repair or uninstall and reinstall"    fi  else    echo_content skyBlue "---> You have installed the latest version of the Trojan Panel Frontend"  fi}# Update Trojan Panel Backendupdate_trojan_panel() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel$") ]]; then    echo_content red "---> Please install the Trojan Panel Backend first"    exit 0  fi  trojan_panel_current_version=$(docker exec trojan-panel ./trojan-panel -version)  if [[ -z "${trojan_panel_current_version}" || ! "${trojan_panel_current_version}" =~ ^v.* || ! $(version_ge "${trojan_panel_current_version}" "v2.1.4") ]]; then    echo_content red "---> The current version does not support online updates"    exit 0  fi  echo_content yellow "Tip: The current version of the Trojan Panel Backend (trojan-panel) is ${trojan_panel_current_version} The latest version is ${trojan_panel_latest_version}"  if [[ "${trojan_panel_current_version}" != "${trojan_panel_latest_version}" ]]; then    echo_content green "---> Update Trojan Panel Backend"    mariadb_ip=$(get_ini_value ${trojan_panel_config_path} mysql.host)    mariadb_port=$(get_ini_value ${trojan_panel_config_path} mysql.port)    mariadb_user=$(get_ini_value ${trojan_panel_config_path} mysql.user)    mariadb_pas=$(get_ini_value ${trojan_panel_config_path} mysql.password)    redis_host=$(get_ini_value ${trojan_panel_config_path} redis.host)    redis_port=$(get_ini_value ${trojan_panel_config_path} redis.port)    redis_pass=$(get_ini_value ${trojan_panel_config_path} redis.password)    trojan_panel_port=$(get_ini_value ${trojan_panel_config_path} server.port)    update_trojan_panel_database    docker exec trojan-panel-redis redis-cli -h "${redis_host}" -p "${redis_port}" -a "${redis_pass}" -e "flushall" &>/dev/null    docker rm -f trojan-panel &&      docker rmi -f jonssonyan/trojan-panel:2.2.0    docker pull jonssonyan/trojan-panel:2.2.0 &&      docker run -d --name trojan-panel --restart always \        --network=host \        -v ${WEB_PATH}:${TROJAN_PANEL_WEBFILE} \        -v ${TROJAN_PANEL_LOGS}:${TROJAN_PANEL_LOGS} \        -v ${TROJAN_PANEL_CONFIG}:${TROJAN_PANEL_CONFIG} \        -v /etc/localtime:/etc/localtime \        -e GIN_MODE=release \        -e "mariadb_ip=${mariadb_ip}" \        -e "mariadb_port=${mariadb_port}" \        -e "mariadb_user=${mariadb_user}" \        -e "mariadb_pas=${mariadb_pas}" \        -e "redis_host=${redis_host}" \        -e "redis_port=${redis_port}" \        -e "redis_pass=${redis_pass}" \        -e "server_port=${trojan_panel_port}" \        jonssonyan/trojan-panel:2.2.0    if [[ -n $(docker ps -q -f "name=^trojan-panel$" -f "status=running") ]]; then      echo_content skyBlue "---> Trojan Panel backend update completed"    else      echo_content red "---> Trojan Panel Backend update fails or runs abnormally, please try to repair or uninstall and reinstall"    fi  else    echo_content skyBlue "---> You have installed the latest version of the Trojan Panel Backend"  fi}# Update Trojan Panel Coreupdate_trojan_panel_core() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-core$") ]]; then    echo_content red "---> Please install the Trojan Panel Core first"    exit 0  fi  trojan_panel_core_current_version=$(docker exec trojan-panel-core ./trojan-panel-core -version)  if [[ -z "${trojan_panel_core_current_version}" || ! "${trojan_panel_core_current_version}" =~ ^v.* || ! $(version_ge "${trojan_panel_core_current_version}" "v2.1.1") ]]; then    echo_content red "---> The current version does not support online updates"    exit 0  fi  echo_content yellow "Tip: The current version of the Trojan Panel Core (trojan-panel-core) is ${trojan_panel_core_current_version} The latest version is ${trojan_panel_core_latest_version}"  if [[ "${trojan_panel_core_current_version}" != "${trojan_panel_core_latest_version}" ]]; then    echo_content green "---> Update Trojan Panel Core"    mariadb_ip=$(get_ini_value ${trojan_panel_core_config_path} mysql.host)    mariadb_port=$(get_ini_value ${trojan_panel_core_config_path} mysql.port)    mariadb_user=$(get_ini_value ${trojan_panel_core_config_path} mysql.user)    mariadb_pas=$(get_ini_value ${trojan_panel_core_config_path} mysql.password)    redis_host=$(get_ini_value ${trojan_panel_core_config_path} redis.host)    redis_port=$(get_ini_value ${trojan_panel_core_config_path} redis.port)    redis_pass=$(get_ini_value ${trojan_panel_core_config_path} redis.password)    grpc_port=$(get_ini_value ${trojan_panel_core_config_path} grpc.port)    trojan_panel_core_port=$(get_ini_value ${trojan_panel_core_config_path} server.port)    update_trojan_panel_core_database    docker exec trojan-panel-redis redis-cli -h "${redis_host}" -p "${redis_port}" -a "${redis_pass}" -e "flushall" &>/dev/null    docker rm -f trojan-panel-core &&      docker rmi -f jonssonyan/trojan-panel-core:2.2.0    domain=$(cat "${DOMAIN_FILE}")    docker pull jonssonyan/trojan-panel-core:2.2.0 &&      docker run -d --name trojan-panel-core --restart always \        --network=host \        -v ${TROJAN_PANEL_CORE_DATA}bin/xray/config/:${TROJAN_PANEL_CORE_DATA}bin/xray/config/ \        -v ${TROJAN_PANEL_CORE_DATA}bin/trojango/config/:${TROJAN_PANEL_CORE_DATA}bin/trojango/config/ \        -v ${TROJAN_PANEL_CORE_DATA}bin/hysteria/config/:${TROJAN_PANEL_CORE_DATA}bin/hysteria/config/ \        -v ${TROJAN_PANEL_CORE_DATA}bin/naiveproxy/config/:${TROJAN_PANEL_CORE_DATA}bin/naiveproxy/config/ \        -v ${TROJAN_PANEL_CORE_LOGS}:${TROJAN_PANEL_CORE_LOGS} \        -v ${TROJAN_PANEL_CORE_CONFIG}:${TROJAN_PANEL_CORE_CONFIG} \        -v ${CERT_PATH}:${CERT_PATH} \        -v ${WEB_PATH}:${WEB_PATH} \        -v /etc/localtime:/etc/localtime \        -e GIN_MODE=release \        -e "mariadb_ip=${mariadb_ip}" \        -e "mariadb_port=${mariadb_port}" \        -e "mariadb_user=${mariadb_user}" \        -e "mariadb_pas=${mariadb_pas}" \        -e "database=${database}" \        -e "account-table=${account_table}" \        -e "redis_host=${redis_host}" \        -e "redis_port=${redis_port}" \        -e "redis_pass=${redis_pass}" \        -e "crt_path=${CERT_PATH}${domain}.crt" \        -e "key_path=${CERT_PATH}${domain}.key" \        -e "grpc_port=${grpc_port}" \        -e "server_port=${trojan_panel_core_port}" \        jonssonyan/trojan-panel-core:2.2.0    if [[ -n $(docker ps -q -f "name=^trojan-panel-core$" -f "status=running") ]]; then      echo_content skyBlue "---> Trojan Panel Core update completed"    else      echo_content red "---> Trojan Panel Core update fails or runs abnormally, please try to repair or uninstall and reinstall"    fi  else    echo_content skyBlue "---> You have installed the latest version of the Trojan Panel Core"  fi}# Uninstall Caddy2+httpsuninstall_caddy2() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-caddy$") ]]; then    echo_content green "---> Uninstall Caddy2+https"    docker rm -f trojan-panel-caddy &&      rm -rf ${CADDY_DATA}    echo_content skyBlue "---> Caddy2+https uninstallation completed"  else    echo_content red "---> Please install Caddy2+https first"  fi}# Uninstall Nginxuninstall_nginx() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-nginx") ]]; then    echo_content green "---> Uninstall Nginx"    docker rm -f trojan-panel-nginx &&      rm -rf ${NGINX_DATA}    echo_content skyBlue "---> Nginx uninstallation completed"  else    echo_content red "---> Please install Nginx first"  fi}# Uninstall MariaDBuninstall_mariadb() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-mariadb$") ]]; then    echo_content green "---> Uninstall MariaDB"    docker rm -f trojan-panel-mariadb &&      rm -rf ${MARIA_DATA}    echo_content skyBlue "---> MariaDB uninstall completed"  else    echo_content red "---> Please install MariaDB first"  fi}# Uninstall Redisuninstall_redis() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-redis$") ]]; then    echo_content green "---> Uninstall Redis"    docker rm -f trojan-panel-redis &&      rm -rf ${REDIS_DATA}    echo_content skyBlue "---> Redis uninstall completed"  else    echo_content red "---> Please install Redis first"  fi}# Uninstall Trojan Panel Frontenduninstall_trojan_panel_ui() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-ui$") ]]; then    echo_content green "---> Uninstall Trojan Panel Frontend"    docker rm -f trojan-panel-ui &&      docker rmi -f jonssonyan/trojan-panel-ui:2.1.6 &&      rm -rf ${TROJAN_PANEL_UI_DATA}    echo_content skyBlue "---> Trojan Panel Frontend uninstallation completed"  else    echo_content red "---> Please install the Trojan Panel Frontend first"  fi}# Uninstall Trojan Panel Backenduninstall_trojan_panel() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel$") ]]; then    echo_content green "---> Uninstall Trojan Panel Backend"    docker rm -f trojan-panel &&      docker rmi -f jonssonyan/trojan-panel:2.2.0 &&      rm -rf ${TROJAN_PANEL_DATA}    echo_content skyBlue "---> Trojan Panel Backend uninstallation completed"  else    echo_content red "---> Please install the Trojan Panel Backend first"  fi}# Uninstall Trojan Panel Coreuninstall_trojan_panel_core() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-core$") ]]; then    echo_content green "---> Uninstall Trojan Panel Core"    docker rm -f trojan-panel-core &&      docker rmi -f jonssonyan/trojan-panel-core:2.2.0 &&      rm -rf ${TROJAN_PANEL_CORE_DATA}    echo_content skyBlue "---> Trojan Panel Core uninstallation completed"  else    echo_content red "---> Please install the Trojan Panel Core first"  fi}# Uninstall all Trojan Panel related containersuninstall_all() {  echo_content green "---> Uninstall all Trojan Panel related containers"  docker rm -f $(docker ps -a -q -f "name=^trojan-panel")  docker rmi -f $(docker images | grep "^jonssonyan/trojan-panel" | awk '{print $3}')  rm -rf ${TP_DATA}  echo_content skyBlue "---> Uninstall all Trojan Panel related containers completed"}# Modify Trojan Panel Frontend portupdate_trojan_panel_ui_port() {  if [[ -n $(docker ps -q -f "name=^trojan-panel-ui$" -f "status=running") ]]; then    echo_content green "---> Modify Trojan Panel Frontend port"    trojan_panel_ui_port=$(grep 'listen.*ssl' ${UI_NGINX_CONFIG} | awk '{print $2}')    if [[ -z "${trojan_panel_ui_port}" ]]; then      ui_https=0      trojan_panel_ui_port=$(grep -oP 'listen\s+\K\d+' ${UI_NGINX_CONFIG} | awk 'NR==1')    fi    if [[ -z "${trojan_panel_ui_port}" ]]; then      echo_content red "---> Trojan Panel Frontend port not queried"      exit 0    fi    echo_content yellow "Tip: The current port of the Trojan Panel Frontend (trojan-panel-ui) is ${trojan_panel_ui_port}"    read -r -p "Please enter the new port of the Trojan Panel Frontend (default: 8888): " trojan_panel_ui_port    [[ -z "${trojan_panel_ui_port}" ]] && trojan_panel_ui_port="8888"    if [[ ${ui_https} == 0 ]]; then      # http      sed -i "s/listen.*;/listen       ${trojan_panel_ui_port};/g" ${UI_NGINX_CONFIG} &&        sed -i "s/http:\/\/\$host:.*\$request_uri;/http:\/\/\$host:${trojan_panel_ui_port}\$request_uri;/g" ${UI_NGINX_CONFIG} &&        docker restart trojan-panel-ui    else      # https      sed -i "s/listen.*ssl;/listen       ${trojan_panel_ui_port} ssl;/g" ${UI_NGINX_CONFIG} &&        sed -i "s/https:\/\/\$host:.*\$request_uri;/https:\/\/\$host:${trojan_panel_ui_port}\$request_uri;/g" ${UI_NGINX_CONFIG} &&        docker restart trojan-panel-ui    fi    if [[ "$?" == "0" ]]; then      echo_content skyBlue "---> Trojan Panel Frontend port modification completed"    else      echo_content red "---> Trojan Panel Frontend port modification failed"    fi  else    echo_content red "---> The Trojan Panel Frontend is not installed or is running abnormally, please repair or uninstall and reinstall and try again"  fi}# Refresh Redis cacheredis_flush_all() {  if [[ -z $(docker ps -a -q -f "name=^trojan-panel-redis$") ]]; then    echo_content red "---> Please install Redis first"    exit 0  fi  if [[ -z $(docker ps -q -f "name=^trojan-panel-redis$" -f "status=running") ]]; then    echo_content red "---> Redis is running abnormally"    exit 0  fi  echo_content green "---> Refresh Redis cache"  read -r -p "Please enter the IP address of Redis (default: local host): " redis_host  [[ -z "${redis_host}" ]] && redis_host="127.0.0.1"  read -r -p "Please enter the port of Redis (default: 6378): " redis_port  [[ -z "${redis_port}" ]] && redis_port=6378  while read -r -p "Please enter the Redis password (required): " redis_pass; do    if [[ -z "${redis_pass}" ]]; then      echo_content red "Password can not be empty"    else      break    fi  done  docker exec trojan-panel-redis redis-cli -h "${redis_host}" -p "${redis_port}" -a "${redis_pass}" -e "flushall" &>/dev/null  echo_content skyBlue "---> Redis cache refresh completed"}# Replace certificatechange_cert() {  domain_1=$(cat "${DOMAIN_FILE}")  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-caddy$") ]]; then    docker rm -f trojan-panel-caddy &&      rm -rf ${CADDY_LOG}* &&      echo "" >${CADDY_CONFIG} &&      rm -rf ${WEB_PATH}*  fi  rm -rf ${CERT_PATH}* &&    echo "" >${DOMAIN_FILE}  install_reverse_proxy  install_cert  domain_2=$(cat "${DOMAIN_FILE}")  if [[ -n "${domain_1}" && -n "${domain_2}" ]]; then    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-nginx$") ]]; then      sed -i "s/${domain_1}/${domain_2}/g" ${NGINX_CONFIG} &&        docker restart trojan-panel-nginx    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-ui$") ]]; then      sed -i "s/${domain_1}/${domain_2}/g" ${UI_NGINX_DATA} &&        docker restart trojan-panel-ui    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-core$") ]]; then      find /tpdata/trojan-panel-core/bin/ -type f -exec sed -i "s/${domain_1}/${domain_2}/g" {} + &&        sed -i "s/${domain_1}/${domain_2}/g" ${trojan_panel_core_config_path} &&        docker restart trojan-panel-core    fi  fi}# Forgot sysadmin passwordforget_pass() {  while :; do    echo_content yellow "1. Query MariaDB password"    echo_content yellow "2. Query Redis password"    echo_content yellow "3. Reset the username and password of the admin panel system administrator"    echo_content yellow "4. Quit"    read -r -p "Please choose (default: 4): " forget_pass_option    [[ -z "${forget_pass_option}" ]] && forget_pass_option=4    case ${forget_pass_option} in    1)      if [[ -n $(docker ps -a -q -f "name=^trojan-panel$") ]]; then        mariadb_user=$(get_ini_value ${trojan_panel_config_path} mysql.user)        mariadb_pas=$(get_ini_value ${trojan_panel_config_path} mysql.password)        echo_content red "\n=============================================================="        echo_content yellow "MariaDB ${mariadb_user} password (please keep it safe): ${mariadb_pas}"        echo_content red "\n=============================================================="      else        echo_content red "---> Please execute on the Trojan Panel backend server"      fi      ;;    2)      if [[ -n $(docker ps -a -q -f "name=^trojan-panel$") ]]; then        redis_pass=$(get_ini_value ${trojan_panel_config_path} redis.password)        echo_content red "\n=============================================================="        echo_content yellow "Redis password (please keep it safe): ${redis_pass}"        echo_content red "\n=============================================================="      else        echo_content red "---> Please execute on the Trojan Panel backend server"      fi      ;;    3)      if [[ -n $(docker ps -a -q -f "name=^trojan-panel-mariadb$") ]]; then        read -r -p "Please enter the IP address of MariaDB (default: local host): " mariadb_ip        [[ -z "${mariadb_ip}" ]] && mariadb_ip="127.0.0.1"        read -r -p "Please enter the port of MariaDB (default: 9507): " mariadb_port        [[ -z "${mariadb_port}" ]] && mariadb_port=9507        read -r -p "Please enter the username of MariaDB (default: root): " mariadb_user        [[ -z "${mariadb_user}" ]] && mariadb_user="root"        while read -r -p "Please enter the password of MariaDB (required): " mariadb_pas; do          if [[ -z "${mariadb_pas}" ]]; then            echo_content red "Password can not be empty"          else            break          fi        done        docker exec trojan-panel-mariadb mysql --default-character-set=utf8 -h"${mariadb_ip}" -P"${mariadb_port}" -u"${mariadb_user}" -p"${mariadb_pas}" -Dtrojan_panel_db -e "update account set username = 'sysadmin',pass = 'tFjD2X1F6i9FfWp2GDU5Vbi1conuaChDKIYbw9zMFrqvMoSz',hash='4366294571b8b267d9cf15b56660f0a70659568a86fc270a52fdc9e5' where id = 1 limit 1"        if [[ "$?" == "0" ]]; then          echo_content red "\n=============================================================="          echo_content yellow "System administrator Default username: sysadmin Default password: 123456"          echo_content yellow "Please log in to the management panel to change the password in time"          echo_content red "\n=============================================================="        else          echo_content red "Admin panel sysadmin username and password reset failed"        fi      else        echo_content red "---> Please execute on the MariaDB server"      fi      ;;    4)      break      ;;    *)      echo_content red "No such option"      continue      ;;    esac  done}# Fault detectionfailure_testing() {  echo_content green "---> Start troubleshooting"  if [[ ! $(docker -v 2>/dev/null) ]]; then    echo_content red "---> Docker is running abnormally"  else    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-caddy$") ]]; then      if [[ -z $(docker ps -q -f "name=^trojan-panel-caddy$" -f "status=running") ]]; then        echo_content red "---> Caddy2 is running abnormally and the running log is as follows:"        docker logs trojan-panel-caddy      fi      domain=$(cat "${DOMAIN_FILE}")      if [[ -n ${domain} && ! -f "${CERT_PATH}${domain}.crt" ]]; then        echo_content red "---> The certificate application is abnormal, please try 1. Change the sub-domain name to re-build 2. Restart the server to re-apply for the certificate 3. Re-build and select the custom certificate option"        if [[ -f ${CADDY_LOG}error.log ]]; then          echo_content red "Caddy2 error log is as follows:"          tail -n 20 ${CADDY_LOG}error.log | grep error        fi      fi    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-mariadb$") && -z $(docker ps -q -f "name=^trojan-panel-mariadb$" -f "status=running") ]]; then      echo_content red "---> The MariaDB is running abnormally and the running log is as follows:"      docker logs trojan-panel-mariadb    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-redis$") && -z $(docker ps -q -f "name=^trojan-panel-redis$" -f "status=running") ]]; then      echo_content red "---> The Redis is running abnormally and the running log is as follows:"      docker logs trojan-panel-redis    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel$") && -z $(docker ps -q -f "name=^trojan-panel$" -f "status=running") ]]; then      echo_content red "---> The Trojan Panel Backend is running abnormally and the running log is as follows:"      if [[ -f ${TROJAN_PANEL_LOGS}trojan-panel.log ]]; then        tail -n 20 ${TROJAN_PANEL_LOGS}trojan-panel.log | grep error      else        docker logs trojan-panel      fi    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-ui$") && -z $(docker ps -q -f "name=^trojan-panel-ui$" -f "status=running") ]]; then      echo_content red "---> The Trojan Panel Frontend is running abnormally and the running log is as follows:"      docker logs trojan-panel-ui    fi    if [[ -n $(docker ps -a -q -f "name=^trojan-panel-core$") && -z $(docker ps -q -f "name=^trojan-panel-core$" -f "status=running") ]]; then      echo_content red "---> The Trojan Panel Core is running abnormally and the running log is as follows:"      if [[ -f ${TROJAN_PANEL_CORE_LOGS}trojan-panel.log ]]; then        tail -n 20 ${TROJAN_PANEL_CORE_LOGS}trojan-panel.log | grep error      else        docker logs trojan-panel-core      fi    fi  fi  echo_content green "---> Troubleshooting ended"}log_query() {  while :; do    echo_content skyBlue "Applications that can query logs are as follows:"    echo_content yellow "1. Trojan Panel Backend"    echo_content yellow "2. Trojan Panel Frontend"    echo_content yellow "3. Quit"    read -r -p "Please select an application (default: 3): " select_log_query_type    [[ -z "${select_log_query_type}" ]] && select_log_query_type=3    case ${select_log_query_type} in    1)      log_file_path=${TROJAN_PANEL_LOGS}trojan-panel.log      ;;    2)      log_file_path=${TROJAN_PANEL_CORE_LOGS}trojan-panel-core.log      ;;    3)      break      ;;    *)      echo_content red "No such option"      continue      ;;    esac    read -r -p "Please enter the number of rows to query (default: 20): " select_log_query_line_type    [[ -z "${select_log_query_line_type}" ]] && select_log_query_line_type=20    if [[ -f ${log_file_path} ]]; then      echo_content skyBlue "The log is as follows:"      tail -n ${select_log_query_line_type} ${log_file_path}    else      echo_content red "No log file exists"    fi  done}version_query() {  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-ui$") && -n $(docker ps -q -f "name=^trojan-panel-ui$" -f "status=running") ]]; then    trojan_panel_ui_current_version=$(docker exec trojan-panel-ui cat ${TROJAN_PANEL_UI_DATA}version)    echo_content yellow "The current version of Trojan Panel Frontend(trojan-panel-ui) is ${trojan_panel_ui_current_version} the latest version is ${trojan_panel_ui_latest_version}"  fi  if [[ -n $(docker ps -a -q -f "name=^trojan-panel$") && -n $(docker ps -q -f "name=^trojan-panel$" -f "status=running") ]]; then    trojan_panel_current_version=$(docker exec trojan-panel ./trojan-panel -version)    echo_content yellow "The current version of Trojan Panel Backend(trojan-panel) is ${trojan_panel_current_version} the latest version is ${trojan_panel_latest_version}"  fi  if [[ -n $(docker ps -a -q -f "name=^trojan-panel-core$") && -n $(docker ps -q -f "name=^trojan-panel-core$" -f "status=running") ]]; then    trojan_panel_core_current_version=$(docker exec trojan-panel-core ./trojan-panel-core -version)    echo_content yellow "The current version of Trojan Panel Core(trojan-panel-core) is ${trojan_panel_core_current_version} the latest version is ${trojan_panel_core_latest_version}"  fi}main() {  cd "$HOME" || exit 0  init_var  mkdir_tools  check_sys  depend_install  clear  echo_content red "\n=============================================================="  echo_content skyBlue "System Required: CentOS 7+/Ubuntu 18+/Debian 10+"  echo_content skyBlue "Version: v2.2.0"  echo_content skyBlue "Description: One click Install Trojan Panel server"  echo_content skyBlue "Author: jonssonyan <https://jonssonyan.com>"  echo_content skyBlue "Github: https://github.com/trojanpanel"  echo_content skyBlue "Docs: https://trojanpanel.github.io"  echo_content red "\n=============================================================="  echo_content yellow "1. Install Trojan Panel Frontend"  echo_content yellow "2. Install Trojan Panel Backend"  echo_content yellow "3. Install Trojan Panel Core"  echo_content yellow "4. Install Caddy2+https"  echo_content yellow "5. Install Nginx"  echo_content yellow "6. Install MariaDB"  echo_content yellow "7. Install Redis"  echo_content green "\n=============================================================="  echo_content yellow "8. Update Trojan Panel Frontend"  echo_content yellow "9. Update Trojan Panel Backend"  echo_content yellow "10. Update Trojan Panel Core"  echo_content green "\n=============================================================="  echo_content yellow "11. Uninstall Trojan Panel Frontend"  echo_content yellow "12. Uninstall Trojan Panel Backend"  echo_content yellow "13. Uninstall Trojan Panel Core"  echo_content yellow "14. Uninstall Caddy2+https"  echo_content yellow "15. Uninstall Nginx"  echo_content yellow "16. Uninstall MariaDB"  echo_content yellow "17. Uninstall Redis"  echo_content yellow "18. Uninstall all Trojan Panel related containers"  echo_content green "\n=============================================================="  echo_content yellow "19. Modify Trojan Panel Frontend port"  echo_content yellow "20. Refresh Redis cache"  echo_content yellow "21. Replace certificate"  echo_content yellow "22. Forgot sysadmin password"  echo_content green "\n=============================================================="  echo_content yellow "23. Fault detection"  echo_content yellow "24. Log query"  echo_content yellow "25. Version query"  read -r -p "Please choose: " selectInstall_type  case ${selectInstall_type} in  1)    install_docker    install_reverse_proxy    install_cert    install_trojan_panel_ui    ;;  2)    install_docker    install_mariadb    install_redis    install_trojan_panel    ;;  3)    install_docker    install_reverse_proxy    install_cert    install_trojan_panel_core    ;;  4)    install_docker    install_caddy2    ;;  5)    install_docker    install_nginx    ;;  6)    install_docker    install_mariadb    ;;  7)    install_docker    install_redis    ;;  8)    update_trojan_panel_ui    ;;  9)    update_trojan_panel    ;;  10)    update_trojan_panel_core    ;;  11)    uninstall_trojan_panel_ui    ;;  12)    uninstall_trojan_panel    ;;  13)    uninstall_trojan_panel_core    ;;  14)    uninstall_caddy2    ;;  15)    uninstall_nginx    ;;  16)    uninstall_mariadb    ;;  17)    uninstall_redis    ;;  18)    uninstall_all    ;;  19)    update_trojan_panel_ui_port    ;;  20)    redis_flush_all    ;;  21)    change_cert    ;;  22)    forget_pass    ;;  23)    failure_testing    ;;  24)    log_query    ;;  25)    version_query    ;;  *)    echo_content red "No such option"    ;;  esac}main
 |