hearth/scripts/deploy-phase2-core-services.sh
Eric Garcia e78000831e Initial commit: Port infrastructure from coherence-mcp
Hearth is the infrastructure home for the letemcook ecosystem.

Ported from coherence-mcp/infra:
- Terraform modules (VPC, EKS, IAM, NLB, S3, storage)
- Kubernetes manifests (Forgejo, ingress, cert-manager, karpenter)
- Deployment scripts (phased rollout)

Status: Not deployed. EKS cluster needs to be provisioned.

Next steps:
1. Bootstrap terraform backend
2. Deploy phase 1 (foundation)
3. Deploy phase 2 (core services including Forgejo)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:06:13 -05:00

259 lines
7.1 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Phase 2: Core Services Deployment (RFC 0040)
#
# This script deploys core services including:
# - HashiCorp Vault for secrets management
# - Keycloak for identity and SSO
# - Forgejo for Git hosting
#
# Usage:
# ./deploy-phase2-core-services.sh [--dry-run] [--skip-vault] [--skip-keycloak] [--skip-forgejo]
#
# Prerequisites:
# - Phase 1 (Foundation) must be deployed and validated
# - kubectl configured for EKS cluster
# - Helm 3.x installed
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INFRA_DIR="$(dirname "$SCRIPT_DIR")"
K8S_DIR="$INFRA_DIR/kubernetes"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Flags
DRY_RUN=false
SKIP_VAULT=false
SKIP_KEYCLOAK=false
SKIP_FORGEJO=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--skip-vault)
SKIP_VAULT=true
shift
;;
--skip-keycloak)
SKIP_KEYCLOAK=true
shift
;;
--skip-forgejo)
SKIP_FORGEJO=true
shift
;;
-h|--help)
echo "Usage: $0 [--dry-run] [--skip-vault] [--skip-keycloak] [--skip-forgejo]"
exit 0
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
exit 1
;;
esac
done
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
run_cmd() {
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY-RUN]${NC} Would run: $*"
else
"$@"
fi
}
check_prerequisites() {
log_info "Checking prerequisites..."
# Check kubectl connectivity
if ! kubectl cluster-info &> /dev/null; then
log_error "kubectl not connected to cluster. Run Phase 1 first."
exit 1
fi
# Check cert-manager is running
if ! kubectl -n cert-manager get pods -l app.kubernetes.io/instance=cert-manager -o jsonpath='{.items[0].status.phase}' 2>/dev/null | grep -q Running; then
log_error "cert-manager not running. Ensure Phase 1 is complete."
exit 1
fi
# Check CockroachDB is running
if ! kubectl -n cockroachdb get pods -l app=cockroachdb -o jsonpath='{.items[0].status.phase}' 2>/dev/null | grep -q Running; then
log_error "CockroachDB not running. Ensure Phase 1 is complete."
exit 1
fi
log_success "All prerequisites met"
}
deploy_vault() {
if [ "$SKIP_VAULT" = true ]; then
log_warn "Skipping Vault deployment"
return
fi
log_info "Deploying HashiCorp Vault..."
# Deploy Vault
run_cmd kubectl apply -k "$K8S_DIR/vault/"
# Wait for Vault pods
if [ "$DRY_RUN" = false ]; then
log_info "Waiting for Vault pods to be ready..."
kubectl -n vault wait --for=condition=ready pod -l app=vault --timeout=300s || true
fi
# Check if Vault needs initialization
if [ "$DRY_RUN" = false ]; then
local vault_status
vault_status=$(kubectl -n vault exec vault-0 -- vault status -format=json 2>/dev/null || echo '{}')
local initialized
initialized=$(echo "$vault_status" | jq -r '.initialized // false')
if [ "$initialized" = "false" ]; then
log_warn "Vault needs initialization!"
echo ""
echo "Run the following commands to initialize Vault:"
echo " kubectl -n vault exec -it vault-0 -- vault operator init"
echo ""
echo "IMPORTANT: Save the unseal keys and root token securely!"
echo ""
echo "Then unseal each Vault pod:"
echo " kubectl -n vault exec -it vault-0 -- vault operator unseal <key1>"
echo " kubectl -n vault exec -it vault-0 -- vault operator unseal <key2>"
echo " kubectl -n vault exec -it vault-0 -- vault operator unseal <key3>"
echo ""
read -p "Press Enter after Vault is initialized and unsealed..."
fi
# Verify Vault is unsealed
vault_status=$(kubectl -n vault exec vault-0 -- vault status -format=json 2>/dev/null || echo '{}')
local sealed
sealed=$(echo "$vault_status" | jq -r '.sealed // true')
if [ "$sealed" = "true" ]; then
log_error "Vault is still sealed. Please unseal before continuing."
exit 1
fi
fi
log_success "Vault deployment complete"
}
deploy_keycloak() {
if [ "$SKIP_KEYCLOAK" = true ]; then
log_warn "Skipping Keycloak deployment"
return
fi
log_info "Deploying Keycloak..."
# Deploy Keycloak
run_cmd kubectl apply -k "$K8S_DIR/keycloak/"
# Wait for Keycloak pods
if [ "$DRY_RUN" = false ]; then
log_info "Waiting for Keycloak pods to be ready..."
kubectl -n keycloak wait --for=condition=ready pod -l app=keycloak --timeout=300s
fi
# Import realm configuration if available
if [ -f "$K8S_DIR/keycloak/realm-config.yaml" ]; then
log_info "Applying realm configuration..."
run_cmd kubectl apply -f "$K8S_DIR/keycloak/realm-config.yaml"
fi
log_success "Keycloak deployment complete"
}
deploy_forgejo() {
if [ "$SKIP_FORGEJO" = true ]; then
log_warn "Skipping Forgejo deployment"
return
fi
log_info "Deploying Forgejo..."
# Deploy Forgejo
run_cmd kubectl apply -k "$K8S_DIR/forgejo/"
# Wait for Forgejo pods
if [ "$DRY_RUN" = false ]; then
log_info "Waiting for Forgejo pods to be ready..."
kubectl -n forgejo wait --for=condition=ready pod -l app=forgejo --timeout=300s
fi
log_success "Forgejo deployment complete"
}
validate_phase2() {
log_info "Running Phase 2 validation..."
local validation_script="$SCRIPT_DIR/validate-phase2.sh"
if [ -x "$validation_script" ]; then
if [ "$DRY_RUN" = true ]; then
log_info "Would run validation script: $validation_script"
else
"$validation_script"
fi
else
log_warn "Validation script not found or not executable: $validation_script"
fi
}
main() {
echo "========================================"
echo "Phase 2: Core Services"
echo "RFC 0040 Deployment"
echo "========================================"
echo ""
if [ "$DRY_RUN" = true ]; then
log_warn "Running in DRY-RUN mode - no changes will be made"
echo ""
fi
check_prerequisites
deploy_vault
deploy_keycloak
deploy_forgejo
validate_phase2
echo ""
echo "========================================"
log_success "Phase 2 deployment complete!"
echo "========================================"
echo ""
echo "Next steps:"
echo " 1. Run validate-phase2.sh to verify deployment"
echo " 2. Configure Keycloak realm and clients via Web UI"
echo " 3. Tag this deployment: git tag -a v0.2.0-phase2 -m 'Phase 2: Core Services'"
echo " 4. Proceed to Phase 3: ./deploy-phase3-dns-email.sh"
}
main "$@"