# Architecture — Arkindex sur Coolify ## Vue d'ensemble ``` Internet (navigateur) │ HTTPS (Let's Encrypt, HTTP-01) ▼ ┌─────────────────────────────┐ │ coolify-proxy (Traefik v3) │ :80/:443 │ routage par labels Docker │ └───────┬───────────┬──────────┘ ark.nak0x.dev │ │ s3.nak0x… / iiif.nak0x… (split par chemin) │ │ ┌───────────────┬────────┘ └──────────┬──────────────┐ ▼ ▼ ▼ ▼ ark-front ark-backend ark-garage ark-cantaloupe (SPA nginx) (API gunicorn) (S3) (IIIF) │ │ \ ▲ │ │ │ \ hairpin S3 │ http interne│ http interne │ │ └──► https://s3. ───┘ :3900 │ :3900 │ ▼ │ │ ark-worker (RQ/Ponos) │ │ │ ▼ │ ┌──────┴──────┬──────────┐ (lit les images ▼ ▼ ▼ ▼ dans les buckets) [réseau "ark"] ark-database ark-redis ark-solr (Postgres) (RQ+cache) (recherche) ``` ## Réseaux Docker - **`ark`** (interne) : tous les services ; communication par **nom de service** (`ark-database`, `ark-redis`, …). Ces noms sont **uniques** exprès (cf. Troubleshooting P4). - **`coolify`** (externe, partagé) : uniquement `ark-garage`, `ark-cantaloupe`, `ark-backend`, `ark-front`, `ark-worker` — pour être joignables par le proxy Traefik et pour le hairpin S3. - En mode Coolify, un 3ᵉ réseau par ressource (``) est ajouté automatiquement. ## TLS & hostnames (contrainte centrale) Coolify n'a que le challenge **HTTP-01** → **pas de certificat wildcard**. Or Arkindex sert S3 et IIIF en **virtual-hosted** (`.s3.`, `.iiif.`). Comme l'ensemble des hostnames est **fini et connu**, on les énumère dans les règles `Host(...)` Traefik → Traefik émet un certificat HTTP-01 par hostname. Le **wildcard DNS** `*.nak0x.dev` (résolution, pas TLS) fait pointer tous ces noms vers le serveur, donc **zéro entrée DNS à créer**. Hostnames servis : - `ark.` — front (catch-all, priorité 1) + backend (`/api`,`/api-docs`,`/admin`,`/rq`,`/static`, priorité 100) - `s3.` + `.s3.` × 9 buckets — Garage - `iiif.`, `uploads.iiif.`, `ingest.iiif.` — Cantaloupe ## Stockage S3 (Garage) - Le backend utilise boto3 avec `addressing_style="auto"` (codé en dur) → **virtual-hosted** (`.s3.`). D'où l'énumération des sous-domaines de bucket + `root_domain` dans `garage.toml` (Garage mappe sous-domaine → bucket). - **Hairpin** : le backend doit joindre `https://s3.` (les URLs présignées données au navigateur utilisent ce host) : requête → IP publique → `coolify-proxy` (TLS valide) → Garage. Vérifié fonctionnel ici. - Cantaloupe, lui, parle à Garage **en interne** (`http://ark-garage:3900`, sans TLS). - 9 buckets : `uploads, ingest, export, iiif-cache, ponos-artifacts, ponos-logs, staging, thumbnails, training`. - Clé S3 : importée dans Garage (admin API/CLI) = `GK_ID`/`GK_SECRET` de `.secrets.env`. ## IIIF (Cantaloupe) - Image custom Teklia : `ScriptLookupStrategy` + `S3Source.top_domain = iiif.` → le bucket est déduit du sous-domaine (`uploads.iiif.` → bucket `uploads`). - 2 `ImageServer` en base : `12345` (uploads) et `67890` (ingest), URLs `https://…iiif./iiif/2`. ## Recherche (Solr) - SolrCloud (`solr -f -cloud`). Les collections sont créées **par corpus** (`project-`) à la volée lors de l'indexation (`arkindex reindex`). Rien à pré-créer. ## Images (versions) `backend/frontend 1.12.2`, `tasks 0.6.2`, `cantaloupe 5.0.7`, `postgis 17-3.5`, `solr 9`, `garage v2.1.0`, `redis alpine`. Toutes **publiques** (pull anonyme). ## Bootstrap : pourquoi on ne l'utilise pas `arkindex bootstrap` est **dev-only** : il refuse si `DEBUG=False` et code les URLs en `*.ark.localhost`. On réplique ses 3 actions avec le vrai domaine (`scripts/20` + `scripts/30`).