#!/usr/bin/env bash # deployment-node.sh - To be run on the execution node (SOLARIA, PIHA, VPS) # This script pulls the latest changes and ensures services are running. set -e # Configuration REPO_PATH="${HOME}/homelab-codex-ws" RUNTIME_PATH="/opt/homelab" HOSTNAME=$(hostname | tr '[:lower:]' '[:upper:]') CURRENT_OS_HOST=$(hostname) echo "--- Starting Deployment on ${HOSTNAME} ---" # 1. Update Repository if [ ! -d "$REPO_PATH" ]; then echo "Error: Repository not found at $REPO_PATH" exit 1 fi cd "$REPO_PATH" echo "Pulling latest changes..." git pull # Resolve host directory: search hosts/*/host.yaml for os_hostname == $(hostname) HOST_LOGICAL=$(python3 -c " import yaml, os, sys current = '${CURRENT_OS_HOST}' hosts_dir = os.path.join('${REPO_PATH}', 'hosts') for entry in sorted(os.listdir(hosts_dir)): host_yaml = os.path.join(hosts_dir, entry, 'host.yaml') if not os.path.isfile(host_yaml): continue try: with open(host_yaml) as f: data = yaml.safe_load(f) if data and data.get('os_hostname') == current: print(entry) sys.exit(0) except Exception: pass ") if [ -n "$HOST_LOGICAL" ]; then HOST_DIR="${REPO_PATH}/hosts/${HOST_LOGICAL}" else HOST_LOGICAL_FB="$(echo "$CURRENT_OS_HOST" | tr '[:upper:]' '[:lower:]')" echo "WARN: no os_hostname match for ${CURRENT_OS_HOST}, falling back to lowercase hostname dir" >&2 HOST_DIR="${REPO_PATH}/hosts/${HOST_LOGICAL_FB}" fi if [ ! -d "$HOST_DIR" ]; then echo "Error: No host directory found for ${CURRENT_OS_HOST} (tried ${HOST_DIR})" >&2 exit 1 fi # 2. Identify Services SERVICES=() if [ -f "${HOST_DIR}/services.txt" ]; then mapfile -t SERVICES < <(grep -v '^\s*#' "${HOST_DIR}/services.txt" | grep -v '^\s*$') elif [ -f "${HOST_DIR}/services.yaml" ]; then SERVICES=($(python3 -c " import yaml, sys try: with open('${HOST_DIR}/services.yaml', 'r') as f: data = yaml.safe_load(f) if data and 'services' in data: if isinstance(data['services'], dict): print(' '.join(data['services'].keys())) elif isinstance(data['services'], list): print(' '.join(data['services'])) except Exception as e: print(f'Error parsing YAML: {e}', file=sys.stderr) sys.exit(1) ")) fi if [ ${#SERVICES[@]} -eq 0 ]; then echo "No services found for ${HOSTNAME}. Skipping service deployment." exit 0 fi # 3. Deploy Services for service in "${SERVICES[@]}"; do echo "Deploying service: ${service}..." COMPOSE_FILE="${REPO_PATH}/services/${service}/docker-compose.yml" if [ ! -f "$COMPOSE_FILE" ]; then echo "Warning: Compose file not found for ${service} at ${COMPOSE_FILE}" continue fi TARGET_DIR="${RUNTIME_PATH}/services/${service}" mkdir -p "$TARGET_DIR" OVERRIDE_FILE="${HOST_DIR}/runtime/${service}/docker-compose.override.yml" COMPOSE_CMD="docker compose -f ${COMPOSE_FILE}" if [ -f "$OVERRIDE_FILE" ]; then echo "Using override file for ${service}" COMPOSE_CMD="${COMPOSE_CMD} -f ${OVERRIDE_FILE}" fi $COMPOSE_CMD up -d --remove-orphans done echo "--- Deployment Complete ---"