#!/usr/bin/env bash set -Eeuo pipefail APP_DIR="${APP_DIR:-/opt/cmpp-platform}" REPO_URL="${REPO_URL:-http://175.27.255.91:3000/hectorzhao/lislgosms.git}" BRANCH="${BRANCH:-main}" PUBLIC_HTTP_PORT="${PUBLIC_HTTP_PORT:-12026}" API_PORT="${API_PORT:-3000}" GATEWAY_CONTROL_ADDR="${GATEWAY_CONTROL_ADDR:-127.0.0.1:8090}" GATEWAY_CMPP_ADDR="${GATEWAY_CMPP_ADDR:-0.0.0.0:17890}" DB_NAME="${DB_NAME:-cmpp_platform}" DB_USER="${DB_USER:-cmpp}" DB_PASSWORD="${DB_PASSWORD:-$(openssl rand -hex 24 | tr -d '\n')}" MINIO_ROOT_USER="${MINIO_ROOT_USER:-cmpp_minio}" MINIO_ROOT_PASSWORD="${MINIO_ROOT_PASSWORD:-$(openssl rand -base64 32 | tr -d '\n')}" MINIO_BUCKET="${MINIO_BUCKET:-cmpp-platform}" OBJECT_STORAGE_DRIVER="${OBJECT_STORAGE_DRIVER:-minio}" OBJECT_STORAGE_LOCAL_ROOT="${OBJECT_STORAGE_LOCAL_ROOT:-/var/lib/cmpp-platform/object-storage}" PROD_ADMIN_EMAIL="${PROD_ADMIN_EMAIL:-admin@example.com}" PROD_ADMIN_USERNAME="${PROD_ADMIN_USERNAME:-prod_admin}" PROD_ADMIN_PASSWORD="${PROD_ADMIN_PASSWORD:-$(openssl rand -base64 18 | tr -d '\n')}" if [[ "$(id -u)" -ne 0 ]]; then echo "Run as root." >&2 exit 1 fi log() { printf '\n[%s] %s\n' "$(date '+%F %T')" "$*"; } install_packages() { log "Installing OS packages" if command -v apt-get >/dev/null 2>&1; then apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl gnupg git nginx redis-server postgresql postgresql-contrib build-essential tar gzip xz-utils openssl elif command -v dnf >/dev/null 2>&1; then dnf install -y ca-certificates curl git nginx redis postgresql-server postgresql-contrib gcc gcc-c++ make tar gzip xz openssl if [[ ! -d /var/lib/pgsql/data/base ]]; then postgresql-setup --initdb fi elif command -v yum >/dev/null 2>&1; then yum install -y ca-certificates curl git nginx redis postgresql-server postgresql-contrib gcc gcc-c++ make tar gzip xz openssl if [[ ! -d /var/lib/pgsql/data/base ]]; then postgresql-setup initdb fi else echo "Unsupported Linux distribution: apt-get/dnf/yum not found." >&2 exit 1 fi } install_node() { local version="${NODE_VERSION:-22.21.1}" local arch case "$(uname -m)" in x86_64|amd64) arch="x64" ;; aarch64|arm64) arch="arm64" ;; *) echo "Unsupported Node.js architecture: $(uname -m)" >&2; exit 1 ;; esac if command -v node >/dev/null 2>&1 && [[ "$(node -v | sed 's/^v//' | cut -d. -f1)" -ge 22 ]]; then return fi log "Installing Node.js ${version} for linux-${arch}" curl -fL "https://nodejs.org/dist/v${version}/node-v${version}-linux-${arch}.tar.xz" -o /tmp/node.tar.xz rm -rf /usr/local/lib/nodejs mkdir -p /usr/local/lib/nodejs tar -C /usr/local/lib/nodejs -xJf /tmp/node.tar.xz --strip-components=1 ln -sf /usr/local/lib/nodejs/bin/node /usr/local/bin/node ln -sf /usr/local/lib/nodejs/bin/npm /usr/local/bin/npm ln -sf /usr/local/lib/nodejs/bin/npx /usr/local/bin/npx ln -sf /usr/local/lib/nodejs/bin/corepack /usr/local/bin/corepack } install_go() { local version="${GO_VERSION:-1.26.0}" local arch case "$(uname -m)" in x86_64|amd64) arch="amd64" ;; aarch64|arm64) arch="arm64" ;; *) echo "Unsupported Go architecture: $(uname -m)" >&2; exit 1 ;; esac if command -v go >/dev/null 2>&1 && [[ "$(go version | awk '{print $3}' | sed 's/go//')" == "$version" ]]; then return fi log "Installing Go ${version} for linux-${arch}" local downloaded="" for url in \ "https://dl.google.com/go/go${version}.linux-${arch}.tar.gz" \ "https://golang.google.cn/dl/go${version}.linux-${arch}.tar.gz" \ "https://go.dev/dl/go${version}.linux-${arch}.tar.gz"; do if curl -fL --connect-timeout 20 --max-time 300 "$url" -o /tmp/go.tar.gz; then downloaded="yes" break fi done if [[ "$downloaded" != "yes" ]]; then echo "Failed to download Go ${version} for linux-${arch}." >&2 exit 1 fi rm -rf /usr/local/go tar -C /usr/local -xzf /tmp/go.tar.gz ln -sf /usr/local/go/bin/go /usr/local/bin/go } install_minio() { if [[ "$OBJECT_STORAGE_DRIVER" == "local" ]]; then log "Skipping MinIO install because OBJECT_STORAGE_DRIVER=local" mkdir -p "$OBJECT_STORAGE_LOCAL_ROOT" return fi local arch case "$(uname -m)" in x86_64|amd64) arch="amd64" ;; aarch64|arm64) arch="arm64" ;; *) echo "Unsupported MinIO architecture: $(uname -m)" >&2; exit 1 ;; esac if [[ -x /usr/local/bin/minio ]]; then log "MinIO already installed" else log "Installing MinIO for linux-${arch}" curl -fL "https://dl.min.io/server/minio/release/linux-${arch}/minio" -o /usr/local/bin/minio chmod +x /usr/local/bin/minio fi useradd --system --home /var/lib/minio --shell /usr/sbin/nologin minio 2>/dev/null || true mkdir -p /var/lib/minio chown -R minio:minio /var/lib/minio } start_infra() { log "Starting PostgreSQL and Redis" systemctl enable --now postgresql || systemctl enable --now postgresql.service systemctl enable --now redis-server 2>/dev/null || systemctl enable --now redis runuser -u postgres -- psql <"${hba_file}.tmp" mv "${hba_file}.tmp" "$hba_file" chown postgres:postgres "$hba_file" chmod 600 "$hba_file" fi systemctl reload postgresql || systemctl reload postgresql.service } write_env() { log "Writing production environment" mkdir -p /etc/cmpp-platform "$APP_DIR" "$APP_DIR/logs/api" "$APP_DIR/logs/gateway" "$APP_DIR/backups" "$OBJECT_STORAGE_LOCAL_ROOT" cat >/etc/cmpp-platform/cmpp-platform.env </etc/cmpp-platform/minio.env </etc/systemd/system/cmpp-minio.service <<'EOF' [Unit] Description=CMPP MinIO object storage After=network.target [Service] User=minio Group=minio EnvironmentFile=/etc/cmpp-platform/minio.env ExecStart=/usr/local/bin/minio server /var/lib/minio --address 127.0.0.1:9000 --console-address 127.0.0.1:9001 Restart=always RestartSec=5 [Install] WantedBy=multi-user.target EOF cat >/etc/systemd/system/cmpp-api.service </etc/systemd/system/cmpp-gateway.service </etc/nginx/conf.d/cmpp-platform.conf </root/cmpp-platform-credentials.txt <:${PUBLIC_HTTP_PORT}" echo "Gateway control health: http://127.0.0.1:8090/health" echo "CMPP inbound port variable reserved: ${GATEWAY_CMPP_ADDR}"