Votre propre stockage + CDN
Connectez votre propre stockage objet et votre propre CDN avec les offres API Velocity et Momentum : configuration par fournisseur, autorisations minimales, vérification de la connexion et ce qui se passe lorsque vous changez de mode.
Disponible avec : les offres API Velocity et Momentum. Non disponible avec Ignite (sans CDN), dans le sandbox développeur (les fichiers du sandbox sont temporaires), ni avec les offres WordPress (elles utilisent le CDN smallPict géré).
En bref : en mode BYO, smallPict écrit vos originaux et vos images optimisées dans votre bucket, et votre CDN les diffuse. Le stockage et le CDN sont toujours connectés ensemble : vous ne pouvez pas apporter l’un sans l’autre.
Qu’est-ce que le BYO
Velocity et Momentum proposent deux modes de diffusion. Vous en choisissez un dans Tableau de bord → CDN et stockage.
- Géré (par défaut) : smallPict conserve vos originaux dans son stockage chiffré (déplacés vers une archive longue durée après 90 jours) et diffuse les images optimisées depuis
cdn.smallpict.app. Rien à configurer. - Votre propre stockage + CDN (BYO) : vous connectez un bucket compatible S3 dans votre propre compte et un CDN dans votre propre compte. Chaque nouvelle tâche écrit l’original et le fichier optimisé dans votre bucket, et l’API renvoie des URL sur le domaine de votre CDN.
Cette règle de couplage existe parce que smallPict doit pouvoir assurer les deux moitiés de la diffusion : écrire les fichiers et retirer les copies obsolètes du cache. Un bucket sans CDN laisserait les purges de cache sans destination ; un CDN sans bucket n’aurait rien à diffuser.
Géré ou BYO
| Géré (par défaut) | Votre propre stockage + CDN | |
|---|---|---|
| Originaux | Stockage chiffré smallPict | originals/<job_id>/<file> dans votre bucket |
| Fichiers optimisés | Diffusés depuis cdn.smallpict.app | optimized/<job_id>.<ext> dans votre bucket, diffusés depuis le domaine de votre CDN |
| Quota de stockage | Velocity 50 Go, Momentum 100 Go | Non décompté. Vous payez votre fournisseur de stockage. |
| Bande passante CDN | Velocity 30 Go/mois, Momentum 200 Go/mois | Non décomptée. Vous payez votre fournisseur de CDN. |
| Transformations | Décomptées de votre offre | Décomptées de votre offre |
| Copie conservée par smallPict | Oui, tant que votre compte est actif | Aucune. Seul le téléversement temporaire de traitement, supprimé sous 24 heures. |
| Purge du cache | Automatique | Automatique, via l’API de votre CDN |
| Performances, domaine et coûts du CDN | smallPict | Vous. smallPict n’est pas responsable des performances, des domaines ni des factures de votre CDN. |
Fournisseurs pris en charge
Stockage (disponible dès aujourd’hui) : Amazon S3, Cloudflare R2, Google Cloud Storage (interopérabilité S3), Alibaba Cloud OSS, Tencent Cloud COS, DigitalOcean Spaces, SumoPod Storage, MinIO, ainsi que tout autre service compatible S3 via un point de terminaison personnalisé (par exemple Hetzner, Vultr ou Wasabi).
CDN (disponible dès aujourd’hui) : Cloudflare et Amazon CloudFront.
Prévu : Azure Blob Storage et d’autres CDN. Vous pouvez demander un accès anticipé sur la page Fournisseurs cloud.
Avant de commencer
- Vous disposez de l’offre API Velocity ou Momentum et êtes connecté en tant qu’administrateur du compte.
- Vous avez un bucket, ainsi qu’un CDN qui diffuse les fichiers de ce bucket en HTTPS.
- Le point de terminaison de stockage est joignable depuis Internet en HTTPS. Les points de terminaison privés, internes ou en HTTP simple sont refusés.
- Vous avez créé des clés restreintes pour smallPict (voir Autorisations minimales ci-dessous). N’utilisez pas les clés root ou administrateur de votre compte.
Ouvrez ensuite Tableau de bord → CDN et stockage, choisissez Votre propre stockage + CDN, remplissez les deux parties et sélectionnez Enregistrer stockage + CDN. smallPict exécute la vérification de la connexion (décrite ci-dessous) et ne vous fait passer en BYO que si elle réussit.
Guides de configuration
A. Amazon S3 + Amazon CloudFront
- Créez le bucket dans la région de votre choix, par exemple
my-imagesdansap-southeast-1. Laissez Block Public Access activé. - Créez une distribution CloudFront avec le bucket comme origine. Utilisez Origin access control (OAC) pour que CloudFront puisse lire le bucket tout en le gardant privé, et appliquez la stratégie de bucket que CloudFront vous propose.
- Facultatif : votre propre domaine. Ajoutez à la distribution un nom de domaine alternatif (par exemple
images.example.com) et un certificat, puis faites pointer un enregistrement DNS vers la distribution. - Créez un utilisateur (ou un rôle) IAM pour le stockage avec cette stratégie :
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::my-images/*" } ]}- Créez un utilisateur IAM pour CloudFront (il peut s’agir du même utilisateur) avec cette stratégie.
cloudfront:GetDistributionest facultatif ; avec cette autorisation, smallPict peut détecter le domaine de la distribution lorsque vous laissez le domaine CDN vide.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation", "cloudfront:GetDistribution" ], "Resource": "arn:aws:cloudfront::123456789012:distribution/E2QWRUHAPOMQZL" } ]}- Dans le tableau de bord :
- Fournisseur de stockage Amazon S3, bucket
my-images, régionap-southeast-1, point de terminaison vide (le point de terminaison standard de la région est utilisé), ainsi que l’access key ID et le secret du stockage. - CDN Amazon CloudFront, le Distribution ID (par exemple
E2QWRUHAPOMQZL), l’access key ID et le secret CloudFront et, si vous le souhaitez, le domaine CDN (https://images.example.com). Laissez le domaine vide pour utiliser le domaine*.cloudfront.netpropre à la distribution.
- Fournisseur de stockage Amazon S3, bucket
B. Cloudflare R2 + Cloudflare
- Créez un bucket R2, par exemple
my-images. - Connectez un domaine personnalisé au bucket (R2 → votre bucket → Settings → Custom Domains), par exemple
images.example.com, sur une zone du même compte Cloudflare. Les requêtes vers ce domaine passent par le cache Cloudflare. N’utilisez pas l’URL de développementr2.deven production. - Créez un jeton d’API R2 (R2 → Manage API tokens) avec Object Read & Write, limité à ce seul bucket. Copiez l’Access Key ID et le Secret Access Key affichés.
- Créez un jeton d’API Cloudflare (My Profile → API Tokens) pour la zone avec Zone → Cache Purge → Purge. Zone → Zone → Read est facultatif.
- Dans le tableau de bord :
- Fournisseur de stockage Cloudflare R2, bucket
my-images, point de terminaisonhttps://<account_id>.r2.cloudflarestorage.com(affiché dans les détails de l’API S3 de votre bucket), régionauto, ainsi que l’Access Key ID et le Secret Access Key R2. - CDN Cloudflare, le Zone ID (page Overview du domaine, section API), le jeton d’API et le domaine CDN
https://images.example.com.
- Fournisseur de stockage Cloudflare R2, bucket
C. Google Cloud Storage + Cloudflare
Google Cloud Storage se connecte via son API XML compatible S3, avec des clés HMAC.
- Créez le bucket, par exemple
my-images. - Créez un compte de service et attribuez-lui Storage Object User (
roles/storage.objectUser) sur ce bucket uniquement. - Créez une clé HMAC pour le compte de service : Cloud Storage → Settings → Interoperability → Create a key for a service account. Copiez l’ID d’accès et le secret.
- Rendez les fichiers optimisés lisibles par votre CDN. Cloudflare récupère les fichiers dans Cloud Storage en HTTPS, donc les objets sous
optimized/doivent être lisibles publiquement. Avec l’accès uniforme au niveau du bucket, accorder le rôle Storage Object Viewer àallUsersrend tout le bucket lisible,originals/compris. Si vos originaux doivent rester privés, placez une couche d’authentification devant (par exemple un Cloudflare Worker qui signe les requêtes vers le bucket). - Faites pointer un enregistrement DNS Cloudflare proxifié vers Cloud Storage, par exemple
images.example.com. Nommez le bucket d’après le nom d’hôte et utilisez un CNAME proxifié versc.storage.googleapis.com, ou utilisez une Origin Rule Cloudflare qui envoie les requêtes versstorage.googleapis.comavec le nom du bucket au début du chemin. - Créez un jeton d’API Cloudflare pour la zone avec Zone → Cache Purge → Purge (Zone → Zone → Read facultatif).
- Dans le tableau de bord : fournisseur de stockage Google Cloud Storage, bucket, point de terminaison
https://storage.googleapis.com, régionauto, l’ID d’accès et le secret HMAC ; CDN Cloudflare, Zone ID, jeton d’API et domaine CDNhttps://images.example.com.
D. MinIO ou tout stockage compatible S3 + Cloudflare
Cette section couvre MinIO et les services compatibles S3 tels que Hetzner, Wasabi, Vultr, SumoPod, Alibaba Cloud OSS, Tencent Cloud COS et DigitalOcean Spaces.
| Fournisseur | Choix dans le tableau de bord | Point de terminaison | Remarques |
|---|---|---|---|
| MinIO | MinIO | Votre serveur, p. ex. https://minio.example.com | Requêtes path-style activées. Le serveur doit être joignable depuis Internet en HTTPS. |
| Hetzner Object Storage | Personnalisé compatible S3 | https://<location>.your-objectstorage.com | |
| Wasabi | Personnalisé compatible S3 | https://s3.<region>.wasabisys.com | |
| Vultr Object Storage | Personnalisé compatible S3 | https://<region>.vultrobjects.com | |
| SumoPod Storage | SumoPod Storage | Dans votre tableau de bord de stockage SumoPod | Path-style activé par défaut. |
| Alibaba Cloud OSS | Alibaba Cloud OSS | https://oss-<region>.aliyuncs.com | Style virtual-hosted uniquement. |
| Tencent Cloud COS | Tencent Cloud COS | https://cos.<region>.myqcloud.com | Le nom du bucket inclut votre APPID, p. ex. my-images-1250000000. |
| DigitalOcean Spaces | DigitalOcean Spaces | https://<region>.digitaloceanspaces.com |
- Créez le bucket et une clé limitée à ce bucket avec les droits put, get et delete sur les objets (voir Autorisations minimales ci-dessous).
- Rendez
optimized/lisible par votre CDN, par exemple avec une stratégie de bucket qui autorises3:GetObjectanonyme suroptimized/*uniquement. Sur MinIO :
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "*" ] }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::my-images/optimized/*" ] } ]}- Placez Cloudflare devant le bucket : un enregistrement DNS proxifié pour
images.example.comqui pointe vers l’hôte public du bucket. Si le fournisseur exige son propre nom d’hôte dans la requête, ajoutez une Origin Rule Cloudflare qui réécrit l’en-tête Host (et, pour les hôtes path-style, ajoute le nom du bucket au chemin). - Créez un jeton d’API Cloudflare pour la zone avec Zone → Cache Purge → Purge (Zone → Zone → Read facultatif).
- Dans le tableau de bord : choisissez le fournisseur dans le tableau, saisissez le bucket, le point de terminaison, la région (
autosi le fournisseur n’en a pas) et les clés ; activez les requêtes path-style lorsque le tableau l’indique ; puis CDN Cloudflare, Zone ID, jeton d’API et domaine CDN.
Autorisations minimales
Donnez à smallPict des clés qui ne peuvent faire que le nécessaire, sur un seul bucket.
| Fournisseur | Autorisations |
|---|---|
| Amazon S3 | s3:PutObject, s3:GetObject, s3:DeleteObject sur arn:aws:s3:::<bucket>/* |
| Amazon CloudFront | cloudfront:CreateInvalidation sur la distribution ; cloudfront:GetDistribution facultatif pour que le domaine puisse être détecté |
| Cloudflare R2 | Jeton d’API R2 avec Object Read & Write, limité au bucket |
| Cloudflare (CDN) | Jeton d’API pour la zone avec Zone → Cache Purge → Purge ; Zone → Zone → Read facultatif |
| Google Cloud Storage | Clé HMAC pour un compte de service disposant de roles/storage.objectUser sur le bucket |
| Alibaba Cloud OSS | Utilisateur RAM avec oss:PutObject, oss:GetObject, oss:DeleteObject sur le bucket |
| Tencent Cloud COS | Sous-utilisateur CAM avec cos:PutObject, cos:GetObject, cos:DeleteObject sur le bucket (le nom du bucket inclut l’APPID) |
| DigitalOcean Spaces | Clé d’accès Spaces limitée au bucket, avec lecture, écriture et suppression |
| MinIO / personnalisé compatible S3 | Put, get et delete sur <bucket>/* ; le point de terminaison doit être en HTTPS public |
La vérification de la connexion
À chaque enregistrement (et lorsque vous sélectionnez Relancer la vérification), smallPict vérifie l’ensemble de la connexion avant de l’utiliser :
- Stockage : écrit un petit fichier de test sous
.smallpict-probe/dans votre bucket, le relit puis le supprime. - Cloudflare : envoie à votre zone une purge de test portant sur une seule URL.
- CloudFront : crée une invalidation de test pour un chemin
/.smallpict-probe/.... Elle est décomptée de vos chemins d’invalidation CloudFront du mois.
Si une étape échoue, rien n’est basculé. Le tableau de bord affiche la raison à côté du champ concerné, par exemple le nom du bucket ou le jeton d’API. La vérification de la connexion est limitée à 5 tentatives par minute.
Accès de votre CDN au bucket
optimized/doit être lisible par votre CDN : soit en lecture publique sur ce préfixe, soit via un accès d’origine du CDN à un bucket privé (Origin access control de CloudFront ou domaine personnalisé R2).originals/peut rester privé. Votre CDN n’en a jamais besoin.- CORS n’est nécessaire que si des navigateurs récupèrent les images en cross-origin depuis JavaScript (par exemple avec
fetch()ou un canvas). Les balises<img>simples n’en ont pas besoin. Si vous en avez besoin, autorisezGETetHEADdepuis l’origine de votre site.
Organisation des objets et URL
| Quoi | Clé dans votre bucket | URL |
|---|---|---|
| Original | originals/<job_id>/<file> | Non diffusé |
| Fichier optimisé | optimized/<job_id>.<ext> | <cdn_domain>/optimized/<job_id>.<ext> |
Le domaine CDN peut inclure un préfixe de chemin, par exemple https://example.com/images ; l’URL devient alors https://example.com/images/optimized/<job_id>.<ext>.
En-têtes de cache
Les fichiers optimisés sont écrits avec Cache-Control: public, max-age=31536000, immutable. Chaque tâche reçoit une clé unique : un nouveau résultat a donc toujours une nouvelle URL, et une purge est rarement nécessaire. Veillez à ce que les règles de cache de votre CDN ne remplacent pas cet en-tête par une durée plus courte.
Purge du cache
- Les demandes de purge faites via l’API (
POST /v1/purge) sont envoyées par lots à votre CDN. - Sur Cloudflare, les fichiers sont purgés par URL. « Purge all » purge uniquement votre hôte de diffusion et votre préfixe de chemin, pas toute votre zone.
- Sur CloudFront, les fichiers sont purgés au moyen d’invalidations. « Purge all » crée une invalidation
/*. Les chemins d’invalidation au-delà du quota gratuit mensuel de CloudFront sont facturés par AWS à votre compte.
Changer de mode
Changer de mode ne déplace pas les fichiers existants. Les fichiers déjà diffusés conservent leurs URL actuelles ; seules les nouvelles tâches utilisent le nouveau mode.
- Géré → BYO : les nouvelles tâches vont dans votre bucket et sont diffusées par votre CDN. Les fichiers déjà présents sur
cdn.smallpict.appy restent. - BYO → géré : les nouvelles tâches utilisent à nouveau le stockage et le CDN gérés. Vos paramètres et clés BYO restent enregistrés mais inutilisés, afin que vous puissiez revenir en arrière sans les saisir à nouveau, jusqu’à ce que vous sélectionniez Déconnecter.
- Déconnecter : supprime les clés et les paramètres BYO enregistrés et vous ramène au mode géré. Les fichiers de votre bucket ne sont pas touchés.
En cas d’échec
- Si smallPict ne peut pas écrire dans votre bucket, il réessaie, puis fait échouer la tâche avec une raison que vous pouvez lire dans la réponse de l’API.
- Le tableau de bord affiche la dernière erreur et sa date, avec un bouton Relancer la vérification.
- Vous recevez un e-mail par incident, et non un par tâche échouée.
- smallPict ne se replie jamais sur le stockage géré. Vos fichiers ne sont jamais stockés à un endroit que vous n’avez pas choisi.
Sécurité
- Les clés sont conservées dans un coffre de secrets chiffré. Elles ne sont plus jamais affichées, jamais renvoyées par l’API et jamais écrites dans les journaux.
- Pour renouveler une clé, saisissez la nouvelle et enregistrez ; la vérification de la connexion s’exécute avec la nouvelle clé. Laissez un champ de clé vide pour conserver la clé enregistrée.
- Les points de terminaison de stockage et de CDN doivent utiliser HTTPS. Les points de terminaison qui se résolvent en adresses privées, de loopback, link-local ou autres adresses internes sont refusés.
- Utilisez des clés distinctes et restreintes pour smallPict, et révoquez-les dans la console de votre fournisseur si vous cessez d’utiliser le BYO.