Skip to content

Installation Complète

Déploiement pas-à-pas du NOC RGZ en 5 étapes.

Prérequis

✅ Complétez Prérequis AVANT de commencer.

Étape 1: Cloner le dépôt

bash
# Cloner
cd /opt  # Ou votre répertoire préféré
git clone https://github.com/gtognisso/RGZ.git
cd RGZ

# Vérifier
ls -la
# Devrait afficher: docker-compose.core.yml, docker-compose.monitoring.yml, .env.example, scripts/, app/, web/...

# Activer scripts
chmod +x scripts/ops/*.sh
ls -la scripts/ops/
# Devrait afficher: init.sh, start.sh, stop.sh, status.sh, smoke_test.sh

Étape 2: Configurer .env

Copier template

bash
cp .env.example .env

Variables OBLIGATOIRES à configurer

Éditer .env avec nano, vi, ou votre éditeur:

bash
nano .env

Section PostgreSQL:

bash
POSTGRES_USER=rgz_admin
POSTGRES_PASSWORD=<générer 32 chars>      # openssl rand -hex 32
POSTGRES_DB=rgz_noc

Section Redis:

bash
REDIS_PASSWORD=<générer 32 chars>         # openssl rand -hex 32

Section FreeRADIUS:

bash
RADIUS_SECRET=<générer 32 chars>          # openssl rand -hex 32

Section ELK Stack:

bash
ELASTIC_PASSWORD=<générer 32 chars>       # openssl rand -hex 32
KIBANA_PASSWORD=<même que ELASTIC>

Section Grafana:

bash
GRAFANA_ADMIN_PASSWORD=<générer 16 chars> # openssl rand -hex 16
GRAFANA_SECRET_KEY=<générer 32 chars>     # openssl rand -hex 32

Section JWT Authentication:

bash
JWT_SECRET_KEY=<générer 64 chars>         # openssl rand -hex 64
JWT_ALGORITHM=RS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=15
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7

Section Paiement (KKiaPay):

bash
KKIAPAY_PUBLIC_KEY=<copier depuis KKiaPay dashboard>
KKIAPAY_SECRET=<copier depuis KKiaPay dashboard>
KKIAPAY_SANDBOX=false  # ou true en dev

Section SMS (Letexto):

bash
LETEXTO_API_KEY=<copier depuis Letexto dashboard>
LETEXTO_BASE_URL=https://api.letexto.com

Section SMTP:

bash
SMTP_HOST=smtp.gmail.com        # ou votre provider
SMTP_PORT=587
SMTP_USER=<votre email>
SMTP_PASSWORD=<App Password si Gmail, sinon le mot de passe SMTP>
SMTP_FROM=noc@rgz.bj

Section DuckDNS + Traefik:

bash
DUCKDNS_TOKEN=<copier depuis DuckDNS>
TRAEFIK_DASHBOARD_PASSWORD=<générer 16 chars>

Section API:

bash
API_HOST=0.0.0.0
API_PORT=8000
API_WORKERS=4
DEBUG=false
ENVIRONMENT=production

Section Celery:

bash
CELERY_BROKER_URL=redis://:${REDIS_PASSWORD}@rgz-redis:6379/0
CELERY_RESULT_BACKEND=redis://:${REDIS_PASSWORD}@rgz-redis:6379/1

Section WhatsApp Business:

bash
WHATSAPP_API_TOKEN=<copier depuis Meta Business>
WHATSAPP_PHONE_NUMBER_ID=<copier depuis Meta Business>

Générer secrets sécurisés

bash
# Générer 32 chars hex
openssl rand -hex 32

# Générer 64 chars hex
openssl rand -hex 64

# Générer 16 chars hex
openssl rand -hex 16

# Exemples:
# 32 chars: 7f9e8d2c1a4b5c6d7e8f9a0b1c2d3e4f
# 64 chars: 7f9e8d2c1a4b5c6d7e8f9a0b1c2d3e4f7f9e8d2c1a4b5c6d7e8f9a0b1c2d3e4f
# 16 chars: 7f9e8d2c1a4b5c6d

Valider .env

bash
# Vérifier syntaxe
bash -n <(cat .env)
# Doit retourner sans erreur

# Vérifier variables obligatoires
grep -E "^(POSTGRES_PASSWORD|REDIS_PASSWORD|RADIUS_SECRET|ELASTIC_PASSWORD)=" .env
# Doit afficher 4 lignes (pas vides)

Étape 3: Exécuter init.sh

⚠️ À exécuter UNE SEULE FOIS (crée DB, initialise Elasticsearch, etc.)

bash
# Lancer init
./scripts/ops/init.sh

# Output attendu:
# ✅ Creating database rgz_noc...
# ✅ Initializing Elasticsearch...
# ✅ Creating Grafana database...
# ✅ Waiting for services (60s timeout)...
# ✅ All checks passed!

En cas d'erreur lors de init.sh

Erreur: "Connection refused" sur PostgreSQL

bash
# Cause: DB pas encore démarrée
# Solution: Attendre 2-3s et relancer
sleep 10 && ./scripts/ops/init.sh

Erreur: "database rgz_noc already exists"

bash
# Cause: init.sh a déjà tourné
# Solution: C'est normal, passer à Étape 4 (start.sh)
./scripts/ops/start.sh

Erreur: "Elasticsearch cluster health: red"

bash
# Cause: Elasticsearch en démarrage
# Solution: Attendre que health devienne "yellow" ou "green"
docker logs rgz-elasticsearch | tail -20
# Attendre ~30s puis relancer

Erreur: "Cannot connect to Docker daemon"

bash
# Cause: Pas d'accès Docker
# Solution: Ajouter user au groupe docker
sudo usermod -aG docker $USER
newgrp docker
# Relancer
./scripts/ops/init.sh

Étape 4: Démarrer la stack

bash
# Démarrer tous les services
./scripts/ops/start.sh

# Output attendu:
# ✅ Starting Docker Compose stacks...
# ✅ Stack core started
# ✅ Stack monitoring started
# ✅ Waiting for services (120s)...

Vérifier le statut

bash
# Vérifier tous les services
./scripts/ops/status.sh

# Output attendu:
# SERVICE              STATUS       HEALTH
# rgz-api              running      healthy ✅
# rgz-db               running      healthy ✅
# rgz-redis            running      healthy ✅
# rgz-radius           running      healthy ✅
# ... (12 autres services)

Services "unhealthy"?

bash
# Vérifier logs du service problématique
docker logs rgz-api --tail 50
docker logs rgz-db --tail 50

# Attendre 5s et relancer status.sh
sleep 5 && ./scripts/ops/status.sh

# Si toujours unhealthy: voir "Dépannage" ci-dessous

Étape 5: Vérification fonctionnelle

Run smoke tests

bash
./scripts/ops/smoke_test.sh

# Output attendu:
# ✅ API health: OK
# ✅ Database: OK
# ✅ Redis: OK
# ✅ RADIUS: OK
# ✅ DNS: OK
# ✅ All tests passed!

Accès web

Ouvrir dans le navigateur:

Credentials par défaut:

ServiceUserPassword
Grafanaadmin(voir GRAFANA_ADMIN_PASSWORD dans .env)
Elasticsearchelastic(voir ELASTIC_PASSWORD dans .env)
Kibanaelastic(voir KIBANA_PASSWORD dans .env)

Test de flux complet

bash
# 1. Générer un OTP SMS
curl -X POST https://api-rgz.duckdns.org/api/v1/otp/request \
  -H "Content-Type: application/json" \
  -d '{"phone": "+22901234567"}'

# Réponse attendue:
# {"otp_id": "uuid", "expires_at": "..."}

# 2. Vérifier que SMS a été envoyé (check Letexto logs)
docker logs rgz-api | grep "letexto"

# 3. Vérifier logs API
docker logs rgz-api --tail 20

Variables d'environnement complètes

Voir Tableau complet variables

Dépannage courant

Services ne démarrent pas

bash
# Cause: Erreurs dans Dockerfiles
# Solution: Vérifier les logs
docker compose -f docker-compose.core.yml logs --follow

# Ou directement sur un service
docker logs rgz-api -f

HTTPS non actif sur Traefik

bash
# Cause: Let's Encrypt pas prêt (attendre 2-3 min après démarrage)
# Solution: Vérifier Traefik
docker logs traefik | grep "Let's Encrypt"

# Si "error: dns problem": DuckDNS token incorrect
# Corriger DUCKDNS_TOKEN dans .env et redémarrer
docker compose -f docker-compose.core.yml restart traefik

Elasticsearch ne démarre pas

bash
# Cause: Pas assez de RAM ou vm.max_map_count trop bas
# Solution:
sudo sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf

# Redémarrer Elasticsearch
docker compose -f docker-compose.monitoring.yml restart rgz-elasticsearch

PostgreSQL timezone warning

bash
# C'est un warning inoffensif, ignorable
# Pour le corriger (optionnel):
docker exec -it rgz-db psql -U rgz_admin -d rgz_noc \
  -c "SELECT timezone('UTC', now());"

Étapes suivantes

  1. ✅ Vérifier que tous les services sont healthy
  2. ✅ Consulter Accès URLs pour se connecter
  3. ✅ Lire Architecture pour comprendre la stack
  4. ✅ Consulter Opérations pour start/stop/logs

Rollback (si nécessaire)

bash
# Arrêter la stack
./scripts/ops/stop.sh

# Nettoyer les volumes (⚠️ supprime les données)
docker compose -f docker-compose.core.yml down -v
docker compose -f docker-compose.monitoring.yml down -v

# Reconfigurer .env et relancer
./scripts/ops/init.sh
./scripts/ops/start.sh

Support

  • Vérifier logs: docker logs <service>
  • Dépannage réseau: docker network ls
  • État stack: ./scripts/ops/status.sh
  • Réinitialiser: ./scripts/ops/init.sh --force

PROJET MOSAÏQUE — 81 outils, 22 conteneurs, 500+ revendeurs WiFi Zone