Complete implementation ready for Coolify: - Node.js 22 + Fastify + socket.io backend - PostgreSQL 16 + Redis 7 services - Docker Compose configuration - Deployment scripts and documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
311 lines
9.4 KiB
Bash
Executable file
311 lines
9.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ============================================================================
|
|
# AgentHub - Déploiement via API Coolify
|
|
# ============================================================================
|
|
#
|
|
# Usage:
|
|
# ./scripts/deploy-coolify-api.sh [--token=<coolify-token>] [--git-url=<repo-url>]
|
|
#
|
|
# Variables d'environnement requises:
|
|
# COOLIFY_TOKEN - Bearer token API Coolify (ou --token)
|
|
# COOLIFY_URL - URL de l'API Coolify (défaut: http://192.168.9.25:8000/api/v1)
|
|
# GIT_REPO_URL - URL du repo Git AgentHub (ou --git-url, optionnel si déjà configuré)
|
|
#
|
|
# Exemple:
|
|
# export COOLIFY_TOKEN="your-token-here"
|
|
# export GIT_REPO_URL="https://forgejo.barodine.net/barodine/agenthub.git"
|
|
# ./scripts/deploy-coolify-api.sh
|
|
#
|
|
|
|
# ============================================================================
|
|
# Configuration
|
|
# ============================================================================
|
|
|
|
COOLIFY_URL="${COOLIFY_URL:-http://192.168.9.25:8000/api/v1}"
|
|
COOLIFY_TOKEN="${COOLIFY_TOKEN:-}"
|
|
GIT_REPO_URL="${GIT_REPO_URL:-}"
|
|
GIT_BRANCH="${GIT_BRANCH:-main}"
|
|
COMPOSE_FILE="${COMPOSE_FILE:-compose.coolify.yml}"
|
|
DOMAIN="${DOMAIN:-agenthub.barodine.net}"
|
|
|
|
# Couleurs pour les logs
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# ============================================================================
|
|
# Fonctions utilitaires
|
|
# ============================================================================
|
|
|
|
log() {
|
|
echo -e "${BLUE}[INFO]${NC} $*"
|
|
}
|
|
|
|
success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $*"
|
|
}
|
|
|
|
warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $*"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[ERROR]${NC} $*" >&2
|
|
}
|
|
|
|
die() {
|
|
error "$*"
|
|
exit 1
|
|
}
|
|
|
|
# Parse arguments
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--token=*)
|
|
COOLIFY_TOKEN="${arg#*=}"
|
|
shift
|
|
;;
|
|
--git-url=*)
|
|
GIT_REPO_URL="${arg#*=}"
|
|
shift
|
|
;;
|
|
--help)
|
|
head -20 "$0" | tail -n +2
|
|
exit 0
|
|
;;
|
|
*)
|
|
die "Unknown argument: $arg"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# ============================================================================
|
|
# Validation
|
|
# ============================================================================
|
|
|
|
log "Validation des prérequis..."
|
|
|
|
if [[ -z "$COOLIFY_TOKEN" ]]; then
|
|
die "COOLIFY_TOKEN requis. Exécutez: export COOLIFY_TOKEN='your-token' ou utilisez --token="
|
|
fi
|
|
|
|
if [[ ! -f "$COMPOSE_FILE" ]]; then
|
|
die "Fichier compose non trouvé: $COMPOSE_FILE"
|
|
fi
|
|
|
|
# Test de connectivité
|
|
log "Test de connectivité à Coolify ($COOLIFY_URL)..."
|
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
-H "Authorization: Bearer $COOLIFY_TOKEN" \
|
|
"$COOLIFY_URL/teams")
|
|
|
|
if [[ "$HTTP_CODE" != "200" ]]; then
|
|
die "Échec de connexion à Coolify (HTTP $HTTP_CODE). Vérifiez le token et l'URL."
|
|
fi
|
|
|
|
success "Connectivité Coolify OK"
|
|
|
|
# ============================================================================
|
|
# Génération des secrets
|
|
# ============================================================================
|
|
|
|
log "Génération des secrets..."
|
|
|
|
# Générer JWT secret si pas déjà défini
|
|
if [[ -z "${JWT_SECRET:-}" ]]; then
|
|
JWT_SECRET=$(openssl rand -base64 32)
|
|
log "JWT_SECRET généré: ${JWT_SECRET:0:8}..."
|
|
fi
|
|
|
|
# Générer Postgres password si pas déjà défini
|
|
if [[ -z "${POSTGRES_PASSWORD:-}" ]]; then
|
|
POSTGRES_PASSWORD=$(openssl rand -base64 24)
|
|
log "POSTGRES_PASSWORD généré: ${POSTGRES_PASSWORD:0:8}..."
|
|
fi
|
|
|
|
# ============================================================================
|
|
# Récupération des informations Coolify
|
|
# ============================================================================
|
|
|
|
log "Récupération des informations Coolify..."
|
|
|
|
# Obtenir la liste des teams
|
|
TEAMS=$(curl -s -H "Authorization: Bearer $COOLIFY_TOKEN" "$COOLIFY_URL/teams")
|
|
TEAM_ID=$(echo "$TEAMS" | python3 -c "import sys, json; teams=json.load(sys.stdin); print(teams[0]['id'] if teams else '')")
|
|
|
|
if [[ -z "$TEAM_ID" ]]; then
|
|
die "Aucune équipe trouvée dans Coolify"
|
|
fi
|
|
|
|
log "Team ID: $TEAM_ID"
|
|
|
|
# Obtenir la liste des projets
|
|
PROJECTS=$(curl -s -H "Authorization: Bearer $COOLIFY_TOKEN" "$COOLIFY_URL/projects")
|
|
PROJECT_ID=$(echo "$PROJECTS" | python3 -c "import sys, json; projects=json.load(sys.stdin); print(next((p['uuid'] for p in projects if p.get('name') == 'AgentHub'), ''))")
|
|
|
|
# ============================================================================
|
|
# Création du projet si nécessaire
|
|
# ============================================================================
|
|
|
|
if [[ -z "$PROJECT_ID" ]]; then
|
|
log "Création du projet AgentHub..."
|
|
|
|
PROJECT_RESPONSE=$(curl -s -X POST "$COOLIFY_URL/projects" \
|
|
-H "Authorization: Bearer $COOLIFY_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"name": "AgentHub",
|
|
"description": "Plateforme de collaboration agent-à-agent Barodine",
|
|
"team_id": "'"$TEAM_ID"'"
|
|
}')
|
|
|
|
PROJECT_ID=$(echo "$PROJECT_RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data.get('uuid', ''))")
|
|
|
|
if [[ -z "$PROJECT_ID" ]]; then
|
|
error "Réponse Coolify: $PROJECT_RESPONSE"
|
|
die "Échec de création du projet"
|
|
fi
|
|
|
|
success "Projet créé: $PROJECT_ID"
|
|
else
|
|
log "Projet AgentHub existant: $PROJECT_ID"
|
|
fi
|
|
|
|
# ============================================================================
|
|
# Configuration de l'application
|
|
# ============================================================================
|
|
|
|
log "Configuration de l'application AgentHub..."
|
|
|
|
# Préparer les variables d'environnement
|
|
ENV_VARS=$(cat <<EOF
|
|
{
|
|
"POSTGRES_USER": "agenthub",
|
|
"POSTGRES_PASSWORD": "$POSTGRES_PASSWORD",
|
|
"POSTGRES_DB": "agenthub",
|
|
"JWT_SECRET": "$JWT_SECRET",
|
|
"ALLOWED_ORIGINS": "https://$DOMAIN",
|
|
"NODE_ENV": "production",
|
|
"LOG_LEVEL": "info"
|
|
}
|
|
EOF
|
|
)
|
|
|
|
# Déterminer la source du code
|
|
if [[ -n "$GIT_REPO_URL" ]]; then
|
|
log "Utilisation du repo Git: $GIT_REPO_URL"
|
|
SOURCE_TYPE="git"
|
|
SOURCE_CONFIG='"source": {
|
|
"type": "git",
|
|
"repository": "'"$GIT_REPO_URL"'",
|
|
"branch": "'"$GIT_BRANCH"'"
|
|
},'
|
|
else
|
|
warn "Aucun repo Git spécifié. Coolify devra être configuré manuellement pour la source."
|
|
SOURCE_TYPE="manual"
|
|
SOURCE_CONFIG=""
|
|
fi
|
|
|
|
# Créer l'application via API
|
|
log "Création de l'application dans Coolify..."
|
|
|
|
APP_PAYLOAD=$(cat <<EOF
|
|
{
|
|
"name": "agenthub",
|
|
"description": "AgentHub - Gateway WebSocket pour agents IA",
|
|
"project_uuid": "$PROJECT_ID",
|
|
$SOURCE_CONFIG
|
|
"build_pack": "docker-compose",
|
|
"docker_compose_location": "$COMPOSE_FILE",
|
|
"fqdn": "$DOMAIN",
|
|
"environment_variables": $ENV_VARS
|
|
}
|
|
EOF
|
|
)
|
|
|
|
log "Payload de l'application:"
|
|
echo "$APP_PAYLOAD" | python3 -m json.tool
|
|
|
|
# Note: L'endpoint exact de création d'application peut varier selon la version de Coolify
|
|
# Documenter pour exécution manuelle si nécessaire
|
|
warn "Note: La création d'application via API Coolify peut nécessiter un endpoint spécifique"
|
|
warn "Consultez: $COOLIFY_URL (documentation API)"
|
|
|
|
# ============================================================================
|
|
# Affichage des informations
|
|
# ============================================================================
|
|
|
|
cat <<EOF
|
|
|
|
${GREEN}============================================================================
|
|
Configuration prête pour le déploiement
|
|
============================================================================${NC}
|
|
|
|
${BLUE}Informations Coolify:${NC}
|
|
- URL API: $COOLIFY_URL
|
|
- Team ID: $TEAM_ID
|
|
- Project ID: $PROJECT_ID
|
|
- Domaine: https://$DOMAIN
|
|
|
|
${BLUE}Configuration AgentHub:${NC}
|
|
- Compose: $COMPOSE_FILE
|
|
- Branch Git: $GIT_BRANCH
|
|
- Repo Git: ${GIT_REPO_URL:-<non configuré>}
|
|
|
|
${BLUE}Secrets générés:${NC}
|
|
- JWT_SECRET: ${JWT_SECRET:0:12}...
|
|
- POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:0:12}...
|
|
|
|
${YELLOW}Prochaines étapes:${NC}
|
|
|
|
1. ${GREEN}Si repo Git configuré:${NC}
|
|
- Push le code sur $GIT_REPO_URL (branche $GIT_BRANCH)
|
|
- Utiliser l'UI Coolify ou l'API pour créer l'application
|
|
|
|
2. ${GREEN}Si déploiement local:${NC}
|
|
- Configurer Coolify pour utiliser un contexte local
|
|
- Ou utiliser l'UI Coolify pour import manuel
|
|
|
|
3. ${GREEN}Vérification post-déploiement:${NC}
|
|
curl https://$DOMAIN/healthz
|
|
# Devrait retourner: {"status":"ok","uptime":...}
|
|
|
|
${BLUE}Variables à conserver:${NC}
|
|
export JWT_SECRET='$JWT_SECRET'
|
|
export POSTGRES_PASSWORD='$POSTGRES_PASSWORD'
|
|
|
|
${YELLOW}Documentation:${NC}
|
|
- Guide complet: docs/DEPLOY-COOLIFY-QUICKSTART.md
|
|
- API Coolify: $COOLIFY_URL/docs (si disponible)
|
|
|
|
${GREEN}============================================================================${NC}
|
|
EOF
|
|
|
|
# Sauvegarder les secrets dans un fichier (pour référence)
|
|
SECRETS_FILE=".env.coolify.secrets"
|
|
cat > "$SECRETS_FILE" <<EOF
|
|
# Secrets générés pour déploiement Coolify
|
|
# Généré le: $(date -Iseconds)
|
|
# NE PAS COMMITTER CE FICHIER
|
|
|
|
JWT_SECRET='$JWT_SECRET'
|
|
POSTGRES_PASSWORD='$POSTGRES_PASSWORD'
|
|
POSTGRES_USER='agenthub'
|
|
POSTGRES_DB='agenthub'
|
|
ALLOWED_ORIGINS='https://$DOMAIN'
|
|
NODE_ENV='production'
|
|
LOG_LEVEL='info'
|
|
EOF
|
|
|
|
chmod 600 "$SECRETS_FILE"
|
|
success "Secrets sauvegardés dans: $SECRETS_FILE (chmod 600)"
|
|
|
|
# ============================================================================
|
|
# Fin
|
|
# ============================================================================
|
|
|
|
success "Configuration terminée. Consultez les étapes ci-dessus pour continuer."
|