#!/bin/bash set -euo pipefail exec > >(tee /var/log/cloud-init-app.log) 2>&1 echo "=== OCI CIS Agent cloud-init started at $(date) ===" # ----------------------------------------------------------------------------- # 1. Install Docker CE + docker-compose-plugin # ----------------------------------------------------------------------------- echo ">>> Installing Docker CE..." dnf install -y dnf-utils dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin --allowerasing systemctl enable docker systemctl start docker echo ">>> Docker version: $(docker --version)" echo ">>> Docker Compose version: $(docker compose version)" # ----------------------------------------------------------------------------- # 2. Wait for block device # ----------------------------------------------------------------------------- DATA_DEVICE="${data_device}" echo ">>> Waiting for block device $DATA_DEVICE..." ATTEMPTS=0 MAX_ATTEMPTS=60 while [ ! -e "$DATA_DEVICE" ] && [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do echo " Waiting for $DATA_DEVICE (attempt $((ATTEMPTS+1))/$MAX_ATTEMPTS)..." sleep 5 ATTEMPTS=$((ATTEMPTS+1)) done if [ ! -e "$DATA_DEVICE" ]; then echo "ERROR: Block device $DATA_DEVICE not found after $MAX_ATTEMPTS attempts" exit 1 fi echo ">>> Block device $DATA_DEVICE is available" # ----------------------------------------------------------------------------- # 3. Format and mount /data # ----------------------------------------------------------------------------- if ! blkid "$DATA_DEVICE" | grep -q ext4; then echo ">>> Formatting $DATA_DEVICE as ext4..." mkfs.ext4 -F "$DATA_DEVICE" fi mkdir -p /data mount "$DATA_DEVICE" /data # Add to fstab if not already present if ! grep -q "$DATA_DEVICE" /etc/fstab; then echo "$DATA_DEVICE /data ext4 defaults,_netdev,nofail 0 2" >> /etc/fstab fi echo ">>> /data mounted successfully" df -h /data # Create application data directories mkdir -p /data/db /data/configs /data/reports /data/terraform /data/wallets # ----------------------------------------------------------------------------- # 4. Docker login to OCIR # ----------------------------------------------------------------------------- OCIR_ENDPOINT="${ocir_region}.ocir.io" echo ">>> Logging into OCIR at $OCIR_ENDPOINT..." echo '${ocir_auth_token}' | docker login "$OCIR_ENDPOINT" \ -u "${ocir_namespace}/${ocir_username}" \ --password-stdin # ----------------------------------------------------------------------------- # 5. Pull images # ----------------------------------------------------------------------------- BACKEND_IMAGE="$OCIR_ENDPOINT/${ocir_namespace}/${ocir_repo_prefix}/backend:latest" FRONTEND_IMAGE="$OCIR_ENDPOINT/${ocir_namespace}/${ocir_repo_prefix}/frontend:latest" echo ">>> Pulling backend image: $BACKEND_IMAGE" docker pull "$BACKEND_IMAGE" echo ">>> Pulling frontend image: $FRONTEND_IMAGE" docker pull "$FRONTEND_IMAGE" # ----------------------------------------------------------------------------- # 6. Write docker-compose.yml # ----------------------------------------------------------------------------- APP_DIR="/opt/oci-cis-agent" mkdir -p "$APP_DIR" cat > "$APP_DIR/docker-compose.yml" <<'COMPOSE_EOF' services: backend: image: ${ocir_region}.ocir.io/${ocir_namespace}/${ocir_repo_prefix}/backend:latest container_name: cisagent-backend restart: unless-stopped environment: - APP_SECRET=${app_secret} - JWT_EXPIRY_HOURS=${jwt_expiry_hours} - CORS_ORIGINS=${cors_origins} - TZ=${app_timezone} volumes: - /data:/data mem_limit: 4g healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"] interval: 30s timeout: 10s retries: 3 start_period: 30s networks: - agent-net frontend: image: ${ocir_region}.ocir.io/${ocir_namespace}/${ocir_repo_prefix}/frontend:latest container_name: cisagent-frontend restart: unless-stopped ports: - "8080:80" mem_limit: 512m depends_on: backend: condition: service_healthy networks: - agent-net networks: agent-net: driver: bridge COMPOSE_EOF echo ">>> docker-compose.yml written to $APP_DIR" # ----------------------------------------------------------------------------- # 7. Start application # ----------------------------------------------------------------------------- echo ">>> Starting application with Docker Compose..." cd "$APP_DIR" docker compose up -d # ----------------------------------------------------------------------------- # 8. Health check wait loop # ----------------------------------------------------------------------------- echo ">>> Waiting for application to become healthy..." ATTEMPTS=0 MAX_ATTEMPTS=60 while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do if curl -sf http://localhost:8080/api/health > /dev/null 2>&1; then echo ">>> Application is healthy!" break fi echo " Health check attempt $((ATTEMPTS+1))/$MAX_ATTEMPTS..." sleep 10 ATTEMPTS=$((ATTEMPTS+1)) done if [ $ATTEMPTS -eq $MAX_ATTEMPTS ]; then echo "WARNING: Application did not become healthy within expected time" echo ">>> Docker container status:" docker compose ps echo ">>> Backend logs:" docker compose logs backend --tail 50 fi echo "=== OCI CIS Agent cloud-init finished at $(date) ==="