#!/bin/bash # ============================================================================= # start.sh — Script de démarrage HuggingFace Spaces # # Rôle : # 1. Initialise le cluster PostgreSQL (premier démarrage uniquement) # 2. Crée la base, applique le schéma et crée l'utilisateur read-only # 3. Démarre PostgreSQL en tâche de fond # 4. Lance Streamlit en premier plan (PID 1 du conteneur) # # Variables d'environnement attendues (Secrets HF Spaces) : # POSTGRES_PASSWORD — mot de passe du superutilisateur 'admin' # PG_USER_1_PASSWORD — mot de passe de l'utilisateur read-only 'user_1' # MISTRAL_API_KEY — clé API Mistral # LOGFIRE_TOKEN — (optionnel) token Logfire # ============================================================================= set -e # --------------------------------------------------------------------------- # Valeurs par défaut (peuvent être surchargées par les Secrets HF) # --------------------------------------------------------------------------- PGDATA="${PGDATA:-/home/user/pgdata}" PG_DB="${PG_DB:-oc_mlops_projet_3}" PG_ADMIN="${PG_ADMIN:-admin}" PG_PORT="${PG_PORT:-5432}" POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-changeme_set_in_hf_secrets}" PG_USER_1_PASSWORD="${PG_USER_1_PASSWORD:-readonly_set_in_hf_secrets}" APP_DIR="/home/user/app" SQL_DIR="$APP_DIR/sql" PG_LOG="/tmp/postgresql.log" # --------------------------------------------------------------------------- # Étape 1 — Initialisation du cluster PostgreSQL (premier démarrage) # --------------------------------------------------------------------------- if [ ! -f "$PGDATA/PG_VERSION" ]; then echo "🔧 [PG] Initialisation du cluster PostgreSQL dans $PGDATA ..." mkdir -p "$PGDATA" # initdb crée le cluster ; l'utilisateur courant (UID 1000) devient superutilisateur # --username définit le nom du superutilisateur PostgreSQL # --pwfile définit son mot de passe depuis un fd temporaire (évite l'exposition dans les logs) initdb \ -D "$PGDATA" \ --username="$PG_ADMIN" \ --pwfile=<(printf '%s' "$POSTGRES_PASSWORD") \ --auth-host=md5 \ --auth-local=md5 \ -E UTF8 \ --locale=C \ > /tmp/initdb.log 2>&1 # Configuration réseau : écoute uniquement sur localhost echo "listen_addresses = '127.0.0.1'" >> "$PGDATA/postgresql.conf" echo "port = $PG_PORT" >> "$PGDATA/postgresql.conf" # HF Spaces tourne en non-root : /var/run/postgresql n'est pas accessible. # On redirige le socket Unix vers /tmp (toujours accessible à UID 1000). echo "unix_socket_directories = '/tmp'" >> "$PGDATA/postgresql.conf" echo "✅ [PG] Cluster initialisé." # ----------------------------------------------------------------------- # Démarrage temporaire pour créer la base et le schéma # ----------------------------------------------------------------------- echo "🚀 [PG] Démarrage temporaire pour l'initialisation ..." pg_ctl -D "$PGDATA" -l "$PG_LOG" start -w -t 60 || { echo "❌ [PG] Échec du démarrage. Log :"; cat "$PG_LOG"; exit 1; } echo "📦 [PG] Création de la base '$PG_DB' ..." PGPASSWORD="$POSTGRES_PASSWORD" createdb \ -h 127.0.0.1 -p "$PG_PORT" -U "$PG_ADMIN" \ "$PG_DB" echo "📐 [PG] Application du schéma relationnel ..." PGPASSWORD="$POSTGRES_PASSWORD" psql \ -h 127.0.0.1 -p "$PG_PORT" \ -U "$PG_ADMIN" -d "$PG_DB" \ -f "$SQL_DIR/01_schema.sql" \ > /tmp/schema_init.log 2>&1 echo "👤 [PG] Création de l'utilisateur read-only 'user_1' ..." PGPASSWORD="$POSTGRES_PASSWORD" psql \ -h 127.0.0.1 -p "$PG_PORT" \ -U "$PG_ADMIN" -d "$PG_DB" << SQL CREATE ROLE user_1 WITH LOGIN NOINHERIT PASSWORD '$PG_USER_1_PASSWORD'; GRANT CONNECT ON DATABASE $PG_DB TO user_1; GRANT USAGE ON SCHEMA public TO user_1; GRANT SELECT ON ALL TABLES IN SCHEMA public TO user_1; SQL echo "⏹️ [PG] Arrêt du démarrage temporaire ..." pg_ctl -D "$PGDATA" stop echo "✅ [PG] Initialisation terminée." fi # --------------------------------------------------------------------------- # Étape 2 — Démarrage de PostgreSQL en tâche de fond # --------------------------------------------------------------------------- echo "🚀 [PG] Démarrage de PostgreSQL (port $PG_PORT) ..." pg_ctl -D "$PGDATA" -l "$PG_LOG" start -w -t 60 || { echo "❌ [PG] Échec du démarrage. Log :"; cat "$PG_LOG"; exit 1; } echo "✅ [PG] PostgreSQL démarré." # --------------------------------------------------------------------------- # Étape 3 — Démarrage de Streamlit en premier plan (port 7860, HF Spaces) # --------------------------------------------------------------------------- echo "🚀 [Streamlit] Démarrage sur le port 7860 ..." cd "$APP_DIR" exec streamlit run MistralChat.py \ --server.port=7860 \ --server.address=0.0.0.0 \ --server.headless=true \ --browser.gatherUsageStats=false