2026-05-26 07:50:43 +08:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2026-05-27 09:39:05 +08:00
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
2026-05-26 07:50:43 +08:00
|
|
|
# shellcheck disable=SC1091
|
2026-05-27 09:39:05 +08:00
|
|
|
source "$ROOT_DIR/scripts/deploy/remote43_patched_stack_lib.sh"
|
2026-05-26 07:50:43 +08:00
|
|
|
|
|
|
|
|
KEY="${KEY:-/home/long/下载/zjsea.pem}"
|
|
|
|
|
REMOTE="${REMOTE:-ubuntu@43.155.133.187}"
|
|
|
|
|
STACK_NAME="${STACK_NAME:-sub2api-patched-$(date +%Y%m%d)}"
|
|
|
|
|
HOST_PORT="${HOST_PORT:-18139}"
|
|
|
|
|
CRM_PORT="${CRM_PORT:-18143}"
|
|
|
|
|
LOCAL_HOST_TUNNEL_PORT="${LOCAL_HOST_TUNNEL_PORT:-$HOST_PORT}"
|
|
|
|
|
LOCAL_CRM_TUNNEL_PORT="${LOCAL_CRM_TUNNEL_PORT:-$CRM_PORT}"
|
|
|
|
|
HOST_IMAGE="${HOST_IMAGE:-weishaw/sub2api:0.1.129}"
|
|
|
|
|
HOST_CONTAINER_PORT="${HOST_CONTAINER_PORT:-8080}"
|
|
|
|
|
PG_IMAGE="${PG_IMAGE:-postgres:16-alpine}"
|
|
|
|
|
REDIS_IMAGE="${REDIS_IMAGE:-redis:7-alpine}"
|
|
|
|
|
DB_NAME="${DB_NAME:-sub2api}"
|
|
|
|
|
DB_PASSWORD="${DB_PASSWORD:-$(remote43_random_hex 16)}"
|
|
|
|
|
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@sub2api.local}"
|
|
|
|
|
ADMIN_PASSWORD="${ADMIN_PASSWORD:-Sub2API-Remote43-Temp-Admin-20260525}"
|
|
|
|
|
JWT_SECRET="${JWT_SECRET:-$(remote43_random_hex 24)}"
|
|
|
|
|
TOTP_ENCRYPTION_KEY="${TOTP_ENCRYPTION_KEY:-$(remote43_random_hex 32)}"
|
|
|
|
|
CRM_ADMIN_TOKEN="${CRM_ADMIN_TOKEN:-$(remote43_random_hex 24)}"
|
|
|
|
|
HOST_NAME="${HOST_NAME:-remote43-patched-${HOST_PORT}}"
|
|
|
|
|
HOST_BINARY="${HOST_BINARY:-}"
|
|
|
|
|
CRM_BINARY="${CRM_BINARY:-$ROOT_DIR/server}"
|
|
|
|
|
PACK_DIR="${PACK_DIR:-$ROOT_DIR/packs/openai-cn-pack}"
|
|
|
|
|
LOCAL_SHARED_PACK_DIR="${LOCAL_SHARED_PACK_DIR:-/tmp/openai-cn-pack-${STACK_NAME}}"
|
2026-05-28 10:13:13 +08:00
|
|
|
LOCAL_REPO_BUNDLE="${LOCAL_REPO_BUNDLE:-/tmp/sub2api-cn-relay-manager-main.bundle}"
|
2026-05-26 07:50:43 +08:00
|
|
|
LOCAL_OPERATOR_ENV_FILE="${LOCAL_OPERATOR_ENV_FILE:-/tmp/remote43-patched-stack-${HOST_PORT}.env}"
|
|
|
|
|
LOCAL_TUNNEL_SCRIPT="${LOCAL_TUNNEL_SCRIPT:-/tmp/remote43-patched-stack-${HOST_PORT}.tunnel.sh}"
|
|
|
|
|
REMOTE_ROOT="${REMOTE_ROOT:-/home/ubuntu/${STACK_NAME}_${HOST_PORT}}"
|
|
|
|
|
REMOTE_PACK_PATH="${REMOTE_PACK_PATH:-$LOCAL_SHARED_PACK_DIR}"
|
2026-05-28 10:13:13 +08:00
|
|
|
REMOTE_REPO_ROOT="${REMOTE_REPO_ROOT:-/home/ubuntu/sub2api-cn-relay-manager-git-current}"
|
|
|
|
|
REMOTE_REPO_BUNDLE="$REMOTE_ROOT/sub2api-cn-relay-manager.bundle"
|
2026-05-26 07:50:43 +08:00
|
|
|
REMOTE_HOST_ENV_FILE="$REMOTE_ROOT/.env.host"
|
|
|
|
|
REMOTE_CRM_ENV_FILE="$REMOTE_ROOT/.env.crm"
|
|
|
|
|
REMOTE_BOOTSTRAP_FILE="$REMOTE_ROOT/bootstrap.sh"
|
|
|
|
|
REMOTE_HOST_BINARY="$REMOTE_ROOT/sub2api-patched"
|
|
|
|
|
REMOTE_CRM_BINARY="$REMOTE_ROOT/sub2api-cn-relay-manager-server"
|
|
|
|
|
REMOTE_DATA_DIR="$REMOTE_ROOT/data"
|
|
|
|
|
REMOTE_CRM_DB_FILE="$REMOTE_ROOT/sub2api-cn-relay-manager.db"
|
|
|
|
|
REMOTE_CRM_PID_FILE="$REMOTE_ROOT/crm.pid"
|
|
|
|
|
REMOTE_CRM_LOG_FILE="$REMOTE_ROOT/crm.log"
|
|
|
|
|
REMOTE_APP_CONTAINER="${REMOTE_APP_CONTAINER:-${STACK_NAME}-app}"
|
|
|
|
|
REMOTE_PG_CONTAINER="${REMOTE_PG_CONTAINER:-${STACK_NAME}-pg}"
|
|
|
|
|
REMOTE_REDIS_CONTAINER="${REMOTE_REDIS_CONTAINER:-${STACK_NAME}-redis}"
|
|
|
|
|
REMOTE_NETWORK="${REMOTE_NETWORK:-${STACK_NAME}-net}"
|
|
|
|
|
DRY_RUN="${DRY_RUN:-0}"
|
|
|
|
|
|
|
|
|
|
die() {
|
|
|
|
|
echo "$*" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require_cmd() {
|
|
|
|
|
command -v "$1" >/dev/null 2>&1 || die "missing command: $1"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
run_cmd() {
|
|
|
|
|
if [[ "$DRY_RUN" == "1" ]]; then
|
|
|
|
|
printf 'DRY_RUN:'
|
|
|
|
|
printf ' %q' "$@"
|
|
|
|
|
printf '\n'
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
"$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssh_remote() {
|
|
|
|
|
run_cmd ssh -i "$KEY" -o StrictHostKeyChecking=no "$REMOTE" "$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scp_remote() {
|
|
|
|
|
run_cmd scp -i "$KEY" -o StrictHostKeyChecking=no "$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prepare_local_shared_pack() {
|
|
|
|
|
case "$LOCAL_SHARED_PACK_DIR" in
|
|
|
|
|
/tmp/*) ;;
|
|
|
|
|
*)
|
|
|
|
|
die "LOCAL_SHARED_PACK_DIR must stay under /tmp, got: $LOCAL_SHARED_PACK_DIR"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
mkdir -p "$(dirname "$LOCAL_SHARED_PACK_DIR")"
|
|
|
|
|
rm -rf "$LOCAL_SHARED_PACK_DIR"
|
|
|
|
|
cp -R "$PACK_DIR" "$LOCAL_SHARED_PACK_DIR"
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-28 10:13:13 +08:00
|
|
|
prepare_local_repo_bundle() {
|
|
|
|
|
case "$LOCAL_REPO_BUNDLE" in
|
|
|
|
|
/tmp/*) ;;
|
|
|
|
|
*)
|
|
|
|
|
die "LOCAL_REPO_BUNDLE must stay under /tmp, got: $LOCAL_REPO_BUNDLE"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
mkdir -p "$(dirname "$LOCAL_REPO_BUNDLE")"
|
|
|
|
|
rm -f "$LOCAL_REPO_BUNDLE"
|
|
|
|
|
git -C "$ROOT_DIR" bundle create "$LOCAL_REPO_BUNDLE" main
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-26 07:50:43 +08:00
|
|
|
write_local_tunnel_script() {
|
|
|
|
|
cat > "$LOCAL_TUNNEL_SCRIPT" <<EOF
|
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
exec ssh -N \\
|
|
|
|
|
-L ${LOCAL_CRM_TUNNEL_PORT}:127.0.0.1:${CRM_PORT} \\
|
|
|
|
|
-L ${LOCAL_HOST_TUNNEL_PORT}:127.0.0.1:${HOST_PORT} \\
|
|
|
|
|
-i $(printf '%q' "$KEY") \\
|
|
|
|
|
-o StrictHostKeyChecking=no \\
|
|
|
|
|
$(printf '%q' "$REMOTE")
|
|
|
|
|
EOF
|
|
|
|
|
chmod +x "$LOCAL_TUNNEL_SCRIPT"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
write_operator_env() {
|
|
|
|
|
remote43_write_env_file "$LOCAL_OPERATOR_ENV_FILE" \
|
|
|
|
|
CRM_BASE "http://127.0.0.1:${LOCAL_CRM_TUNNEL_PORT}" \
|
|
|
|
|
HOST_BASE "http://127.0.0.1:${LOCAL_HOST_TUNNEL_PORT}" \
|
|
|
|
|
CRM_HOST_BASE "http://127.0.0.1:${HOST_PORT}" \
|
|
|
|
|
REMOTE_HOST_BASE "http://127.0.0.1:${HOST_PORT}" \
|
|
|
|
|
HOST_NAME "$HOST_NAME" \
|
|
|
|
|
PACK_PATH "$LOCAL_SHARED_PACK_DIR" \
|
|
|
|
|
REMOTE_HOST_ENV_FILE "$REMOTE_HOST_ENV_FILE" \
|
2026-05-28 10:13:13 +08:00
|
|
|
REMOTE_REPO_ROOT "$REMOTE_REPO_ROOT" \
|
2026-05-26 07:50:43 +08:00
|
|
|
KEY "$KEY" \
|
|
|
|
|
REMOTE "$REMOTE" \
|
|
|
|
|
CRM_ADMIN_TOKEN "$CRM_ADMIN_TOKEN"
|
|
|
|
|
chmod 600 "$LOCAL_OPERATOR_ENV_FILE"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main() {
|
|
|
|
|
require_cmd bash
|
|
|
|
|
require_cmd curl
|
2026-05-28 10:13:13 +08:00
|
|
|
require_cmd git
|
2026-05-26 07:50:43 +08:00
|
|
|
require_cmd python3
|
|
|
|
|
require_cmd ssh
|
|
|
|
|
require_cmd scp
|
|
|
|
|
remote43_require_file "$KEY" "ssh key"
|
|
|
|
|
[[ -n "${HOST_BINARY// }" ]] || die "HOST_BINARY is required"
|
|
|
|
|
remote43_require_file "$HOST_BINARY" "patched host binary"
|
|
|
|
|
remote43_require_file "$CRM_BINARY" "crm server binary"
|
|
|
|
|
[[ -d "$PACK_DIR" ]] || die "missing pack dir: $PACK_DIR"
|
|
|
|
|
[[ "$REMOTE_PACK_PATH" == "$LOCAL_SHARED_PACK_DIR" ]] || die "REMOTE_PACK_PATH must equal LOCAL_SHARED_PACK_DIR so local/remote PACK_PATH stay identical"
|
|
|
|
|
|
|
|
|
|
prepare_local_shared_pack
|
2026-05-28 10:13:13 +08:00
|
|
|
prepare_local_repo_bundle
|
2026-05-26 07:50:43 +08:00
|
|
|
write_local_tunnel_script
|
|
|
|
|
write_operator_env
|
|
|
|
|
|
|
|
|
|
local tmpdir host_env_file crm_env_file bootstrap_file
|
|
|
|
|
tmpdir="$(mktemp -d)"
|
|
|
|
|
trap "rm -rf $(printf '%q' "$tmpdir")" EXIT
|
|
|
|
|
host_env_file="$tmpdir/.env.host"
|
|
|
|
|
crm_env_file="$tmpdir/.env.crm"
|
|
|
|
|
bootstrap_file="$tmpdir/bootstrap.sh"
|
|
|
|
|
|
|
|
|
|
render_remote43_host_env \
|
|
|
|
|
"$REMOTE_PG_CONTAINER" \
|
|
|
|
|
"$REMOTE_REDIS_CONTAINER" \
|
|
|
|
|
"$DB_PASSWORD" \
|
|
|
|
|
"$DB_NAME" \
|
|
|
|
|
"$ADMIN_EMAIL" \
|
|
|
|
|
"$ADMIN_PASSWORD" \
|
|
|
|
|
"$JWT_SECRET" \
|
|
|
|
|
"$TOTP_ENCRYPTION_KEY" > "$host_env_file"
|
|
|
|
|
render_remote43_crm_env \
|
|
|
|
|
"$CRM_PORT" \
|
|
|
|
|
"file:${REMOTE_CRM_DB_FILE}?_foreign_keys=on&_busy_timeout=5000" \
|
2026-05-28 10:13:13 +08:00
|
|
|
"$CRM_ADMIN_TOKEN" \
|
|
|
|
|
"$REMOTE_REPO_ROOT" > "$crm_env_file"
|
2026-05-26 07:50:43 +08:00
|
|
|
render_remote43_bootstrap_script \
|
|
|
|
|
"$REMOTE_ROOT" \
|
|
|
|
|
"$REMOTE_HOST_ENV_FILE" \
|
|
|
|
|
"$REMOTE_CRM_ENV_FILE" \
|
|
|
|
|
"$(basename "$REMOTE_HOST_BINARY")" \
|
|
|
|
|
"$(basename "$REMOTE_CRM_BINARY")" \
|
|
|
|
|
"$REMOTE_DATA_DIR" \
|
|
|
|
|
"$REMOTE_CRM_DB_FILE" \
|
|
|
|
|
"$REMOTE_CRM_PID_FILE" \
|
|
|
|
|
"$REMOTE_CRM_LOG_FILE" \
|
|
|
|
|
"$REMOTE_APP_CONTAINER" \
|
|
|
|
|
"$REMOTE_PG_CONTAINER" \
|
|
|
|
|
"$REMOTE_REDIS_CONTAINER" \
|
|
|
|
|
"$REMOTE_NETWORK" \
|
|
|
|
|
"$HOST_IMAGE" \
|
|
|
|
|
"$PG_IMAGE" \
|
|
|
|
|
"$REDIS_IMAGE" \
|
|
|
|
|
"$DB_PASSWORD" \
|
|
|
|
|
"$DB_NAME" \
|
|
|
|
|
"$HOST_PORT" \
|
|
|
|
|
"$CRM_PORT" \
|
2026-05-28 10:13:13 +08:00
|
|
|
"$HOST_CONTAINER_PORT" \
|
|
|
|
|
"$REMOTE_REPO_ROOT" \
|
|
|
|
|
"$REMOTE_REPO_BUNDLE" > "$bootstrap_file"
|
2026-05-26 07:50:43 +08:00
|
|
|
chmod +x "$bootstrap_file"
|
|
|
|
|
|
|
|
|
|
ssh_remote "mkdir -p $(printf '%q' "$REMOTE_ROOT") $(printf '%q' "$(dirname "$REMOTE_PACK_PATH")") && rm -rf $(printf '%q' "$REMOTE_PACK_PATH")"
|
|
|
|
|
scp_remote "$HOST_BINARY" "$REMOTE:$REMOTE_HOST_BINARY"
|
|
|
|
|
scp_remote "$CRM_BINARY" "$REMOTE:$REMOTE_CRM_BINARY"
|
2026-05-28 10:13:13 +08:00
|
|
|
scp_remote "$LOCAL_REPO_BUNDLE" "$REMOTE:$REMOTE_REPO_BUNDLE"
|
2026-05-26 07:50:43 +08:00
|
|
|
scp_remote "$host_env_file" "$REMOTE:$REMOTE_HOST_ENV_FILE"
|
|
|
|
|
scp_remote "$crm_env_file" "$REMOTE:$REMOTE_CRM_ENV_FILE"
|
|
|
|
|
scp_remote "$bootstrap_file" "$REMOTE:$REMOTE_BOOTSTRAP_FILE"
|
|
|
|
|
scp_remote -r "$LOCAL_SHARED_PACK_DIR" "$REMOTE:$REMOTE_PACK_PATH"
|
|
|
|
|
ssh_remote "bash $(printf '%q' "$REMOTE_BOOTSTRAP_FILE")"
|
|
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
|
remote43 patched stack prepared
|
|
|
|
|
remote host base: http://127.0.0.1:${HOST_PORT}
|
|
|
|
|
remote crm base: http://127.0.0.1:${CRM_PORT}
|
|
|
|
|
remote host env file: ${REMOTE_HOST_ENV_FILE}
|
2026-05-28 10:13:13 +08:00
|
|
|
remote repo root: ${REMOTE_REPO_ROOT}
|
2026-05-26 07:50:43 +08:00
|
|
|
local operator env file: ${LOCAL_OPERATOR_ENV_FILE}
|
|
|
|
|
local tunnel script: ${LOCAL_TUNNEL_SCRIPT}
|
|
|
|
|
shared pack path: ${LOCAL_SHARED_PACK_DIR}
|
|
|
|
|
|
|
|
|
|
next:
|
|
|
|
|
1. 在另一终端运行: ${LOCAL_TUNNEL_SCRIPT}
|
|
|
|
|
2. 当前终端执行: set -a; source ${LOCAL_OPERATOR_ENV_FILE}; set +a
|
2026-05-27 09:39:05 +08:00
|
|
|
3. 再运行: bash ${ROOT_DIR}/scripts/acceptance/import_remote43_provider.sh kimi-a7m kimi-k2.6 A7M_KIMI_API_KEY /path/to/keyfile
|
2026-05-26 07:50:43 +08:00
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main "$@"
|