Back to .md Directory

Infrastructure AWS - Harena

Documentation complète de l'infrastructure AWS et procédures de déploiement pour le projet Harena.

May 2, 2026
0 downloads
1 views
ai
View source

Infrastructure AWS - Harena

Documentation complète de l'infrastructure AWS et procédures de déploiement pour le projet Harena.


Table des matières

  1. Vue d'ensemble
  2. Accès à l'infrastructure
  3. Configuration des services
  4. Procédures de déploiement
  5. Monitoring et logs
  6. Résolution de problèmes
  7. Sécurité

Vue d'ensemble

Architecture déployée

L'application Harena est déployée sur AWS avec l'architecture suivante :

┌─────────────────────────────────────────────────────────────┐
│                         Internet                             │
└────────────────────────┬────────────────────────────────────┘
                         │
                         ▼
                  ┌──────────────┐
                  │  EC2 Instance │
                  │ 63.35.52.216 │
                  └──────┬───────┘
                         │
         ┌───────────────┼───────────────┐
         │               │               │
    ┌────▼────┐    ┌────▼────┐    ┌────▼────┐
    │ Nginx   │    │  Docker │    │  RDS    │
    │ :80     │    │ Network │    │ :5432   │
    └─────────┘    └────┬────┘    └─────────┘
                        │
         ┌──────────────┼──────────────┐
         │              │              │
    ┌────▼────┐    ┌───▼────┐    ┌───▼────┐
    │  User   │    │ Search │    │ Sync   │
    │ Service │    │Service │    │Service │
    │  :3000  │    │ :3001  │    │ :3004  │
    └─────────┘    └────────┘    └────────┘
         │              │              │
    ┌────▼────┐    ┌───▼────┐    ┌───▼────────┐
    │ Metric  │    │Budget  │    │Enrichment  │
    │ Service │    │Profiling│   │  Service   │
    │  :3002  │    │ :3006  │    │   :3005    │
    └─────────┘    └────────┘    └────────────┘
         │
    ┌────▼──────────┐
    │ Conversation  │
    │  Service V3   │
    │    :3008      │
    └───────────────┘

Informations clés

RessourceValeurDescription
Instance EC2i-0011b978b7cea66dcInstance principale hébergeant les services Docker
IP Publique63.35.52.216IP publique fixe (Elastic IP)
URL Cloudflarehttps://food-dining-email-riders.trycloudflare.comURL publique gratuite (temporaire, phase dev)
Région AWSeu-west-1Europe (Irlande)
Zoneeu-west-1aZone de disponibilité
Security Groupsg-0aa65b430c3e93badGroupe de sécurité harena-allinone-sg-dev
IAM Roleharena-ec2-profile-devProfil IAM avec accès SSM
Base de données63.35.52.216:5432PostgreSQL (RDS ou sur EC2)
Redis63.35.52.216:6379Cache Redis

Note : L'URL Cloudflare est active uniquement quand le tunnel cloudflared est en cours d'exécution sur l'instance EC2.


Accès à l'infrastructure

Accès public via Cloudflare Tunnel

URL publique : https://food-dining-email-riders.trycloudflare.com

Cloudflare Tunnel expose Harena sur internet de manière sécurisée (SSL automatique, protection DDoS) sans ouvrir de ports supplémentaires.

Vérifier si le tunnel est actif :

aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["ps aux | grep cloudflared | grep -v grep"]' \
    --region eu-west-1

Voir l'URL actuelle du tunnel :

aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["cat /home/ec2-user/cloudflare-tunnel.log | grep trycloudflare.com | tail -1"]' \
    --region eu-west-1

Redémarrer le tunnel (nouvelle URL générée) :

aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["pkill cloudflared","nohup cloudflared tunnel --url http://localhost:80 > /home/ec2-user/cloudflare-tunnel.log 2>&1 &","sleep 5","cat /home/ec2-user/cloudflare-tunnel.log | grep trycloudflare.com"]' \
    --region eu-west-1

Arrêter le tunnel :

aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["pkill cloudflared"]' \
    --region eu-west-1

Note : L'URL générée change à chaque redémarrage du tunnel. Pour une URL fixe, il faudrait acheter un domaine et configurer un tunnel nommé Cloudflare.

Prérequis

  1. AWS CLI installé et configuré
aws --version
aws configure
  1. Clé SSH : ~/.ssh/harena-deploy-key.pem
chmod 400 ~/.ssh/harena-deploy-key.pem
  1. Droits AWS : Accès au compte AWS ID 204093577928

Méthodes d'accès

1. Via AWS Systems Manager (SSM) - RECOMMANDÉ

Avantages : Pas besoin de clé SSH, logs centralisés, plus sécurisé

# Envoyer une commande
aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["docker ps"]' \
    --region eu-west-1 \
    --output json

# Récupérer le résultat (remplacer COMMAND_ID)
aws ssm get-command-invocation \
    --command-id <COMMAND_ID> \
    --instance-id i-0011b978b7cea66dc \
    --region eu-west-1 \
    --query 'StandardOutputContent' \
    --output text

Script d'aide : Voir aws-ssm-helper.sh (à créer si nécessaire)

2. Via SSH (Fallback)

ssh -i ~/.ssh/harena-deploy-key.pem ec2-user@63.35.52.216

Note : L'agent SSM doit être installé et configuré sur l'instance.

Commandes utiles

# Vérifier l'état de l'instance
aws ec2 describe-instances \
    --instance-ids i-0011b978b7cea66dc \
    --region eu-west-1 \
    --query 'Reservations[0].Instances[0].[State.Name,PublicIpAddress]'

# Vérifier l'agent SSM
aws ssm describe-instance-information \
    --filters "Key=InstanceIds,Values=i-0011b978b7cea66dc" \
    --region eu-west-1

# Lister les security groups
aws ec2 describe-security-groups \
    --group-ids sg-0aa65b430c3e93bad \
    --region eu-west-1 \
    --query 'SecurityGroups[0].IpPermissions[*].[IpProtocol,FromPort,ToPort]'

Configuration des services

Services déployés

ServicePortConteneur DockerStatus
Nginx80harena_nginx
User Service3000harena_user_service
Search Service3001harena_search_service
Metric Service3002harena_metric_service
Sync Service3004harena_sync_service
Enrichment Service3005harena_enrichment_service
Budget Profiling3006harena_budget_profiling_service
Conversation V33008harena_conversation_v3
Grafana4000harena_grafana
Prometheus9090harena_prometheus

Variables d'environnement (.env sur AWS)

Localisation : /home/ec2-user/harena/.env

Variables critiques :

# Base de données PostgreSQL
DATABASE_URL=postgresql://harena_admin:HaReNa2024SecureDbPassword123@63.35.52.216:5432/harena

# Redis
REDIS_URL=redis://:HaReNa2024-Redis-Auth-Token-Secure-Key-123456@63.35.52.216:6379/0

# Bridge API (sync bancaire)
BRIDGE_CLIENT_ID=<secret>
BRIDGE_CLIENT_SECRET=<secret>
BRIDGE_API_URL=https://api.bridgeapi.io
BRIDGE_API_VERSION=2021-06-01
BRIDGE_WEBHOOK_SECRET=<secret>

# Elasticsearch (enrichment)
ELASTICSEARCH_URL=http://elasticsearch:9200

# OpenAI / LLM
OPENAI_API_KEY=<secret>
LLM_MODEL=gpt-4o-mini
LLM_RESPONSE_MODEL=gpt-4o

# DeepSeek (alternative LLM)
DEEPSEEK_API_KEY=<secret>
DEEPSEEK_API_URL=https://api.deepseek.com

⚠️ IMPORTANT :

  • Le DATABASE_URL doit utiliser le nom de conteneur Docker harena_postgres (pas l'IP 63.35.52.216)
  • Les services backend doivent communiquer via le réseau Docker interne, pas via l'IP publique
  • Vérifier que le .env est à jour après chaque déploiement

Ports ouverts dans le Security Group

# Vérifier les ports ouverts
aws ec2 describe-security-groups \
    --group-ids sg-0aa65b430c3e93bad \
    --region eu-west-1 \
    --query 'SecurityGroups[0].IpPermissions[*].[FromPort,ToPort,IpRanges[0].Description]' \
    --output table

Ports actuellement ouverts :

  • 22 (SSH)
  • 80 (HTTP - Nginx)
  • 443 (HTTPS - non configuré pour l'instant)
  • 3000 (User Service)
  • 3001 (Search Service)
  • 3002 (Metric Service)
  • 3004 (Sync Service)
  • 3005 (Enrichment Service)
  • 3006 (Budget Profiling)
  • 3008 (Conversation V3)
  • 5432 (PostgreSQL)
  • 6379 (Redis)

Pour ajouter un port :

# Exemple : Ouvrir le port 8080
aws ec2 authorize-security-group-ingress \
    --group-id sg-0aa65b430c3e93bad \
    --protocol tcp \
    --port 8080 \
    --cidr 0.0.0.0/0 \
    --region eu-west-1 \
    --description "Description du service"

Procédures de déploiement

Déploiement manuel via SSM

1. Mettre à jour le code sur AWS

# Via SSM
COMMAND_ID=$(aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["cd /home/ec2-user/harena && git pull origin main"]' \
    --region eu-west-1 \
    --output text --query 'Command.CommandId')

# Attendre et récupérer le résultat
sleep 5
aws ssm get-command-invocation \
    --command-id $COMMAND_ID \
    --instance-id i-0011b978b7cea66dc \
    --region eu-west-1 \
    --query 'StandardOutputContent' --output text

2. Reconstruire et redémarrer les services

# Rebuild d'un service spécifique (ex: sync_service)
COMMAND_ID=$(aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["cd /home/ec2-user/harena && docker-compose build sync_service && docker-compose up -d --force-recreate --no-deps sync_service"]' \
    --region eu-west-1 \
    --output text --query 'Command.CommandId')

sleep 10
aws ssm get-command-invocation \
    --command-id $COMMAND_ID \
    --instance-id i-0011b978b7cea66dc \
    --region eu-west-1 \
    --query 'StandardOutputContent' --output text

3. Vérifier le déploiement

# Vérifier que tous les conteneurs sont UP
COMMAND_ID=$(aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["docker ps --format \"table {{.Names}}\t{{.Status}}\t{{.Ports}}\""]' \
    --region eu-west-1 \
    --output text --query 'Command.CommandId')

sleep 3
aws ssm get-command-invocation \
    --command-id $COMMAND_ID \
    --instance-id i-0011b978b7cea66dc \
    --region eu-west-1 \
    --query 'StandardOutputContent' --output text

Déploiement du frontend

Script existant : update-frontend-aws.sh

#!/bin/bash
# Déployer le frontend sur AWS

# 1. Build local
cd harena_front
npm run build

# 2. Transférer vers AWS via SCP
scp -r -i ~/.ssh/harena-deploy-key.pem dist/* ec2-user@63.35.52.216:/home/ec2-user/harena/harena_front/dist/

# 3. Redémarrer nginx
aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["docker-compose restart nginx"]' \
    --region eu-west-1

Rollback rapide

En cas de problème après déploiement :

# 1. Revenir à la version précédente du code
aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["cd /home/ec2-user/harena && git reset --hard HEAD~1 && docker-compose up -d --force-recreate"]' \
    --region eu-west-1

# 2. Vérifier les logs
aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["docker logs <service_name> --tail 50"]' \
    --region eu-west-1

Monitoring et logs

Grafana

URL : http://63.35.52.216:4000 Credentials : Voir .env (GRAFANA_ADMIN_USER / GRAFANA_ADMIN_PASSWORD)

Dashboards disponibles :

  • Harena System Overview (monitoring/grafana/dashboards/json/harena-overview.json)

Prometheus

URL : http://63.35.52.216:9090

Métriques collectées :

  • Container metrics (CPU, RAM, Network)
  • Node metrics (system-level)
  • Application metrics (via exporters)

Consulter les logs

Via SSM (depuis votre machine)

# Logs d'un service spécifique
aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["docker logs harena_sync_service --tail 100"]' \
    --region eu-west-1

# Logs en temps réel (via SSH recommandé)
ssh -i ~/.ssh/harena-deploy-key.pem ec2-user@63.35.52.216
docker logs -f harena_sync_service

Via SSH

# Se connecter
ssh -i ~/.ssh/harena-deploy-key.pem ec2-user@63.35.52.216

# Logs de tous les services
cd /home/ec2-user/harena
docker-compose logs --tail=50

# Logs d'un service spécifique
docker logs harena_user_service --tail 100 -f

# Filtrer les erreurs
docker logs harena_sync_service 2>&1 | grep -i error

Health checks

Tous les services exposent un endpoint /health :

# User Service
curl http://63.35.52.216:3000/health

# Sync Service
curl http://63.35.52.216:3004/health

# Conversation V3
curl http://63.35.52.216:3008/health

Résolution de problèmes

Service ne démarre pas

1. Vérifier les logs

docker logs harena_<service_name> --tail 50

2. Vérifier les variables d'environnement

docker exec harena_<service_name> env | grep DATABASE_URL

3. Vérifier la connexion à la base de données

# Depuis l'instance EC2
psql postgresql://harena_admin:PASSWORD@63.35.52.216:5432/harena -c "SELECT 1;"

Problème de base de données

Symptôme : Erreur could not translate host name "harena-postgres"

Cause : Le .env sur AWS utilise le nom Docker local au lieu de l'IP

Solution :

# Corriger le DATABASE_URL
aws ssm send-command \
    --instance-ids i-0011b978b7cea66dc \
    --document-name "AWS-RunShellScript" \
    --parameters 'commands=["cd /home/ec2-user/harena && sed -i \"s/@harena-postgres:/@63.35.52.216:/g\" .env && docker-compose up -d --force-recreate"]' \
    --region eu-west-1

Service timeout ou lent

1. Vérifier les ressources

docker stats

2. Vérifier la configuration des pools de connexions

  • Voir db_service/session.py : pool_size=20, max_overflow=30

3. Redémarrer le service

docker-compose restart <service_name>

Webhook Bridge ne fonctionne pas

URL attendue : http://63.35.52.216:3004/webhooks/bridge

⚠️ Bridge exige HTTPS - Actuellement non configuré

Options :

  1. Configurer Let's Encrypt + nginx (nécessite un nom de domaine)
  2. Utiliser CloudFlare Tunnel (gratuit)
  3. Utiliser ngrok en local pour le développement

Tester le webhook :

curl -X POST http://63.35.52.216:3004/webhooks/bridge \
  -H "Content-Type: application/json" \
  -H "BridgeApi-Signature: test" \
  -d '{"type": "test", "content": {}}'

Sécurité

Credentials et secrets

⚠️ NE JAMAIS COMMITER :

  • .env (local et production)
  • Clés SSH
  • Tokens d'API

Bonnes pratiques :

  1. Utiliser AWS Secrets Manager pour les secrets sensibles
  2. Rotation régulière des mots de passe
  3. Principe du moindre privilège pour les IAM roles

Accès SSH

Désactivé pour l'instant - Utiliser SSM en priorité

Si SSH nécessaire :

ssh -i ~/.ssh/harena-deploy-key.pem ec2-user@63.35.52.216

Permissions de la clé :

chmod 400 ~/.ssh/harena-deploy-key.pem

Firewall (Security Group)

Règles actuelles : Tous les ports ouverts à 0.0.0.0/0 (internet)

⚠️ Recommandation : Restreindre l'accès aux ports sensibles :

  • PostgreSQL (5432) : Accès limité à l'IP de l'instance uniquement
  • Redis (6379) : Accès limité à l'IP de l'instance uniquement
  • Services backend (3000-3008) : Accès via nginx uniquement (fermer les ports publics)

Exemple de restriction :

# Supprimer la règle actuelle
aws ec2 revoke-security-group-ingress \
    --group-id sg-0aa65b430c3e93bad \
    --protocol tcp --port 5432 --cidr 0.0.0.0/0 \
    --region eu-west-1

# Ajouter une règle restreinte
aws ec2 authorize-security-group-ingress \
    --group-id sg-0aa65b430c3e93bad \
    --protocol tcp --port 5432 \
    --source-group sg-0aa65b430c3e93bad \
    --region eu-west-1

Backup

⚠️ À CONFIGURER :

  1. Snapshots EC2 : Sauvegardes régulières de l'instance
aws ec2 create-snapshot \
    --volume-id <volume-id> \
    --description "Harena backup $(date +%Y-%m-%d)" \
    --region eu-west-1
  1. Backup PostgreSQL :
# Via pg_dump sur l'instance
ssh ec2-user@63.35.52.216
pg_dump postgresql://harena_admin:PASSWORD@localhost:5432/harena > backup_$(date +%Y%m%d).sql

# Télécharger le backup
scp -i ~/.ssh/harena-deploy-key.pem \
    ec2-user@63.35.52.216:/home/ec2-user/backup_*.sql \
    ./backups/
  1. RDS Automated Backups : Si PostgreSQL est sur RDS (à vérifier)

Checklist de déploiement

Avant de déployer

  • Tests locaux réussis
  • Code commité et poussé sur main
  • .env à jour sur AWS
  • Backup de la base de données effectué
  • Grafana/Prometheus fonctionnels

Déploiement

  • Pull du code sur AWS
  • Rebuild des images Docker modifiées
  • Redémarrage des services concernés
  • Vérification des logs (pas d'erreurs)
  • Tests des endpoints critiques
  • Vérification du dashboard Grafana

Après déploiement

  • Monitoring actif (Grafana)
  • Webhooks Bridge testés (si applicable)
  • Notifier l'équipe du déploiement
  • Documenter les changements

Contacts et ressources

Documentation technique

  • Docker Compose : docker-compose.yml
  • Nginx : nginx/conf.d/harena.conf
  • Monitoring : monitoring/
  • Scripts : Voir *.sh à la racine

Ressources AWS

Support


Changelog Infrastructure

2025-11-06

  • ✅ Installation de Cloudflare Tunnel (cloudflared) sur EC2 (ARM64)
    • URL publique : https://food-dining-email-riders.trycloudflare.com
    • SSL automatique, protection DDoS gratuite
    • Tunnel gratuit temporaire pour phase de développement
    • Commandes de gestion documentées
  • ✅ Documentation complète de l'accès via Cloudflare Tunnel

2025-10-30

  • ✅ Correction critique du DATABASE_URL dans .env sur AWS (63.35.52.216harena_postgres)
    • Problème : Les services essayaient de se connecter via l'IP publique au lieu du réseau Docker
    • Solution : Utilisation du nom de conteneur Docker harena_postgres pour connexion interne
    • Impact : Tous les services backend maintenant "healthy" (user, search, metric, sync, enrichment, budget_profiling)
  • ✅ Correction de la configuration Loki (arrêt des crashs en boucle)
    • Migration de boltdb-shipper (v11) vers tsdb (v13)
    • Suppression des champs obsolètes (shared_store, max_look_back_period, table_manager)
    • Compatible avec Loki 2.9+
  • ✅ Ajout du endpoint /health au search_service
    • Corrige le statut "unhealthy" du healthcheck Docker
  • ✅ Redéploiement complet de tous les services backend avec la nouvelle configuration

2025-10-29

  • ✅ Première tentative de correction du DATABASE_URL (incorrecte)
  • ✅ Redémarrage de sync_service et enrichment_service
  • ✅ Validation des webhooks Bridge (endpoint fonctionnel mais HTTPS requis)
  • ✅ Documentation complète de l'infrastructure créée

À faire

  • Configurer HTTPS avec Let's Encrypt ou CloudFlare Tunnel
  • Restreindre les security groups (principe du moindre privilège)
  • Mettre en place des backups automatisés
  • Configurer des alertes Grafana
  • Elastic IP pour l'instance EC2
  • Domain name + certificat SSL

Document maintenu par : Équipe Harena Dernière mise à jour : 2025-11-06

Related Documents