#!/bin/bash # Automated deployment script for GLAM SPARQL server # Uses Hetzner API to discover server IP and deploys via SSH # # Usage: ./deploy.sh [options] # Options: # --infra Deploy infrastructure changes (Terraform) # --data Deploy ontology/schema data # --frontend Build and deploy frontend # --reload Reload data into Oxigraph # --all Deploy everything # --status Check server status only set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Load environment variables if [ -f "$PROJECT_ROOT/.env" ]; then export $(grep -v '^#' "$PROJECT_ROOT/.env" | xargs) fi # Configuration HCLOUD_TOKEN="${HETZNER_HC_API_TOKEN:-}" SERVER_NAME="glam-sparql" SERVER_USER="root" REMOTE_DATA_DIR="/mnt/data" # Check for required token if [ -z "$HCLOUD_TOKEN" ]; then echo -e "${RED}Error: HETZNER_HC_API_TOKEN not found in .env${NC}" echo "Please add your Hetzner API token to .env:" echo " HETZNER_HC_API_TOKEN=your_token_here" exit 1 fi # Parse arguments DEPLOY_INFRA=false DEPLOY_DATA=false DEPLOY_FRONTEND=false RELOAD_OXIGRAPH=false STATUS_ONLY=false if [ $# -eq 0 ]; then echo "Usage: $0 [--infra] [--data] [--frontend] [--reload] [--all] [--status]" exit 1 fi for arg in "$@"; do case $arg in --infra) DEPLOY_INFRA=true ;; --data) DEPLOY_DATA=true ;; --frontend) DEPLOY_FRONTEND=true ;; --reload) RELOAD_OXIGRAPH=true ;; --all) DEPLOY_INFRA=true DEPLOY_DATA=true DEPLOY_FRONTEND=true RELOAD_OXIGRAPH=true ;; --status) STATUS_ONLY=true ;; *) echo "Unknown option: $arg" exit 1 ;; esac done # Function to get server IP from Hetzner API get_server_ip() { local response=$(curl -s -H "Authorization: Bearer $HCLOUD_TOKEN" \ "https://api.hetzner.cloud/v1/servers?name=$SERVER_NAME") local ip=$(echo "$response" | jq -r '.servers[0].public_net.ipv4.ip // empty') if [ -z "$ip" ] || [ "$ip" = "null" ]; then echo "" else echo "$ip" fi } # Function to check server status check_server_status() { local response=$(curl -s -H "Authorization: Bearer $HCLOUD_TOKEN" \ "https://api.hetzner.cloud/v1/servers?name=$SERVER_NAME") echo "$response" | jq -r '.servers[0] | "Server: \(.name)\nStatus: \(.status)\nIP: \(.public_net.ipv4.ip)\nType: \(.server_type.name)\nLocation: \(.datacenter.name)"' } # Function to wait for SSH wait_for_ssh() { local ip=$1 local max_attempts=30 echo -e "${BLUE}Waiting for SSH to be available on $ip...${NC}" for i in $(seq 1 $max_attempts); do if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o BatchMode=yes \ "$SERVER_USER@$ip" "echo 'connected'" 2>/dev/null; then echo -e "${GREEN}SSH connection established${NC}" return 0 fi echo " Attempt $i/$max_attempts..." sleep 10 done echo -e "${RED}Failed to establish SSH connection${NC}" return 1 } echo -e "${BLUE}════════════════════════════════════════════════════════════════${NC}" echo -e "${BLUE} GLAM Infrastructure Deployment${NC}" echo -e "${BLUE}════════════════════════════════════════════════════════════════${NC}" echo "" # Get server IP echo -e "${YELLOW}Discovering server...${NC}" SERVER_IP=$(get_server_ip) if [ -z "$SERVER_IP" ]; then if [ "$DEPLOY_INFRA" = true ]; then echo -e "${YELLOW}Server not found. Will be created by Terraform.${NC}" else echo -e "${RED}Error: Server '$SERVER_NAME' not found in Hetzner Cloud${NC}" echo "Run with --infra to create the server first." exit 1 fi else echo -e "${GREEN}Found server: $SERVER_IP${NC}" fi # Status only mode if [ "$STATUS_ONLY" = true ]; then echo "" echo -e "${BLUE}Server Status:${NC}" check_server_status if [ -n "$SERVER_IP" ]; then echo "" echo -e "${BLUE}Service Status:${NC}" ssh -o StrictHostKeyChecking=no "$SERVER_USER@$SERVER_IP" \ "systemctl is-active oxigraph && echo 'Oxigraph: Running' || echo 'Oxigraph: Stopped'; \ systemctl is-active caddy && echo 'Caddy: Running' || echo 'Caddy: Stopped'" echo "" echo -e "${BLUE}SPARQL Triple Count:${NC}" ssh -o StrictHostKeyChecking=no "$SERVER_USER@$SERVER_IP" \ "curl -s -X POST -H 'Content-Type: application/sparql-query' \ -H 'Accept: application/sparql-results+json' \ --data 'SELECT (COUNT(*) AS ?count) WHERE { ?s ?p ?o }' \ http://localhost:7878/query | jq -r '.results.bindings[0].count.value // \"0\"' | xargs -I {} echo '{} triples'" fi exit 0 fi # Deploy infrastructure if [ "$DEPLOY_INFRA" = true ]; then echo "" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${BLUE} Deploying Infrastructure${NC}" echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" cd "$PROJECT_ROOT/infrastructure/terraform" # Initialize Terraform echo -e "${YELLOW}Initializing Terraform...${NC}" terraform init -upgrade # Create terraform.tfvars if it doesn't exist if [ ! -f terraform.tfvars ]; then echo -e "${YELLOW}Creating terraform.tfvars from environment...${NC}" cat > terraform.tfvars <