diff --git a/products/fly-deploy.sh b/products/fly-deploy.sh new file mode 100755 index 0000000..0cc0011 --- /dev/null +++ b/products/fly-deploy.sh @@ -0,0 +1,153 @@ +#!/bin/bash + +# dd0c Fly.io Deployment Script +# Deploys all 5 Node services + shared Postgres + Redis +# Budget target: ~$5/mo total (shared-cpu-1x, 256MB, auto-stop) +# +# Prerequisites: +# 1. flyctl installed: curl -L https://fly.io/install.sh | sh +# 2. flyctl auth login +# 3. dd0c.dev DNS pointed to Fly.io (CNAME or A records) + +set -euo pipefail + +ORG="${FLY_ORG:-personal}" +REGION="${FLY_REGION:-iad}" +JWT_SECRET="${JWT_SECRET:-$(openssl rand -hex 32)}" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +step() { echo -e "\n${YELLOW}▸ $1${NC}"; } +ok() { echo -e " ${GREEN}✓${NC} $1"; } +fail() { echo -e " ${RED}✗${NC} $1"; exit 1; } + +# ─── Shared Infrastructure ─── + +step "Creating shared Postgres cluster (dd0c-db)" +if flyctl postgres list --org "$ORG" 2>/dev/null | grep -q dd0c-db; then + ok "dd0c-db already exists" +else + flyctl postgres create \ + --name dd0c-db \ + --org "$ORG" \ + --region "$REGION" \ + --vm-size shared-cpu-1x \ + --volume-size 1 \ + --initial-cluster-size 1 \ + --password "$(openssl rand -hex 16)" + ok "dd0c-db created" +fi + +step "Creating shared Redis (dd0c-redis via Upstash)" +if flyctl redis list 2>/dev/null | grep -q dd0c-redis; then + ok "dd0c-redis already exists" +else + flyctl redis create \ + --name dd0c-redis \ + --org "$ORG" \ + --region "$REGION" \ + --no-eviction + ok "dd0c-redis created" +fi + +# Get connection strings +PG_CONN=$(flyctl postgres config show dd0c-db --app dd0c-db 2>/dev/null | grep "internal" | awk '{print $NF}' || echo "") +REDIS_URL=$(flyctl redis status dd0c-redis 2>/dev/null | grep "Private URL" | awk '{print $NF}' || echo "") + +# ─── Create per-product databases ─── + +step "Creating per-product databases" +for db in dd0c_drift dd0c_alert dd0c_portal dd0c_cost dd0c_run; do + flyctl postgres connect -a dd0c-db -c "CREATE DATABASE $db;" 2>/dev/null || true + ok "$db" +done + +# ─── Deploy Services ─── + +declare -A APPS=( + ["dd0c-drift"]="02-iac-drift-detection/saas" + ["dd0c-alert"]="03-alert-intelligence" + ["dd0c-portal"]="04-lightweight-idp" + ["dd0c-cost"]="05-aws-cost-anomaly" + ["dd0c-run"]="06-runbook-automation" +) + +declare -A DBS=( + ["dd0c-drift"]="dd0c_drift" + ["dd0c-alert"]="dd0c_alert" + ["dd0c-portal"]="dd0c_portal" + ["dd0c-cost"]="dd0c_cost" + ["dd0c-run"]="dd0c_run" +) + +for app in dd0c-alert dd0c-portal dd0c-cost dd0c-run dd0c-drift; do + dir="${APPS[$app]}" + db="${DBS[$app]}" + + step "Deploying $app (from $dir)" + + # Create app if needed + if ! flyctl apps list --org "$ORG" 2>/dev/null | grep -q "$app"; then + flyctl apps create "$app" --org "$ORG" + ok "App created" + else + ok "App exists" + fi + + # Attach Postgres (creates DATABASE_URL secret automatically) + flyctl postgres attach dd0c-db --app "$app" --database-name "$db" 2>/dev/null || true + ok "Postgres attached ($db)" + + # Set secrets + flyctl secrets set \ + --app "$app" \ + JWT_SECRET="$JWT_SECRET" \ + REDIS_URL="${REDIS_URL:-redis://dd0c-redis.internal:6379}" \ + 2>/dev/null + ok "Secrets set" + + # Deploy + cd "$SCRIPT_DIR/$dir" + flyctl deploy --app "$app" --region "$REGION" --ha=false + ok "$app deployed" + cd "$SCRIPT_DIR" +done + +# ─── Custom Domains ─── + +step "Setting up custom domains" +declare -A DOMAINS=( + ["dd0c-drift"]="drift.dd0c.dev" + ["dd0c-alert"]="alert.dd0c.dev" + ["dd0c-portal"]="portal.dd0c.dev" + ["dd0c-cost"]="cost.dd0c.dev" + ["dd0c-run"]="run.dd0c.dev" +) + +for app in "${!DOMAINS[@]}"; do + domain="${DOMAINS[$app]}" + flyctl certs add "$domain" --app "$app" 2>/dev/null || true + ok "$app → $domain" +done + +# ─── Summary ─── + +echo "" +echo -e "${GREEN}═══════════════════════════════════${NC}" +echo -e "${GREEN}dd0c deployed to Fly.io!${NC}" +echo "" +echo " JWT_SECRET: $JWT_SECRET" +echo " Region: $REGION" +echo "" +echo " Services:" +for app in "${!DOMAINS[@]}"; do + echo " https://${DOMAINS[$app]}" +done +echo "" +echo -e "${YELLOW}DNS: Point these CNAMEs to $app.fly.dev${NC}" +echo -e "${YELLOW}Save the JWT_SECRET — it's shared across all services.${NC}"