#!/bin/bash # ============================================ # Wordly.art - Configuration Wizard # ============================================ # Usage: bash scripts/setup-env.sh # ============================================ set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BOLD='\033[1m' NC='\033[0m' ENV_FILE=".env" echo "" echo -e "${CYAN}${BOLD}=========================================${NC}" echo -e "${CYAN}${BOLD} Wordly.art - Configuration Wizard${NC}" echo -e "${CYAN}${BOLD}=========================================${NC}" echo "" if [ ! -f "docker-compose.yml" ]; then echo -e "${RED}Erreur: lance ce script depuis la racine du projet (cd /opt/wordly)${NC}" exit 1 fi ask() { local prompt="$1" default="$2" varname="$3" required="$4" if [ -n "$default" ]; then echo -ne "${YELLOW}${prompt}${NC} [${default}]: " else echo -ne "${YELLOW}${prompt}${NC}: " fi read -r answer answer="${answer:-$default}" if [ "$required" = "true" ] && [ -z "$answer" ]; then echo -e "${RED}Cette valeur est obligatoire!${NC}" ask "$prompt" "$default" "$varname" "$required" return fi eval "$varname=\"\$answer\"" } ask_password() { local prompt="$1" varname="$2" echo -ne "${YELLOW}${prompt}${NC}: " stty -echo 2>/dev/null || true read -r answer stty echo 2>/dev/null || true echo "" eval "$varname=\"\$answer\"" } generate_secret() { python3 -c "import secrets; print(secrets.token_urlsafe(64))" 2>/dev/null || openssl rand -base64 48 | tr -d '\n' } generate_hex() { python3 -c "import secrets; print(secrets.token_hex(32))" 2>/dev/null || openssl rand -hex 32 } generate_password() { python3 -c "import secrets; print(secrets.token_urlsafe(32))" 2>/dev/null || openssl rand -base64 24 | tr -d '\n' } # =========================================== # ETAPE 1 : Domaine # =========================================== echo -e "${BOLD}--- Domaine ---${NC}" echo "" ask "Nom de domaine" "wordly.art" DOMAIN true # =========================================== # ETAPE 2 : Base de donnees # =========================================== echo "" echo -e "${BOLD}--- Base de donnees ---${NC}" echo "" ask "Utilisateur PostgreSQL" "translate" POSTGRES_USER true POSTGRES_PASSWORD=$(generate_password) echo -e " ${GREEN}Mot de passe DB genere${NC}" # =========================================== # ETAPE 3 : Admin # =========================================== echo "" echo -e "${BOLD}--- Compte Administrateur ---${NC}" echo "" ask "Nom d'utilisateur admin" "admin" ADMIN_USERNAME true ask_password "Mot de passe admin" ADMIN_PASSWORD if [ -z "$ADMIN_PASSWORD" ]; then echo -e "${RED}Le mot de passe admin est obligatoire!${NC}" ask_password "Mot de passe admin" ADMIN_PASSWORD fi echo "" ask_password "Confirmer le mot de passe" ADMIN_PASSWORD_CONFIRM if [ "$ADMIN_PASSWORD" != "$ADMIN_PASSWORD_CONFIRM" ]; then echo -e "${RED}Les mots de passe ne correspondent pas!${NC}" exit 1 fi echo -e " ${GREEN}Mot de passe confirme${NC}" echo -e " ${CYAN}Generation du hash bcrypt...${NC}" ADMIN_PASSWORD_HASH="" if command -v docker &> /dev/null; then ADMIN_PASSWORD_HASH=$(docker run --rm python:3.12-slim bash -c \ "pip install 'passlib[bcrypt]' bcrypt > /dev/null 2>&1 && \ python3 -c \"from passlib.context import CryptContext; \ print(CryptContext(schemes=['bcrypt']).hash('${ADMIN_PASSWORD}'))\"" 2>/dev/null) fi if [ -z "$ADMIN_PASSWORD_HASH" ]; then echo -e " ${YELLOW}Hash bcrypt non genere. Tu devras le faire manuellement.${NC}" ADMIN_PASSWORD_HASH="CHANGE_WITH_BCRYPT_HASH" else echo -e " ${GREEN}Hash bcrypt genere${NC}" fi # =========================================== # ETAPE 4 : Secrets auto # =========================================== echo "" echo -e "${BOLD}--- Secrets de securite (auto) ---${NC}" JWT_SECRET_KEY=$(generate_secret) ADMIN_TOKEN_SECRET=$(generate_hex) echo -e " ${GREEN}JWT_SECRET_KEY genere${NC}" echo -e " ${GREEN}ADMIN_TOKEN_SECRET genere${NC}" # =========================================== # ETAPE 5 : Services de traduction # =========================================== echo "" echo -e "${BOLD}--- Service de traduction ---${NC}" echo "" echo "Quel service par defaut ?" echo " 1) google (gratuit, aucune cle)" echo " 2) ollama (local, gratuit,需要一个 GPU)" echo " 3) deepseek (tres bon rapport Q/P, ~0.14$/M tokens)" echo " 4) minimax (MiniMax-M1 / m2.7)" echo " 5) deepl (haute qualite, 500k car/mois gratuit)" echo " 6) openai (GPT, payant)" echo " 7) openrouter (multi-modeles)" ask "Choix (1-7)" "1" TRANSLATION_CHOICE # Initialiser tous les flags a false GOOGLE_ENABLED="true" OLLAMA_ENABLED="false" OLLAMA_BASE_URL="http://ollama:11434" OLLAMA_MODEL="llama3" DEEPL_ENABLED="false" DEEPL_API_KEY="" OPENAI_ENABLED="false" OPENAI_API_KEY="" OPENAI_MODEL="gpt-4o-mini" OPENAI_BASE_URL="https://api.openai.com/v1" OPENROUTER_ENABLED="false" OPENROUTER_API_KEY="" OPENROUTER_MODEL="deepseek/deepseek-chat" DEEPSEEK_ENABLED="false" DEEPSEEK_API_KEY="" DEEPSEEK_MODEL="deepseek-chat" DEEPSEEK_BASE_URL="https://api.deepseek.com/v1" MINIMAX_ENABLED="false" MINIMAX_API_KEY="" MINIMAX_MODEL="MiniMax-M1" MINIMAX_BASE_URL="https://api.minimax.chat/v1" case "$TRANSLATION_CHOICE" in 1) TRANSLATION_SERVICE="google" ;; 2) TRANSLATION_SERVICE="ollama" OLLAMA_ENABLED="true" ask "URL Ollama" "http://ollama:11434" OLLAMA_BASE_URL ask "Modele Ollama" "llama3" OLLAMA_MODEL ;; 3) TRANSLATION_SERVICE="deepseek" DEEPSEEK_ENABLED="true" ask "Cle API DeepSeek" "" DEEPSEEK_API_KEY true ask "Modele DeepSeek" "deepseek-chat" DEEPSEEK_MODEL ;; 4) TRANSLATION_SERVICE="minimax" MINIMAX_ENABLED="true" ask "Cle API Minimax" "" MINIMAX_API_KEY true ask "Modele Minimax" "MiniMax-M1" MINIMAX_MODEL ;; 5) TRANSLATION_SERVICE="deepl" DEEPL_ENABLED="true" ask "Cle API DeepL" "" DEEPL_API_KEY true ;; 6) TRANSLATION_SERVICE="openai" OPENAI_ENABLED="true" ask "Cle API OpenAI" "" OPENAI_API_KEY true ask "Modele OpenAI" "gpt-4o-mini" OPENAI_MODEL ;; 7) TRANSLATION_SERVICE="openrouter" OPENROUTER_ENABLED="true" ask "Cle API OpenRouter" "" OPENROUTER_API_KEY true ask "Modele OpenRouter" "deepseek/deepseek-chat" OPENROUTER_MODEL ;; *) TRANSLATION_SERVICE="google" ;; esac # =========================================== # ETAPE 6 : Monitoring # =========================================== echo "" echo -e "${BOLD}--- Monitoring Grafana ---${NC}" echo "" ask "Utilisateur Grafana" "admin" GRAFANA_USER true GRAFANA_PASSWORD=$(generate_password) echo -e " ${GREEN}Mot de passe Grafana genere: ${GRAFANA_PASSWORD}${NC}" # =========================================== # ETAPE 7 : Stripe # =========================================== echo "" echo -e "${BOLD}--- Paiements Stripe (optionnel) ---${NC}" echo "" echo " Tu peux configurer Stripe plus tard avec: bash scripts/manage-keys.sh" ask "Configurer Stripe maintenant ? (oui/non)" "non" SETUP_STRIPE STRIPE_SECRET_KEY="" STRIPE_WEBHOOK_SECRET="" STRIPE_STARTER_PRICE_ID="" STRIPE_PRO_PRICE_ID="" STRIPE_BUSINESS_PRICE_ID="" if [ "$SETUP_STRIPE" = "oui" ]; then ask "Cle secrete Stripe (sk_live_... ou sk_test_...)" "" STRIPE_SECRET_KEY ask "Webhook secret (whsec_...)" "" STRIPE_WEBHOOK_SECRET ask "Price ID Starter (price_...)" "" STRIPE_STARTER_PRICE_ID ask "Price ID Pro (price_...)" "" STRIPE_PRO_PRICE_ID ask "Price ID Business (price_...)" "" STRIPE_BUSINESS_PRICE_ID fi # =========================================== # RESUME # =========================================== echo "" echo -e "${CYAN}${BOLD}=========================================${NC}" echo -e "${CYAN}${BOLD} Resume de la configuration${NC}" echo -e "${CYAN}${BOLD}=========================================${NC}" echo "" echo -e " Domaine: ${BOLD}${DOMAIN}${NC}" echo -e " Traduction: ${BOLD}${TRANSLATION_SERVICE}${NC}" echo -e " DB User: ${BOLD}${POSTGRES_USER}${NC}" echo -e " Admin: ${BOLD}${ADMIN_USERNAME}${NC}" echo -e " JWT Secret: ${BOLD}${JWT_SECRET_KEY:0:20}...${NC}" echo -e " Admin Token: ${BOLD}${ADMIN_TOKEN_SECRET:0:20}...${NC}" echo -e " Grafana: ${BOLD}${GRAFANA_USER} / ${GRAFANA_PASSWORD}${NC}" echo "" echo -e " Providers actifs:" echo -e " Google: ${GREEN}toujours actif${NC}" echo -e " Ollama: $([ "$OLLAMA_ENABLED" = "true" ] && echo "${GREEN}ON${NC}" || echo "${RED}OFF${NC}")" echo -e " DeepSeek: $([ "$DEEPSEEK_ENABLED" = "true" ] && echo "${GREEN}ON${NC}" || echo "${RED}OFF${NC}")" echo -e " Minimax: $([ "$MINIMAX_ENABLED" = "true" ] && echo "${GREEN}ON${NC}" || echo "${RED}OFF${NC}")" echo -e " DeepL: $([ "$DEEPL_ENABLED" = "true" ] && echo "${GREEN}ON${NC}" || echo "${RED}OFF${NC}")" echo -e " OpenAI: $([ "$OPENAI_ENABLED" = "true" ] && echo "${GREEN}ON${NC}" || echo "${RED}OFF${NC}")" echo -e " OpenRouter: $([ "$OPENROUTER_ENABLED" = "true" ] && echo "${GREEN}ON${NC}" || echo "${RED}OFF${NC}")" echo "" if [ -n "$STRIPE_SECRET_KEY" ]; then echo -e " Stripe: ${GREEN}Configure${NC}" else echo -e " Stripe: ${YELLOW}Non configure (gerer plus tard)${NC}" fi echo "" ask "Valider cette configuration ? (oui/non)" "oui" CONFIRM if [ "$CONFIRM" != "oui" ]; then echo "Annule." exit 0 fi # =========================================== # ECRITURE DU .env # =========================================== echo "" echo -e "${CYAN}Ecriture du fichier .env...${NC}" cat > "$ENV_FILE" <