#!/bin/bash # ============================================================================= # Setup da Aula 09 - n8n via Helm (Hetzner Cloud) # ============================================================================= # # Este script instala e configura: # 1. cert-manager (opcional, para Let's Encrypt) # 2. n8n com PostgreSQL, Redis, Workers e Webhooks # # Pré-requisitos: # - Kubernetes cluster Talos na Hetzner (aula-08) com: # - Hetzner CSI Driver (StorageClass: hcloud-volumes) # - NGINX Ingress Controller com LoadBalancer # - kubectl configurado (KUBECONFIG=../aula-08/kubeconfig) # - Helm 3.x instalado # # Uso: # export KUBECONFIG=$(pwd)/../aula-08/kubeconfig # chmod +x setup.sh # ./setup.sh # # ============================================================================= set -e # Para na primeira falha # Cores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Funções de log log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERRO]${NC} $1"; } # Diretório do script SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Variáveis de configuração (serão preenchidas pelo usuário ou .env) N8N_HOST="" DOMAIN="" # Extraído automaticamente do N8N_HOST USE_CLOUDFLARE="" USE_LETSENCRYPT="" LETSENCRYPT_EMAIL="" # ============================================================================= # FUNÇÕES DE CONFIGURAÇÃO # ============================================================================= save_config() { cat > "$SCRIPT_DIR/.env" </dev/null || true helm repo update jetstack if helm status cert-manager -n cert-manager &> /dev/null; then log_success "cert-manager já está instalado" else helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.16.2 \ --set crds.enabled=true \ --wait \ --timeout 5m log_success "cert-manager instalado" fi } create_cluster_issuer() { log_info "Criando ClusterIssuer para Let's Encrypt..." cat </dev/null || echo "") # Extrair nome do host (parte antes do primeiro ponto) HOST_NAME=$(echo "$N8N_HOST" | cut -d. -f1) echo "" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo -e "${CYAN} Configure o DNS${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" if [[ "$USE_CLOUDFLARE" == "true" ]]; then echo "" echo "No painel do CloudFlare (https://dash.cloudflare.com):" echo "" echo -e " ${YELLOW}Tipo:${NC} A" echo -e " ${YELLOW}Nome:${NC} ${HOST_NAME}" echo -e " ${YELLOW}Conteúdo:${NC} ${GREEN}${LB_IP}${NC}" echo -e " ${YELLOW}Proxy:${NC} ✓ (ícone laranja)" echo "" echo -e " ${YELLOW}Tipo:${NC} A" echo -e " ${YELLOW}Nome:${NC} * (wildcard, para multi-tenant)" echo -e " ${YELLOW}Conteúdo:${NC} ${GREEN}${LB_IP}${NC}" echo -e " ${YELLOW}Proxy:${NC} ✓ (ícone laranja)" echo "" echo -e "${GREEN}O CloudFlare cuida do TLS automaticamente!${NC}" else echo "" echo "No seu provedor DNS:" echo "" echo -e " ${YELLOW}Tipo:${NC} A" echo -e " ${YELLOW}Nome:${NC} ${HOST_NAME}" echo -e " ${YELLOW}Valor:${NC} ${GREEN}${LB_IP}${NC}" echo "" echo -e " ${YELLOW}Tipo:${NC} A" echo -e " ${YELLOW}Nome:${NC} * (wildcard, para multi-tenant)" echo -e " ${YELLOW}Valor:${NC} ${GREEN}${LB_IP}${NC}" if [[ "$USE_LETSENCRYPT" == "true" ]]; then echo "" echo -e "${GREEN}Let's Encrypt irá emitir certificados automaticamente!${NC}" echo -e "Aguarde ~2 minutos após configurar o DNS." fi fi # Determinar protocolo PROTOCOL="https" if [[ "$USE_CLOUDFLARE" == "false" && "$USE_LETSENCRYPT" == "false" ]]; then PROTOCOL="http" fi echo "" echo -e "Acesse: ${GREEN}${PROTOCOL}://${N8N_HOST}${NC}" } # ============================================================================= # VERIFICAÇÕES INICIAIS # ============================================================================= log_info "Verificando pré-requisitos..." # Verificar kubectl if ! command -v kubectl &> /dev/null; then log_error "kubectl não encontrado. Instale o kubectl primeiro." exit 1 fi log_success "kubectl encontrado" # Verificar conexão com cluster if ! kubectl cluster-info &> /dev/null; then log_error "Não foi possível conectar ao cluster Kubernetes." exit 1 fi log_success "Conectado ao cluster Kubernetes" # Verificar helm if ! command -v helm &> /dev/null; then log_error "Helm não encontrado. Instale o Helm >= 3.14 primeiro." log_info "Instalação: https://helm.sh/docs/intro/install/" exit 1 fi log_success "Helm $(helm version --short) encontrado" # ============================================================================= # COLETAR INPUT DO USUÁRIO # ============================================================================= collect_user_input echo "" # ============================================================================= # 1. VERIFICAR PRÉ-REQUISITOS DA AULA-08 # ============================================================================= log_info "=== Verificando infraestrutura (aula-08) ===" # Verificar Hetzner CSI Driver if ! kubectl get storageclass hcloud-volumes &> /dev/null; then log_error "StorageClass hcloud-volumes não encontrado!" log_error "Execute primeiro o setup.sh da aula-08 para instalar o CSI Driver." exit 1 fi log_success "Hetzner CSI Driver instalado (hcloud-volumes)" # Verificar NGINX Ingress if ! kubectl get ingressclass nginx &> /dev/null; then log_error "NGINX Ingress não encontrado!" log_error "Execute primeiro o setup.sh da aula-08 para instalar o Ingress Controller." exit 1 fi log_success "NGINX Ingress Controller instalado" echo "" # ============================================================================= # 2. INSTALAR CERT-MANAGER (se Let's Encrypt) # ============================================================================= if [[ "$USE_LETSENCRYPT" == "true" ]]; then log_info "=== Configurando cert-manager ===" install_cert_manager create_cluster_issuer echo "" fi # ============================================================================= # 2.5. PAUSA PARA CONFIGURAÇÃO DE DNS # ============================================================================= show_dns_instructions echo "" echo -e "${YELLOW}⚠ Configure o DNS agora antes de continuar.${NC}" if [[ "$USE_LETSENCRYPT" == "true" ]]; then echo -e "${YELLOW} O Let's Encrypt precisa do DNS configurado para emitir o certificado.${NC}" fi echo "" echo -n "Pressione ENTER quando o DNS estiver configurado..." read -r echo "" # ============================================================================= # 3. CRIAR NAMESPACE E APLICAR SECRETS # ============================================================================= log_info "=== Configurando namespace n8n ===" # Criar namespace se não existir if kubectl get namespace n8n &> /dev/null; then log_success "Namespace n8n já existe" else log_info "Criando namespace n8n..." kubectl create namespace n8n log_success "Namespace n8n criado" fi echo "" # ============================================================================= # 4. INSTALAR n8n VIA HELM # ============================================================================= log_info "=== Instalando n8n ===" # Adicionar repo do community-charts log_info "Adicionando repositório Helm do community-charts..." helm repo add community-charts https://community-charts.github.io/helm-charts 2>/dev/null || true helm repo update # Construir argumentos do Helm dinamicamente HELM_ARGS="" # Configurar host do ingress HELM_ARGS="$HELM_ARGS --set ingress.hosts[0].host=${N8N_HOST}" HELM_ARGS="$HELM_ARGS --set ingress.hosts[0].paths[0].path=/" HELM_ARGS="$HELM_ARGS --set ingress.hosts[0].paths[0].pathType=Prefix" # Configurar webhook URL if [[ "$USE_CLOUDFLARE" == "true" || "$USE_LETSENCRYPT" == "true" ]]; then HELM_ARGS="$HELM_ARGS --set webhook.url=https://${N8N_HOST}" else HELM_ARGS="$HELM_ARGS --set webhook.url=http://${N8N_HOST}" fi # Configurar TLS - gerar values overlay para anotações com pontos TEMP_TLS_VALUES=$(mktemp) if [[ "$USE_LETSENCRYPT" == "true" ]]; then HELM_ARGS="$HELM_ARGS --set ingress.tls[0].hosts[0]=${N8N_HOST}" HELM_ARGS="$HELM_ARGS --set ingress.tls[0].secretName=n8n-tls" cat > "$TEMP_TLS_VALUES" < "$TEMP_TLS_VALUES" fi # Configurar N8N_SECURE_COOKIE if [[ "$USE_CLOUDFLARE" == "true" || "$USE_LETSENCRYPT" == "true" ]]; then HELM_ARGS="$HELM_ARGS --set main.extraEnvVars.N8N_SECURE_COOKIE=true" HELM_ARGS="$HELM_ARGS --set worker.extraEnvVars.N8N_SECURE_COOKIE=true" HELM_ARGS="$HELM_ARGS --set webhook.extraEnvVars.N8N_SECURE_COOKIE=true" fi # Verificar se já está instalado if helm status n8n -n n8n &> /dev/null; then log_warn "n8n já está instalado. Atualizando..." eval helm upgrade n8n community-charts/n8n \ --namespace n8n \ --values "$SCRIPT_DIR/custom-values.yaml" \ -f "$TEMP_TLS_VALUES" \ $HELM_ARGS \ --wait \ --timeout 10m log_success "n8n atualizado com sucesso!" else log_info "Instalando n8n..." eval helm install n8n community-charts/n8n \ --namespace n8n \ --values "$SCRIPT_DIR/custom-values.yaml" \ -f "$TEMP_TLS_VALUES" \ $HELM_ARGS \ --wait \ --timeout 10m log_success "n8n instalado com sucesso!" fi rm -f "$TEMP_TLS_VALUES" echo "" # ============================================================================= # 5. AGUARDAR PODS FICAREM PRONTOS # ============================================================================= log_info "=== Aguardando pods ficarem prontos ===" log_info "Aguardando PostgreSQL..." kubectl wait --for=condition=ready pod \ -l app.kubernetes.io/name=postgresql \ -n n8n \ --timeout=180s 2>/dev/null || log_warn "Timeout aguardando PostgreSQL" log_info "Aguardando Redis..." kubectl wait --for=condition=ready pod \ -l app.kubernetes.io/name=redis \ -n n8n \ --timeout=120s 2>/dev/null || log_warn "Timeout aguardando Redis" log_info "Aguardando n8n main..." kubectl wait --for=condition=ready pod \ -l app.kubernetes.io/component=main \ -n n8n \ --timeout=180s 2>/dev/null || log_warn "Timeout aguardando n8n main" log_info "Aguardando n8n workers..." kubectl wait --for=condition=ready pod \ -l app.kubernetes.io/component=worker \ -n n8n \ --timeout=120s 2>/dev/null || log_warn "Timeout aguardando workers" log_info "Aguardando n8n webhooks..." kubectl wait --for=condition=ready pod \ -l app.kubernetes.io/component=webhook \ -n n8n \ --timeout=120s 2>/dev/null || log_warn "Timeout aguardando webhooks" log_success "Todos os componentes estão rodando!" echo "" # ============================================================================= # RESUMO FINAL # ============================================================================= echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo -e "${GREEN} Setup Completo!${NC}" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" echo "Componentes instalados:" if [[ "$USE_LETSENCRYPT" == "true" ]]; then echo " - cert-manager (ClusterIssuer: letsencrypt)" fi echo " - n8n (namespace: n8n)" echo " - Main node" echo " - Workers (2-5 réplicas, autoscaling)" echo " - Webhooks (1-3 réplicas, autoscaling)" echo " - PostgreSQL" echo " - Redis" echo "" echo "Configuração:" echo " Hostname: ${N8N_HOST}" echo " CloudFlare: ${USE_CLOUDFLARE}" echo " Let's Encrypt: ${USE_LETSENCRYPT}" echo "" echo "Comandos úteis:" echo " # Ver todos os pods" echo " kubectl get pods -n n8n" echo "" echo " # Ver logs do n8n" echo " kubectl logs -f -n n8n deployment/n8n" echo "" echo " # Ver HPA (autoscaler)" echo " kubectl get hpa -n n8n" echo "" echo " # Ver ingress" echo " kubectl get ingress -n n8n" echo "" if [[ "$USE_LETSENCRYPT" == "true" ]]; then echo " # Ver status do certificado" echo " kubectl get certificate -n n8n" echo "" fi echo " # Adicionar novo cliente" echo " ./add-client.sh " echo "" echo " # Desinstalar" echo " helm uninstall n8n -n n8n" echo "" echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" # Mostrar status atual log_info "Status atual dos pods:" echo "" kubectl get pods -n n8n echo "" log_info "Status do HPA:" echo "" kubectl get hpa -n n8n 2>/dev/null || echo "HPA ainda não criado" echo "" log_info "Status do Ingress:" echo "" kubectl get ingress -n n8n echo ""