Picarones / docs /operations /deployment-institutional.md
Claude
chore: finir le retrait execution_mode (audit du commit precedent)
a23e336 unverified

Déploiement institutionnel — Picarones

Ce guide cible les DSI de bibliothèques nationales et services d'archives qui souhaitent héberger Picarones sur leur propre infrastructure (intranet, derrière SSO, avec stockage centralisé) plutôt que sur HuggingFace Space public.

Pour le déploiement HuggingFace Space ou un usage local rapide, voir how-to/install.md.

Pré-requis

Système

  • Linux x86_64 ou ARM64 (Debian 12+, RHEL 9+, Ubuntu 22.04+ LTS, Rocky 9+).
  • Python 3.11 ou 3.12 (3.13 informationnel).
  • Tesseract OCR ≥ 5.3 (avec packs fra, lat, eng au minimum).
  • 3 GB RAM pour un worker FastAPI exécutant max_in_flight=4 documents en parallèle dans le ThreadPool du CorpusRunner (profil mémoire dominé par Pillow + jiwer + les modèles OCR locaux chargés une fois par instance).
  • 5 GB de disque pour l'application + 50 GB recommandés pour les uploads et la base SQLite des jobs.

Réseau

  • Sortant : optionnel (HF Datasets / Gallica / HTR-United uniquement si vous activez les imports distants).
  • Entrant : un seul port HTTP (défaut 7860) à exposer derrière votre reverse proxy (Nginx, Apache, Traefik).

Optionnel

  • PostgreSQL 14+ (en remplacement de SQLite si vous montez en multi-instance — voir § Architecture cible).
  • Reverse proxy SSO (Shibboleth, CAS, OIDC, OAuth2 proxy).
  • Stack observabilité (Prometheus + Grafana, ou ELK/Loki).

Architecture cible

Mono-instance (recommandé pour < 10 utilisateurs simultanés)

[Utilisateur] → [Reverse proxy SSO] → [Picarones Docker] → [SQLite jobs.db]
                                              ↓
                                    [Volume persistant uploads/]
                                              ↓
                                    [Volume persistant reports/]

Configuration minimale, rétro-compatible avec le déploiement HuggingFace Space. Le reverse proxy ajoute l'authentification (SSO institutionnel) et la terminaison TLS.

Multi-instance (charge > 50 jobs/h)

[Utilisateur] → [Load balancer + SSO] → [Picarones × N]
                                              ↓
                                  [PostgreSQL jobs (centralisé)]
                                              ↓
                                  [Volume NFS uploads/ partagé]

Notes :

  • PostgreSQL : JobStore utilise SQLite par défaut. Pour PostgreSQL, dériver une classe PostgresJobStore qui implémente la même API (create_job, update_progress, get_job, etc.). À défaut, partager la BD SQLite via NFS ne fonctionne pas — le mode WAL exige un filesystem local.
  • Volume NFS pour uploads/ et reports/ afin que tous les workers voient les mêmes fichiers.
  • Sticky sessions sur le LB pour SSE (les progress streams doivent rester sur le même worker).

Configuration

Toutes les variables sont documentées dans .env.example. Les principales pour un déploiement institutionnel :

# Sécurité (Sprints A4 + 24)
PICARONES_PUBLIC_MODE=        # vide ou 0 = mode dev (autorise OCR cloud)
PICARONES_CSRF_REQUIRED=1     # OBLIGATOIRE derrière SSO
PICARONES_CSRF_SECRET="$(openssl rand -hex 32)"

# Restrictions
PICARONES_BROWSE_ROOTS="/var/lib/picarones/uploads:/data/corpus"
PICARONES_MAX_UPLOAD_MB=500
PICARONES_MAX_CONCURRENT_JOBS=8
PICARONES_RATE_LIMIT_PER_HOUR=0   # 0 = illimité (le SSO gère l'identité)

# Persistance
PICARONES_JOBS_DB=/var/lib/picarones/jobs.sqlite

# RGPD
PICARONES_UPLOAD_RETENTION_DAYS=7
PICARONES_LOG_IP_RETENTION_HOURS=24

Intégration SSO

Picarones n'implémente pas de mécanisme d'authentification natif — l'authentification est déléguée à votre reverse proxy. Pattern recommandé : header trusté X-Remote-User.

Nginx + Shibboleth (université, Renater)

location / {
    auth_request /shibauthorizer;
    proxy_set_header X-Remote-User $http_remote_user;
    proxy_set_header X-Remote-Groups $http_remote_groups;
    proxy_pass http://picarones-backend:7860;

    # SSE long-polling
    proxy_buffering off;
    proxy_read_timeout 24h;
}

Apache + CAS (CRU, ESR français)

<Location />
    AuthType CAS
    Require valid-user
    RequestHeader set X-Remote-User %{REMOTE_USER}s
    ProxyPass http://localhost:7860/
    ProxyPassReverse http://localhost:7860/
</Location>

Traefik + OIDC (déploiements modernes)

http:
  middlewares:
    oidc-auth:
      forwardAuth:
        address: "http://oauth2-proxy:4180/auth"
        trustForwardHeader: true
        authResponseHeaders:
          - X-Auth-Request-User
          - X-Auth-Request-Email

  routers:
    picarones:
      rule: "Host(`picarones.institution.fr`)"
      service: picarones
      tls:
        certResolver: letsencrypt
      middlewares:
        - oidc-auth

Sauvegarde et restauration

Composants à sauvegarder

Élément Chemin Stratégie
BD jobs /var/lib/picarones/jobs.sqlite* Snapshot quotidien (mode WAL : sauvegarder .sqlite, .sqlite-wal, .sqlite-shm ensemble)
Uploads /var/lib/picarones/uploads/ Snapshot hebdomadaire, rétention 30 jours (cf. RGPD)
Rapports /var/lib/picarones/reports/ Snapshot hebdomadaire, rétention illimitée (artefacts citables)
Historique longitudinal /var/lib/picarones/history.sqlite Snapshot quotidien
Configuration /etc/picarones/, .env Versionner dans le système de gestion de config (Ansible, Salt)

Restauration

# Arrêt du service
systemctl stop picarones

# Restauration BD
cp backups/jobs.sqlite-2026-05-01.sqlite /var/lib/picarones/jobs.sqlite

# Restauration uploads
rsync -av backups/uploads-2026-05-01/ /var/lib/picarones/uploads/

# Redémarrage
systemctl start picarones

# Vérification : marquage des jobs orphelins
curl http://localhost:7860/api/status

Les jobs running au moment du snapshot sont automatiquement marqués interrupted au redémarrage. Le tableau de bord sera donc cohérent.

Migration de schéma BD

Picarones évolue sa BD via une stratégie append-only — nouvelles colonnes ajoutées avec ALTER TABLE ADD COLUMN ... DEFAULT NULL. Aucune migration destructive entre versions mineures.

Pour vérifier la compatibilité d'une BD existante avec une nouvelle version :

sqlite3 jobs.sqlite "PRAGMA table_info(jobs);" > current_schema.txt
# Comparer avec docs/schema/jobs.sqlite.X.Y.Z.sql versionné

Si une migration majeure est nécessaire (changement de moteur SQL, structure incompatible), elle sera annoncée 2 versions mineures avant et un script de migration sera fourni dans scripts/migrate/.

Observabilité

Logs structurés

Picarones logge en format texte simple par défaut. Pour ELK / Loki / Datadog, ajouter un wrapper JSON :

# /etc/picarones/logging.conf
[handler_json]
class = pythonjsonlogger.jsonlogger.JsonFormatter
format = %(asctime)s %(levelname)s %(name)s %(message)s

Variable d'env : PICARONES_LOG_FORMAT=json (à implémenter dans un sprint ultérieur — actuellement les logs sont en plain text).

Métriques Prometheus (recommandé)

L'exposition Prometheus n'est pas livrée par défaut. Pour l'ajouter, monter un conteneur sidecar prometheus_client_python qui expose :

  • picarones_jobs_total{status="..."}
  • picarones_jobs_duration_seconds
  • picarones_uploads_size_bytes_total
  • picarones_engine_invocations_total{engine="..."}

Voir docs/operations/observability.md.

Healthcheck

Un endpoint /health minimal répond en < 50 ms sans toucher à la BD ni aux engines. Configurer le LB pour le cibler avec un timeout court (5 s).

Sécurité réseau

Liste blanche réseau

Si vos engines cloud sont activés (PICARONES_PUBLIC_MODE non défini), autoriser en sortie uniquement :

Domaine Usage
api.openai.com OpenAI / GPT-4o
api.anthropic.com Claude
api.mistral.ai Mistral OCR + LLM
vision.googleapis.com Google Vision
*.cognitiveservices.azure.com Azure Doc Intelligence
huggingface.co Imports HF Datasets (optionnel)
gallica.bnf.fr Imports Gallica (optionnel)

Politique de mots de passe

Les clés API LLM/OCR sont passées en variables d'environnement uniquement (jamais sur le filesystem en clair). Voir SECURITY.md.

Mise à l'échelle

Charge Configuration
< 5 jobs/h, < 5 utilisateurs Mono-instance, SQLite, 2 vCPU / 4 GB RAM
5–50 jobs/h, < 20 utilisateurs Mono-instance, SQLite, 4 vCPU / 8 GB RAM, max_in_flight=8
> 50 jobs/h Multi-instance derrière LB, PostgreSQL centralisé, NFS uploads
> 500 jobs/h Considérer un orchestrateur de tâches dédié (Celery + Redis), hors scope Picarones

Checklist déploiement

  • Tesseract installé avec packs de langues nécessaires.
  • Variables d'env configurées (mode dev/public, CSRF, browse roots).
  • Volume persistant pour uploads/, reports/, BD.
  • Reverse proxy SSO en place (CSRF activé !).
  • Backup automatique configuré (cron quotidien minimum).
  • Healthcheck /health configuré dans le LB.
  • TLS terminé au reverse proxy.
  • Liste blanche réseau si engines cloud actifs.
  • Rétention RGPD configurée (cf. data-retention-rgpd.md).
  • Audit RGAA externe planifié si prestation publique (cf. accessibility.md).
  • Issue tracking institutionnel (Mantis, JIRA, Redmine) synchronisé avec les issues GitHub si pertinent.

Aide et support


Dernière mise à jour : 2 mai 2026.