Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
287 lines
9.6 KiB
Bash
Executable File
287 lines
9.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Deploy Off-Chain Services (State Anchoring & Transaction Mirroring) to Proxmox Container
|
|
|
|
set -euo pipefail
|
|
|
|
# Load IP configuration
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[✓]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
log_detail() { echo -e "${CYAN}[DETAIL]${NC} $1"; }
|
|
|
|
# Configuration
|
|
VMID="${VMID:-5000}"
|
|
PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}"
|
|
PROXMOX_USER="${PROXMOX_USER:-root}"
|
|
SERVICES_DIR="${PROJECT_ROOT}/smom-dbis-138/services"
|
|
DEPLOY_USER="${DEPLOY_USER:-deploy}"
|
|
DEPLOY_HOME="/home/${DEPLOY_USER}"
|
|
DEPLOY_DIR="${DEPLOY_HOME}/services"
|
|
|
|
# Load .env if exists
|
|
if [ -f "${PROJECT_ROOT}/.env" ]; then
|
|
source "${PROJECT_ROOT}/.env"
|
|
log_info "Loaded environment variables from .env"
|
|
fi
|
|
|
|
# Check prerequisites
|
|
check_prerequisites() {
|
|
log_info "Checking prerequisites..."
|
|
|
|
if ! command -v ssh &> /dev/null; then
|
|
log_error "ssh command not found"
|
|
exit 1
|
|
fi
|
|
|
|
if ! ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "${PROXMOX_USER}@${PROXMOX_HOST}" "pct list | grep -q '^\s*${VMID}\s'" 2>/dev/null; then
|
|
log_error "Container ${VMID} does not exist on ${PROXMOX_HOST}"
|
|
log_info "Available options:"
|
|
log_info " 1. Create container first using: pct create ${VMID} ..."
|
|
log_info " 2. Use existing container: Set VMID=<existing_vmid>"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Prerequisites check passed"
|
|
}
|
|
|
|
# Test SSH connection to container
|
|
test_container_connection() {
|
|
log_info "Testing connection to container ${VMID}..."
|
|
|
|
local container_ip
|
|
if [ -n "${CONTAINER_IP:-}" ]; then
|
|
container_ip="${CONTAINER_IP}"
|
|
else
|
|
log_detail "Getting container IP from Proxmox..."
|
|
container_ip=$(ssh "${PROXMOX_USER}@${PROXMOX_HOST}" "pct exec ${VMID} -- hostname -I | awk '{print \$1}'" 2>/dev/null || echo "")
|
|
fi
|
|
|
|
if [ -z "${container_ip}" ]; then
|
|
log_error "Could not determine container IP. Set CONTAINER_IP environment variable."
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Container IP: ${container_ip}"
|
|
|
|
# Test connection
|
|
if ! ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "root@${container_ip}" "echo 'Connected'" 2>/dev/null; then
|
|
log_warn "Direct SSH to container IP failed. Using pct exec instead."
|
|
USE_PCT_EXEC=true
|
|
else
|
|
USE_PCT_EXEC=false
|
|
CONTAINER_IP="${container_ip}"
|
|
fi
|
|
|
|
log_success "Connection method: $([ "$USE_PCT_EXEC" = "true" ] && echo "pct exec" || echo "SSH direct")"
|
|
}
|
|
|
|
# Execute command in container
|
|
exec_container() {
|
|
local cmd="$1"
|
|
if [ "$USE_PCT_EXEC" = "true" ]; then
|
|
ssh "${PROXMOX_USER}@${PROXMOX_HOST}" "pct exec ${VMID} -- bash -c '${cmd}'"
|
|
else
|
|
ssh "root@${CONTAINER_IP}" "${cmd}"
|
|
fi
|
|
}
|
|
|
|
# Push file to container
|
|
push_file() {
|
|
local local_file="$1"
|
|
local remote_file="$2"
|
|
if [ "$USE_PCT_EXEC" = "true" ]; then
|
|
ssh "${PROXMOX_USER}@${PROXMOX_HOST}" "pct push ${VMID} '${local_file}' '${remote_file}'"
|
|
else
|
|
scp "${local_file}" "root@${CONTAINER_IP}:${remote_file}"
|
|
fi
|
|
}
|
|
|
|
# Install Node.js in container
|
|
install_nodejs() {
|
|
log_info "Installing Node.js..."
|
|
|
|
exec_container "command -v node >/dev/null 2>&1 && node --version || echo 'NOT_INSTALLED'" | grep -q "NOT_INSTALLED" || {
|
|
log_success "Node.js already installed: $(exec_container 'node --version')"
|
|
return 0
|
|
}
|
|
|
|
log_detail "Installing Node.js 20.x..."
|
|
exec_container "export DEBIAN_FRONTEND=noninteractive && \
|
|
apt-get update -qq && \
|
|
apt-get install -y -qq curl ca-certificates gnupg && \
|
|
mkdir -p /etc/apt/keyrings && \
|
|
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
|
|
echo 'deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main' > /etc/apt/sources.list.d/nodesource.list && \
|
|
apt-get update -qq && \
|
|
apt-get install -y -qq nodejs"
|
|
|
|
log_success "Node.js installed: $(exec_container 'node --version')"
|
|
}
|
|
|
|
# Install PM2 in container
|
|
install_pm2() {
|
|
log_info "Installing PM2..."
|
|
|
|
exec_container "command -v pm2 >/dev/null 2>&1 && pm2 --version || echo 'NOT_INSTALLED'" | grep -q "NOT_INSTALLED" || {
|
|
log_success "PM2 already installed: $(exec_container 'pm2 --version')"
|
|
return 0
|
|
}
|
|
|
|
exec_container "npm install -g pm2"
|
|
log_success "PM2 installed: $(exec_container 'pm2 --version')"
|
|
}
|
|
|
|
# Create deployment user
|
|
create_deploy_user() {
|
|
log_info "Creating deployment user..."
|
|
|
|
exec_container "id ${DEPLOY_USER} >/dev/null 2>&1 || useradd -m -s /bin/bash ${DEPLOY_USER}"
|
|
exec_container "mkdir -p ${DEPLOY_DIR} && chown -R ${DEPLOY_USER}:${DEPLOY_USER} ${DEPLOY_DIR}"
|
|
|
|
log_success "Deployment user created: ${DEPLOY_USER}"
|
|
}
|
|
|
|
# Deploy service to container
|
|
deploy_service() {
|
|
local service_name="$1"
|
|
local service_path="${SERVICES_DIR}/${service_name}"
|
|
|
|
log_info "Deploying ${service_name}..."
|
|
|
|
if [ ! -d "${service_path}" ]; then
|
|
log_error "Service directory not found: ${service_path}"
|
|
return 1
|
|
fi
|
|
|
|
# Create service directory in container
|
|
exec_container "mkdir -p ${DEPLOY_DIR}/${service_name}"
|
|
|
|
# Copy service files
|
|
log_detail "Copying service files..."
|
|
if [ "$USE_PCT_EXEC" = "true" ]; then
|
|
# Using pct push requires tar archive for directories
|
|
(cd "${service_path}" && tar czf - .) | ssh "${PROXMOX_USER}@${PROXMOX_HOST}" "pct exec ${VMID} -- tar xzf - -C ${DEPLOY_DIR}/${service_name}"
|
|
else
|
|
scp -r "${service_path}/"* "root@${CONTAINER_IP}:${DEPLOY_DIR}/${service_name}/"
|
|
fi
|
|
|
|
# Copy .env if exists
|
|
if [ -f "${PROJECT_ROOT}/.env" ]; then
|
|
push_file "${PROJECT_ROOT}/.env" "${DEPLOY_DIR}/${service_name}/.env"
|
|
elif [ -f "${service_path}/.env" ]; then
|
|
push_file "${service_path}/.env" "${DEPLOY_DIR}/${service_name}/.env"
|
|
else
|
|
log_warn "No .env file found. Service may need manual configuration."
|
|
fi
|
|
|
|
# Install dependencies and build
|
|
log_detail "Installing dependencies..."
|
|
exec_container "cd ${DEPLOY_DIR}/${service_name} && \
|
|
export NODE_ENV=production && \
|
|
npm ci --omit=dev && \
|
|
npm run build"
|
|
|
|
# Fix permissions
|
|
exec_container "chown -R ${DEPLOY_USER}:${DEPLOY_USER} ${DEPLOY_DIR}/${service_name}"
|
|
|
|
log_success "${service_name} deployed successfully"
|
|
}
|
|
|
|
# Deploy services with PM2
|
|
deploy_pm2() {
|
|
log_info "Deploying services with PM2..."
|
|
|
|
# Deploy state-anchoring-service
|
|
log_detail "Deploying state-anchoring-service..."
|
|
exec_container "cd ${DEPLOY_DIR}/state-anchoring-service && \
|
|
su - ${DEPLOY_USER} -c 'cd ${DEPLOY_DIR}/state-anchoring-service && \
|
|
pm2 delete state-anchoring-service 2>/dev/null || true && \
|
|
pm2 start dist/index.js --name state-anchoring-service && \
|
|
pm2 save'"
|
|
|
|
# Deploy transaction-mirroring-service
|
|
log_detail "Deploying transaction-mirroring-service..."
|
|
exec_container "cd ${DEPLOY_DIR}/transaction-mirroring-service && \
|
|
su - ${DEPLOY_USER} -c 'cd ${DEPLOY_DIR}/transaction-mirroring-service && \
|
|
pm2 delete transaction-mirroring-service 2>/dev/null || true && \
|
|
pm2 start dist/index.js --name transaction-mirroring-service && \
|
|
pm2 save'"
|
|
|
|
# Setup PM2 startup
|
|
exec_container "su - ${DEPLOY_USER} -c 'pm2 startup systemd -u ${DEPLOY_USER} --hp ${DEPLOY_HOME}'" || {
|
|
log_warn "PM2 startup command may need manual execution. See logs above."
|
|
}
|
|
|
|
log_success "Services deployed with PM2"
|
|
}
|
|
|
|
# Verify deployment
|
|
verify_deployment() {
|
|
log_info "Verifying deployment..."
|
|
|
|
log_detail "Checking PM2 status..."
|
|
exec_container "su - ${DEPLOY_USER} -c 'pm2 status'" || {
|
|
log_error "PM2 status check failed"
|
|
return 1
|
|
}
|
|
|
|
log_detail "Checking service logs (last 10 lines)..."
|
|
exec_container "su - ${DEPLOY_USER} -c 'pm2 logs state-anchoring-service --lines 10 --nostream'" || true
|
|
exec_container "su - ${DEPLOY_USER} -c 'pm2 logs transaction-mirroring-service --lines 10 --nostream'" || true
|
|
|
|
log_success "Deployment verification complete"
|
|
}
|
|
|
|
# Main deployment function
|
|
main() {
|
|
log_info "=== Deploying Off-Chain Services to Proxmox ==="
|
|
log_info "VMID: ${VMID}"
|
|
log_info "Proxmox Host: ${PROXMOX_HOST}"
|
|
log_info "Services Directory: ${SERVICES_DIR}"
|
|
log_info ""
|
|
|
|
check_prerequisites
|
|
test_container_connection
|
|
install_nodejs
|
|
install_pm2
|
|
create_deploy_user
|
|
|
|
# Deploy services
|
|
deploy_service "state-anchoring-service"
|
|
deploy_service "transaction-mirroring-service"
|
|
|
|
# Deploy with PM2
|
|
deploy_pm2
|
|
|
|
# Verify
|
|
verify_deployment
|
|
|
|
log_success ""
|
|
log_success "=== Deployment Complete ==="
|
|
log_info ""
|
|
log_info "Services are running on container ${VMID}"
|
|
log_info "To check status: ssh ${PROXMOX_USER}@${PROXMOX_HOST} 'pct exec ${VMID} -- su - ${DEPLOY_USER} -c \"pm2 status\"'"
|
|
log_info "To view logs: ssh ${PROXMOX_USER}@${PROXMOX_HOST} 'pct exec ${VMID} -- su - ${DEPLOY_USER} -c \"pm2 logs\"'"
|
|
log_info ""
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|