feat(minio) — exposer l'API S3 en HTTPS public (s3.arcodange.fr) + CORS de la PWA #20

Merged
arcodange merged 1 commits from arcodange/minio-public-fr into main 2026-07-26 07:34:49 +02:00
Owner

Débloque kadans-api#23 (URL présignées MinIO), qui est lui-même le maillon de « je veux synchroniser mes vidéos entre mes appareils ».

Pourquoi c'est nécessaire, et pas un confort

La PWA est servie en https://kadans.arcodange.fr et téléverse directement vers MinIO. Deux faits du navigateur rendent le .lab inutilisable :

  1. Contenu mixte — une page https ne peut pas émettre de requête vers http://. L'ingress existant est en entrypoint web, sans TLS.
  2. .lab n'est pas résolvable hors du LAN — la synchronisation ne marcherait qu'à la maison, ce qui vide de son sens « retrouver mes vidéos sur mon autre appareil ».

Même motif que grafana/templates/ingress-public.yaml, déjà en place : entrypoint web, TLS terminé par le tunnel Cloudflare (wildcard *.arcodange.fr), middleware crowdsec. Le .lab interne reste inchangé.

Deux décisions qui méritent d'être dites

Pas de basic-auth, contrairement à kadans-public. Une requête S3 porte sa propre signature (SigV4) ; un défi HTTP Basic casserait le PUT présigné, auquel le navigateur n'a aucun moyen de répondre. L'autorisation vient de l'URL signée et de sa durée de vie courte — 15 min pour déposer, 1 h pour lire.

CORS sur les origines exactes, jamais *. Le téléversement est inter-origines, donc précédé d'un préflight OPTIONS : sans cette liste, le PUT ne part même pas. Et * rendrait une URL présignée qui fuiterait rejouable depuis n'importe quel site.

⚠ Un point signalé, non mesuré

Le trafic public passe par le tunnel Cloudflare, dont les offres gratuites plafonnent la taille du corps d'une requête (de l'ordre de 100 Mo). Je ne l'ai pas mesuré — il faut un vrai téléversement pour le savoir, et je ne voulais pas l'affirmer sans preuve.

Ce qu'on sait en revanche rend le sujet peu urgent : sur le corpus réel (707 vidéos, ~2 ans), la durée moyenne est de 53 secondes et deux vidéos seulement dépassent 5 minutes. Au palier « travail » de l'ADR-018 (360p ≈ 3,4 Mo/min), 100 Mo valent ~29 minutes de cours. Si la limite se confirme, le plafond de 200 Mio annoncé côté API mérite d'être ramené sous celle du tunnel : mieux vaut refuser tôt, avec une phrase claire, qu'échouer au milieu d'un téléversement.

Reste à faire, hors de cette PR

Le compte de service MinIO (mc admin policy create borné à kadans-videos/*, puis vault kv put kvv2/kadans/minio …) et la bascule de stockage.enabled côté kadans-api — les commandes exactes sont dans kadans-api#23 et dans le README de ce chart.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA

Débloque **kadans-api#23** (URL présignées MinIO), qui est lui-même le maillon de « je veux synchroniser mes vidéos entre mes appareils ». ## Pourquoi c'est nécessaire, et pas un confort La PWA est servie en `https://kadans.arcodange.fr` et téléverse **directement** vers MinIO. Deux faits du navigateur rendent le `.lab` inutilisable : 1. **Contenu mixte** — une page `https` ne peut pas émettre de requête vers `http://`. L'ingress existant est en entrypoint `web`, sans TLS. 2. **`.lab` n'est pas résolvable hors du LAN** — la synchronisation ne marcherait qu'à la maison, ce qui vide de son sens « retrouver mes vidéos sur mon autre appareil ». Même motif que `grafana/templates/ingress-public.yaml`, déjà en place : entrypoint `web`, TLS terminé par le tunnel Cloudflare (wildcard `*.arcodange.fr`), middleware crowdsec. **Le `.lab` interne reste inchangé.** ## Deux décisions qui méritent d'être dites **Pas de basic-auth**, contrairement à `kadans-public`. Une requête S3 porte sa **propre** signature (SigV4) ; un défi HTTP Basic casserait le PUT présigné, auquel le navigateur n'a aucun moyen de répondre. L'autorisation vient de l'URL signée et de sa durée de vie courte — 15 min pour déposer, 1 h pour lire. **CORS sur les origines exactes**, jamais `*`. Le téléversement est inter-origines, donc précédé d'un préflight `OPTIONS` : sans cette liste, le PUT ne part même pas. Et `*` rendrait une URL présignée qui fuiterait rejouable **depuis n'importe quel site**. ## ⚠ Un point signalé, non mesuré Le trafic public passe par le tunnel Cloudflare, dont les offres gratuites plafonnent la taille du corps d'une requête (de l'ordre de **100 Mo**). **Je ne l'ai pas mesuré** — il faut un vrai téléversement pour le savoir, et je ne voulais pas l'affirmer sans preuve. Ce qu'on sait en revanche rend le sujet peu urgent : sur le corpus réel (707 vidéos, ~2 ans), la durée **moyenne est de 53 secondes** et **deux vidéos seulement dépassent 5 minutes**. Au palier « travail » de l'ADR-018 (360p ≈ 3,4 Mo/min), 100 Mo valent ~29 minutes de cours. Si la limite se confirme, le plafond de 200 Mio annoncé côté API mérite d'être ramené **sous** celle du tunnel : mieux vaut refuser tôt, avec une phrase claire, qu'échouer au milieu d'un téléversement. ## Reste à faire, hors de cette PR Le compte de service MinIO (`mc admin policy create` borné à `kadans-videos/*`, puis `vault kv put kvv2/kadans/minio …`) et la bascule de `stockage.enabled` côté kadans-api — les commandes exactes sont dans kadans-api#23 et dans le README de ce chart. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA
arcodange added 1 commit 2026-07-26 01:57:00 +02:00
feat(minio) — exposer l'API S3 en HTTPS public (s3.arcodange.fr) + CORS de la PWA
Helm Charts / Detect changed charts (push) Successful in 1m6s
Helm Charts / Detect changed charts (pull_request) Successful in 1m5s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
1490f4c514
Sans ça, la synchronisation des vidéos ne peut pas marcher, et ce sont des faits
du navigateur : une page servie en https ne peut pas émettre de requête vers
http:// (contenu mixte), et `.lab` n'est pas résolvable hors du LAN. L'ingress
existant est en entrypoint `web` sans TLS, sur un domaine interne — donc
inutilisable depuis kadans.arcodange.fr, en déplacement COMME à la maison.

Même motif que grafana/templates/ingress-public.yaml : entrypoint `web`, TLS
terminé par le tunnel Cloudflare (wildcard *.arcodange.fr), middleware crowdsec.
Le `.lab` interne reste inchangé.

PAS de basic-auth, contrairement à kadans-public : une requête S3 porte sa propre
signature (SigV4), et un défi HTTP Basic casserait le PUT présigné auquel le
navigateur ne peut pas répondre. L'autorisation vient de l'URL signée et de sa
durée de vie courte.

CORS déclaré sur les origines EXACTES de la PWA (.fr et .lab), jamais « * » :
une URL présignée qui fuiterait serait sinon rejouable depuis n'importe quel
site. Sans cette liste, le préflight OPTIONS échoue et le PUT ne part même pas.

⚠ Signalé, NON mesuré : le tunnel Cloudflare plafonne probablement le corps
d'une requête (~100 Mo sur les offres gratuites). À éprouver avec un vrai
téléversement. Contexte utile : sur le corpus réel du fondateur (707 vidéos,
~2 ans), la durée MOYENNE est de 53 s et deux vidéos seulement dépassent 5 min —
au palier « travail » de l'ADR-018, 100 Mo valent ~29 min de cours.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA
arcodange merged commit f49a79e393 into main 2026-07-26 07:34:49 +02:00
arcodange deleted branch arcodange/minio-public-fr 2026-07-26 07:34:50 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/tools#20