spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1#!/usr/bin/env bash2# Shared helpers for deploy/bin/*.sh — sourced, not executed.3# Targets: data = BHS128 (public via BHS64 gateway, stores on 10.68.0.1) · crawl = BHS64b (workers, 10.68.0.2)4set -euo pipefail56REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"7REMOTE_DIR="${DCI_REMOTE_DIR:-/srv/dci/app}"8BACKUP_DIR="${DCI_BACKUP_DIR:-/srv/dci/backups}"9OFFSITE_DIR="${DCI_OFFSITE_DIR:-/srv/dci-backups}"10DATA_WG_IP="${DATA_WG_IP:-10.67.0.60}"11DATA_PRIVATE_IP="${DATA_PRIVATE_IP:-10.68.0.1}"12CRAWL_PRIVATE_IP="${CRAWL_PRIVATE_IP:-10.68.0.2}"13PUBLIC_URL="${DCI_PUBLIC_URL:-https://www.datacenterindex.io}"14SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=15 -o ServerAliveInterval=30)1516c_bold=$'\033[1m'; c_dim=$'\033[2m'; c_red=$'\033[31m'; c_grn=$'\033[32m'; c_ylw=$'\033[33m'; c_rst=$'\033[0m'17log() { printf '%s▸ %s%s\n' "$c_bold" "$*" "$c_rst"; }18ok() { printf '%s✓ %s%s\n' "$c_grn" "$*" "$c_rst"; }19warn() { printf '%s! %s%s\n' "$c_ylw" "$*" "$c_rst" >&2; }20die() { printf '%s✗ %s%s\n' "$c_red" "$*" "$c_rst" >&2; exit 1; }2122# target → ssh alias23host_for() {24 case "$1" in25 data) echo "${DCI_DATA_HOST:-BHS128}" ;;26 crawl) echo "${DCI_CRAWL_HOST:-BHS64b}" ;;27 *) die "unknown target '$1' (data|crawl)" ;;28 esac29}30check_target() { case "${1:-}" in data|crawl) ;; *) die "usage: $(basename "$0") data|crawl" ;; esac; }3132# service → target (for logs.sh / status.sh convenience)33target_for_service() {34 case "$1" in35 worker|worker-b) echo crawl ;;36 *) echo data ;;37 esac38}3940remote() { # remote <target> <cmd...>41 local t="$1"; shift42 ssh "${SSH_OPTS[@]}" "$(host_for "$t")" "$@"43}4445# The compose command as executed ON the remote host (docker or sudo docker, whichever works).46compose_prefix() { # compose_prefix <target>47 local t="$1"48 echo "cd $REMOTE_DIR && TSX_VERSION=$(tsx_version) \$(docker info >/dev/null 2>&1 && echo docker || echo 'sudo docker') compose -f deploy/compose.$t.yml --env-file deploy/.env.$t"49}50compose() { # compose <target> <compose args...>51 local t="$1"; shift52 remote "$t" "$(compose_prefix "$t") $*"53}5455tsx_version() {56 sed -nE 's/^ tsx@([0-9]+\.[0-9]+\.[0-9]+):.*/\1/p' "$REPO_ROOT/pnpm-lock.yaml" | head -1 | grep . || echo 4.23.1357}5859require_env_file() { # require_env_file <target>60 local f="$REPO_ROOT/deploy/.env.$1"61 if [[ ! -f "$f" ]]; then62 if remote "$1" "test -f $REMOTE_DIR/deploy/.env.$1"; then63 warn "no local $f — keeping the existing remote copy"64 return 065 fi66 die "missing $f (copy deploy/.env.$1.example and fill the secrets)"67 fi68 if grep -qE '^(POSTGRES_PASSWORD|REDIS_PASSWORD|S3_SECRET_KEY)=$' "$f"; then69 die "$f still has empty secrets"70 fi71}7273ensure_remote_layout() { # ensure_remote_layout <target>74 local t="$1"75 # clickhouse (uid 101 in its container) writes BACKUP files into $BACKUP_DIR/clickhouse → sticky world-writable76 remote "$t" "sudo mkdir -p $REMOTE_DIR $BACKUP_DIR/pg $BACKUP_DIR/config $BACKUP_DIR/minio $BACKUP_DIR/clickhouse /srv/dci/out \77 && sudo chown -R \$USER:\$USER /srv/dci && sudo chmod 1777 $BACKUP_DIR/clickhouse /srv/dci/out \78 && (docker info >/dev/null 2>&1 || sudo usermod -aG docker \$USER)"79}8081sync_repo() { # sync_repo <target>82 local t="$1" host; host="$(host_for "$t")"83 log "rsync repo → $host:$REMOTE_DIR"84 rsync -az --delete \85 --exclude-from="$REPO_ROOT/deploy/rsync-exclude.txt" \86 -e "ssh ${SSH_OPTS[*]}" \87 "$REPO_ROOT/" "$host:$REMOTE_DIR/"88 if [[ -f "$REPO_ROOT/deploy/.env.$t" ]]; then89 scp -q "${SSH_OPTS[@]}" "$REPO_ROOT/deploy/.env.$t" "$host:$REMOTE_DIR/deploy/.env.$t" && remote "$t" "chmod 600 $REMOTE_DIR/deploy/.env.$t"90 fi91 remote "$t" "chmod +x $REMOTE_DIR/deploy/bin/*.sh $REMOTE_DIR/deploy/bin/remote/*.sh $REMOTE_DIR/deploy/docker/entrypoint.sh $REMOTE_DIR/deploy/minio/init.sh"92 ok "synced"93}9495wait_http() { # wait_http <target> <url> [attempts] [sleep]96 local t="$1" url="$2" n="${3:-60}" s="${4:-5}" i97 for ((i = 1; i <= n; i++)); do98 if remote "$t" "curl -fsS -m 5 -o /dev/null $url"; then ok "healthy: $url"; return 0; fi99 printf '%s waiting for %s (%d/%d)%s\n' "$c_dim" "$url" "$i" "$n" "$c_rst"100 sleep "$s"101 done102 return 1103}104