Aller au contenu

EPIDOCS API — Runbook (site down)

Procédure d'urgence

Ce document décrit la marche à suivre si EPIDOCS API est inaccessible en production.

Aide-mémoire

Élément Valeur
VPS ssh root@VPS_IP
Répertoire projet /root/projects/mydocs/epidocs-api
Port hôte 7010
Port conteneur 8000
Conteneur API epidocs_api
Conteneur DB epidocs_db
Image ghcr.io/epitechafrik/epidocs-api:deploy
Volume DB epidocs-api_postgres_data (externe)
Media ./media (bind mount)
URL prod https://api.mydocs.epitools.bj

Étape 1 — Diagnostic initial

ssh root@VPS_IP
cd /root/projects/mydocs/epidocs-api

# État des conteneurs
docker compose ps

# Test rapide
curl -o /dev/null -s -w "%{http_code}" http://127.0.0.1:7010/
Résultat Signification Aller à
200 API fonctionne, problème Nginx/DNS Étape 2a
503 Mode maintenance activé Étape 2b
Pas de réponse Conteneur down Étape 3

Cas particulier : l'API répond (200) mais PERSONNE ne peut se connecter

Ce n'est pas couvert par les étapes ci-dessous (elles supposent un problème réseau/conteneur, pas d'auth). Si /auth/callback renvoie 401 "NON AUTORISÉ" pour tout le monde juste après une connexion Microsoft réussie, suspecter en premier un AZURE_CLIENT_SECRET expiré — voir Erreurs courantes → AZURE_CLIENT_SECRET expiré pour le diagnostic et la procédure de rotation.

Étape 2a — L'API répond mais le site est inaccessible

Le problème est au niveau Nginx ou DNS.

# Vérifier Nginx
docker ps | grep nginx
docker logs nginx-proxy --tail 20

# Vérifier la config Nginx pour epidocs
docker exec nginx-proxy cat /etc/nginx/conf.d/epidocs.conf 2>/dev/null || echo "Config introuvable"

# Vérifier le DNS
dig api.mydocs.epitools.bj

Étape 2b — Mode maintenance activé par erreur

docker compose exec web python manage.py shell -c "
from apps.user.models import SystemStatus
s = SystemStatus.objects.first()
if s:
    s.is_maintenance = False
    s.scheduled_start = None
    s.scheduled_end = None
    s.save()
    print('Mode maintenance désactivé')
else:
    print('Aucun SystemStatus trouvé')
"

Étape 3 — Conteneur down

# Voir les conteneurs arrêtés
docker compose ps -a

# Derniers logs avant le crash
docker compose logs web --tail 50
docker compose logs db --tail 50

3a — Redémarrer les conteneurs

docker compose up -d

Attendre 30 secondes puis vérifier :

docker compose ps
curl -o /dev/null -s -w "%{http_code}" http://127.0.0.1:7010/

3b — Si la DB ne démarre pas

# Vérifier le volume
docker volume inspect epidocs-api_postgres_data

# Si le volume n'existe pas
docker volume create epidocs-api_postgres_data

# Relancer
docker compose up -d db
docker compose logs -f db
# Attendre "database system is ready to accept connections"

docker compose up -d web

3c — Si l'API ne démarre pas (erreur de migration)

# Lire les logs d'erreur
docker compose logs web --tail 50

# Lancer les migrations manuellement
docker compose exec web python manage.py migrate

# Si une migration est corrompue, identifier laquelle
docker compose exec web python manage.py showmigrations | grep "\[ \]"

3d — Si l'image Docker est corrompue

# Re-pull l'image
docker compose pull web

# Relancer
docker compose up -d web

Étape 3e — La pipeline GitHub Actions est bloquée (facturation) et un fix urgent doit sortir

Contexte : un correctif urgent doit être déployé, mais la pipeline GitHub Actions ne démarre même pas (job en échec immédiat avec "recent account payments have failed or your spending limit needs to be increased" — voir troubleshooting.md). C'est un blocage de facturation au niveau de l'organisation, pas un problème de code — la résolution normale (un owner/admin d'organisation corrige la facturation dans GitHub Settings) peut prendre du temps. Procédure de contournement : construire et déployer l'image directement sur le VPS, sans passer par GHCR.

# 1. Depuis un checkout local à jour, sur le commit à déployer
git archive --format=tar.gz -o /tmp/epidocs-deploy.tar.gz <commit_ou_branche>

# 2. Envoyer l'archive sur le VPS
scp /tmp/epidocs-deploy.tar.gz root@VPS_IP:/tmp/

# 3. Sur le VPS : extraire et builder l'image en local
ssh root@VPS_IP
mkdir -p /tmp/epidocs-build && tar xzf /tmp/epidocs-deploy.tar.gz -C /tmp/epidocs-build
cd /tmp/epidocs-build

# Builder avec EXACTEMENT le tag utilisé par docker-compose.prod.yml —
# sinon `docker compose up -d` re-pull l'ancienne image depuis GHCR.
docker build -t ghcr.io/epitechafrik/epidocs-api:deploy .

# 4. Basculer vers le répertoire de déploiement et relancer, SANS docker compose pull
# (l'image est déjà locale — un pull écraserait le build qu'on vient de faire)
cd /root/projects/mydocs/epidocs-api
docker stop epidocs_api 2>/dev/null || true
docker rm epidocs_api 2>/dev/null || true
docker compose up -d

# 5. Vérifier
docker compose ps
curl -o /dev/null -s -w "%{http_code}" http://127.0.0.1:7010/

Une fois la facturation GitHub Actions débloquée, le prochain push normal sur deploy re-synchronise l'image sur GHCR — pas d'action de nettoyage particulière à faire côté VPS.

Étape 4 — Vérification post-recovery

# 1. API répond
curl -s http://127.0.0.1:7010/ | head -5

# 2. Base de données accessible
docker compose exec web python manage.py shell -c "
from django.db import connection
cursor = connection.cursor()
cursor.execute('SELECT COUNT(*) FROM student_student')
print(f'Étudiants: {cursor.fetchone()[0]}')
"

# 3. Healthcheck Docker
docker compose ps
# Les deux conteneurs doivent être (healthy)

# 4. Génération de document fonctionne (vérifier les templates)
docker compose exec web ls -la /epidocs/media/modeles/

Étape 5 — Communication

  1. Si le service a été indisponible plus de 5 minutes, informer les utilisateurs via le système d'annonces :
docker compose exec web python manage.py shell -c "
from apps.user.models import Announcement, User
admin = User.objects.filter(is_superuser=True).first()
Announcement.objects.create(
    title='Service rétabli',
    message='Le service EPIDOCS a été temporairement indisponible. Tout est rétabli.',
    target='all',
    priority='info',
    is_active=True,
    created_by=admin
)
print('Annonce créée')
"
  1. Documenter l'incident : cause, durée, résolution

Contacts

Rôle Contact
Développeur & Mainteneur YemalinModeste — yemalin1.agbangla@epitech.eu
Repo EpitechAfrik/epidocs-api