fix: scripts properly set ENABLED flags and all env vars for providers
Some checks failed
Deploy to Homelab / Deploy Wordly to 192.168.1.151 (push) Has been cancelled
Deploy to Homelab / Deploy Monitoring (if configured) (push) Has been cancelled

setup-env.sh:
- Each provider choice now sets its *_ENABLEED=true flag explicitly
- All provider fields written to .env (model, base_url, api_key, enabled)
- Shows active provider status in summary

manage-keys.sh:
- Each provider menu sets *_ENABLEED=true when key is added
- Sets *_ENABLEED=false when key is removed
- Writes all required env vars (model, base_url) not just API key
- Shows provider status with enabled/disabled state
- Better organized menu

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 12:52:06 +02:00
parent 034d6bfce8
commit 7e97bbd07b
2 changed files with 324 additions and 277 deletions

View File

@@ -2,13 +2,11 @@
# ============================================
# Wordly.art - Configuration Wizard
# ============================================
# Script interactif pour configurer le .env
# Lancer sur le serveur: bash scripts/setup-env.sh
# Usage: bash scripts/setup-env.sh
# ============================================
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
@@ -24,43 +22,30 @@ echo -e "${CYAN}${BOLD} Wordly.art - Configuration Wizard${NC}"
echo -e "${CYAN}${BOLD}=========================================${NC}"
echo ""
# Verifier qu'on est dans le bon dossier
if [ ! -f "docker-compose.yml" ]; then
echo -e "${RED}Erreur: lance ce script depuis la racine du projet (cd /opt/wordly)${NC}"
echo "Usage: bash scripts/setup-env.sh"
exit 1
fi
# Fonction pour demander une valeur avec defaut
ask() {
local prompt="$1"
local default="$2"
local varname="$3"
local required="$4"
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\""
}
# Fonction pour demander un mot de passe cache
ask_password() {
local prompt="$1"
local varname="$2"
local prompt="$1" varname="$2"
echo -ne "${YELLOW}${prompt}${NC}: "
stty -echo 2>/dev/null || true
read -r answer
@@ -69,26 +54,20 @@ ask_password() {
eval "$varname=\"\$answer\""
}
# Fonction pour generer un secret
generate_secret() {
python3 -c "import secrets; print(secrets.token_urlsafe(64))" 2>/dev/null || \
openssl rand -base64 48 | tr -d '\n'
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
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'
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 & DNS ---${NC}"
echo -e "${BOLD}--- Domaine ---${NC}"
echo ""
ask "Nom de domaine" "wordly.art" DOMAIN true
@@ -96,11 +75,11 @@ ask "Nom de domaine" "wordly.art" DOMAIN true
# ETAPE 2 : Base de donnees
# ===========================================
echo ""
echo -e "${BOLD}--- Base de donnees PostgreSQL ---${NC}"
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 genere automatiquement${NC}"
echo -e " ${GREEN}Mot de passe DB genere${NC}"
# ===========================================
# ETAPE 3 : Admin
@@ -109,10 +88,10 @@ echo ""
echo -e "${BOLD}--- Compte Administrateur ---${NC}"
echo ""
ask "Nom d'utilisateur admin" "admin" ADMIN_USERNAME true
ask_password "Mot de passe admin (cache)" ADMIN_PASSWORD
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 (cache)" ADMIN_PASSWORD
ask_password "Mot de passe admin" ADMIN_PASSWORD
fi
echo ""
ask_password "Confirmer le mot de passe" ADMIN_PASSWORD_CONFIRM
@@ -122,29 +101,26 @@ if [ "$ADMIN_PASSWORD" != "$ADMIN_PASSWORD_CONFIRM" ]; then
fi
echo -e " ${GREEN}Mot de passe confirme${NC}"
# Generer le hash bcrypt
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}Impossible de generer le hash bcrypt automatiquement.${NC}"
echo -e " ${YELLOW}Tu devras le generer manuellement plus tard.${NC}"
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
# ETAPE 4 : Secrets auto
# ===========================================
echo ""
echo -e "${BOLD}--- Secrets de securite ---${NC}"
echo -e " ${CYAN}Generation automatique des secrets...${NC}"
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}"
@@ -154,59 +130,80 @@ echo -e " ${GREEN}ADMIN_TOKEN_SECRET genere${NC}"
# ETAPE 5 : Services de traduction
# ===========================================
echo ""
echo -e "${BOLD}--- Services de traduction ---${NC}"
echo -e "${BOLD}--- Service de traduction ---${NC}"
echo ""
echo "Quel service de traduction par defaut ?"
echo " 1) ollama (local, gratuit)"
echo " 2) google (API gratuite via deep_translator)"
echo " 3) deepl (haute qualite, 500k car/mois gratuit)"
echo " 4) openai (GPT, payant)"
echo " 5) openrouter (multi-modeles, payant)"
echo " 6) deepseek (tres bon rapport qualite/prix)"
echo " 7) minimax (MiniMax-M1 / m2.7, payant)"
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
case "$TRANSLATION_CHOICE" in
1) TRANSLATION_SERVICE="ollama" ;;
2) TRANSLATION_SERVICE="google" ;;
3) TRANSLATION_SERVICE="deepl" ;;
4) TRANSLATION_SERVICE="openai" ;;
5) TRANSLATION_SERVICE="openrouter" ;;
6) TRANSLATION_SERVICE="deepseek" ;;
7) TRANSLATION_SERVICE="minimax" ;;
*) TRANSLATION_SERVICE="ollama" ;;
esac
# 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"
if [ "$TRANSLATION_SERVICE" = "ollama" ]; then
ask "URL Ollama" "http://ollama:11434" OLLAMA_BASE_URL
ask "Modele Ollama" "llama3" OLLAMA_MODEL
fi
if [ "$TRANSLATION_SERVICE" = "deepl" ] || [ "$TRANSLATION_SERVICE" = "all" ]; then
ask "Cle API DeepL (laisser vide si pas maintenant)" "" DEEPL_API_KEY
fi
if [ "$TRANSLATION_SERVICE" = "openai" ] || [ "$TRANSLATION_SERVICE" = "all" ]; then
ask "Cle API OpenAI (laisser vide si pas maintenant)" "" OPENAI_API_KEY
fi
if [ "$TRANSLATION_SERVICE" = "openrouter" ] || [ "$TRANSLATION_SERVICE" = "all" ]; then
ask "Cle API OpenRouter (laisser vide si pas maintenant)" "" OPENROUTER_API_KEY
fi
if [ "$TRANSLATION_SERVICE" = "deepseek" ] || [ "$TRANSLATION_SERVICE" = "all" ]; then
ask "Cle API DeepSeek (laisser vide si pas maintenant)" "" DEEPSEEK_API_KEY
fi
if [ "$TRANSLATION_SERVICE" = "minimax" ] || [ "$TRANSLATION_SERVICE" = "all" ]; then
ask "Cle API Minimax (laisser vide si pas maintenant)" "" MINIMAX_API_KEY
fi
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
@@ -219,11 +216,12 @@ GRAFANA_PASSWORD=$(generate_password)
echo -e " ${GREEN}Mot de passe Grafana genere: ${GRAFANA_PASSWORD}${NC}"
# ===========================================
# ETAPE 7 : Stripe (optionnel)
# 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=""
@@ -232,11 +230,11 @@ STRIPE_PRO_PRICE_ID=""
STRIPE_BUSINESS_PRICE_ID=""
if [ "$SETUP_STRIPE" = "oui" ]; then
ask "Cle secrete Stripe (sk_live_...)" "" STRIPE_SECRET_KEY
ask "Cle secrete Stripe (sk_live_... ou sk_test_...)" "" STRIPE_SECRET_KEY
ask "Webhook secret (whsec_...)" "" STRIPE_WEBHOOK_SECRET
ask "Price ID Starter" "" STRIPE_STARTER_PRICE_ID
ask "Price ID Pro" "" STRIPE_PRO_PRICE_ID
ask "Price ID Business" "" STRIPE_BUSINESS_PRICE_ID
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
# ===========================================
@@ -247,39 +245,46 @@ 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 " Admin hash: ${BOLD}${ADMIN_PASSWORD_HASH:0:20}...${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 -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}"
echo -e " Stripe: ${GREEN}Configure${NC}"
else
echo -e " Stripe: ${YELLOW}Non configure${NC}"
echo -e " Stripe: ${YELLOW}Non configure (gerer plus tard)${NC}"
fi
echo ""
# Confirmation
ask "Cette configuration est correcte ? (oui/non)" "oui" CONFIRM
ask "Valider cette configuration ? (oui/non)" "oui" CONFIRM
if [ "$CONFIRM" != "oui" ]; then
echo "Annule. Relance le script pour recommencer."
echo "Annule."
exit 0
fi
# ===========================================
# GENERATION DU FICHIER .env
# ECRITURE DU .env
# ===========================================
echo ""
echo -e "${CYAN}Generation du fichier .env...${NC}"
echo -e "${CYAN}Ecriture du fichier .env...${NC}"
cat > "$ENV_FILE" <<ENVEOF
cat > "$ENV_FILE" <<EOF
# ============================================
# Wordly.art - Environnement de production
# Genere automatiquement le $(date +"%Y-%m-%d a %H:%M")
# Genere le $(date +"%Y-%m-%d a %H:%M")
# ============================================
# Application
@@ -296,24 +301,43 @@ NEXT_PUBLIC_API_URL=https://${DOMAIN}
BACKEND_PORT=8000
FRONTEND_PORT=3000
# Traduction
# ===== TRADUCTION =====
TRANSLATION_SERVICE=${TRANSLATION_SERVICE}
OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://ollama:11434}
OLLAMA_MODEL=${OLLAMA_MODEL:-llama3}
DEEPL_API_KEY=${DEEPL_API_KEY}
OPENAI_API_KEY=${OPENAI_API_KEY}
OPENAI_MODEL=gpt-4o-mini
OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
# Google (toujours actif, gratuit)
GOOGLE_TRANSLATE_ENABLED=true
# Ollama (local LLM)
OLLAMA_ENABLED=${OLLAMA_ENABLED}
OLLAMA_BASE_URL=${OLLAMA_BASE_URL}
OLLAMA_MODEL=${OLLAMA_MODEL}
# DeepSeek
DEEPSEEK_ENABLED=${DEEPSEEK_ENABLED:-false}
DEEPSEEK_ENABLED=${DEEPSEEK_ENABLED}
DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
DEEPSEEK_MODEL=deepseek-chat
DEEPSEEK_MODEL=${DEEPSEEK_MODEL}
DEEPSEEK_BASE_URL=${DEEPSEEK_BASE_URL}
# Minimax (m2.7 / MiniMax-M1)
MINIMAX_ENABLED=${MINIMAX_ENABLED:-false}
MINIMAX_ENABLED=${MINIMAX_ENABLED}
MINIMAX_API_KEY=${MINIMAX_API_KEY}
MINIMAX_MODEL=MiniMax-M1
MINIMAX_MODEL=${MINIMAX_MODEL}
MINIMAX_BASE_URL=${MINIMAX_BASE_URL}
# DeepL
DEEPL_ENABLED=${DEEPL_ENABLED}
DEEPL_API_KEY=${DEEPL_API_KEY}
# OpenAI
OPENAI_ENABLED=${OPENAI_ENABLED}
OPENAI_API_KEY=${OPENAI_API_KEY}
OPENAI_MODEL=${OPENAI_MODEL}
OPENAI_BASE_URL=${OPENAI_BASE_URL}
# OpenRouter
OPENROUTER_ENABLED=${OPENROUTER_ENABLED}
OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
OPENROUTER_MODEL=${OPENROUTER_MODEL}
# Upload
MAX_FILE_SIZE_MB=50
@@ -348,53 +372,19 @@ STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
STRIPE_STARTER_PRICE_ID=${STRIPE_STARTER_PRICE_ID}
STRIPE_PRO_PRICE_ID=${STRIPE_PRO_PRICE_ID}
STRIPE_BUSINESS_PRICE_ID=${STRIPE_BUSINESS_PRICE_ID}
ENVEOF
EOF
# Securiser le fichier
chmod 600 "$ENV_FILE"
echo -e "${GREEN}Fichier .env cree avec succes!${NC}"
echo -e "${GREEN}.env ecrit avec succes!${NC}"
echo ""
# ===========================================
# PROPOSITIONS FINALES
# ===========================================
echo -e "${BOLD}Prochaines etapes :${NC}"
echo " 1. Verifier: ${CYAN}cat .env${NC}"
echo " 2. Lancer: ${CYAN}docker compose up -d --build${NC}"
echo " 3. Tester: ${CYAN}curl http://localhost:8000/health${NC}"
echo " 4. Monitorer: ${CYAN}docker compose ps${NC}"
echo ""
echo -e " 1. Verifier le fichier:"
echo -e " ${CYAN}cat .env${NC}"
echo ""
echo -e " 2. Lancer l'application:"
echo -e " ${CYAN}docker compose up -d --build${NC}"
echo ""
echo -e " 3. Verifier que tout tourne:"
echo -e " ${CYAN}docker compose ps${NC}"
echo -e " ${CYAN}curl http://localhost:8000/health${NC}"
echo ""
echo -e " 4. Lancer le monitoring:"
echo -e " ${CYAN}docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d${NC}"
echo ""
# Sauvegarder les infos importantes dans un fichier temp
INFO_FILE="/tmp/wordly-setup-info.txt"
cat > "$INFO_FILE" <<INFOEOF
========================================
Wordly.art - Infos de configuration
Genere le $(date)
========================================
Domaine: ${DOMAIN}
Admin: ${ADMIN_USERNAME}
Grafana: ${GRAFANA_USER} / ${GRAFANA_PASSWORD}
DB Password: ${POSTGRES_PASSWORD}
ATTENTION: Ce fichier contient des secrets!
Supprime-le apres avoir note les infos: rm ${INFO_FILE}
========================================
INFOEOF
chmod 600 "$INFO_FILE"
echo -e "${YELLOW}Infos sensibles sauvegardees dans ${INFO_FILE}${NC}"
echo -e "${YELLOW}Supprime ce fichier apres note: rm ${INFO_FILE}${NC}"
echo -e "${YELLOW}Pour ajouter/modifier des cles API plus tard:${NC}"
echo " ${CYAN}bash scripts/manage-keys.sh${NC}"
echo ""
echo -e "${GREEN}${BOLD}Configuration terminee!${NC}"