Aller au contenu

Configurer les téléchargements médias de Strapi 5 vers Amazon S3 avec des URLs signées privées

Apprenez pas à pas à installer le provider d’upload AWS‑S3, configurer des buckets privés, générer des URLs signées et ajuster les politiques de sécurité pour la gestion des médias sous Strapi 5.

Par l’équipe Revisionary · · 5 min de lecture

a rack of electronic equipment in a dark room
Photo de Tyler sur Unsplash

Strapi 5 peut stocker tous les médias téléchargés dans un bucket Amazon S3 et retourner automatiquement des URLs signées lorsque le bucket est privé. Le processus consiste à installer le package officiel @strapi/provider-upload-aws-s3, ajouter une configuration de provider dans config/plugins.{js|ts}, définir l’ACL du bucket à private (ou omettre l’ACL publique), définir la valeur signedUrlExpires, et ajuster à la fois le CORS du bucket et la Content Security Policy (CSP) de Strapi. Le guide suivant vous accompagne pas à pas, montre l’extrait complet de configuration et souligne les points de migration depuis Strapi 4.

1. Prérequis

  • Strapi 5 (toute version 5.x) fonctionnant sur Node 18‑24.
  • Un bucket Amazon S3 que vous contrôlez.
  • Un utilisateur ou rôle IAM avec les permissions suivantes : s3:PutObject, s3:GetObject, s3:ListBucket, s3:DeleteObject, s3:PutObjectAcl.
  • Accès aux paramètres CORS du bucket.
  • (Facultatif) Variables d’environnement pour les identifiants et la région afin de ne pas stocker les secrets dans le code.
turned-on gray laptop computer
Photo de Safar Safarov sur Unsplash

2. Installer le provider d’upload AWS‑S3

Le provider officiel est publié sous le nom @strapi/provider-upload-aws-s3. Installez‑le avec votre gestionnaire de paquets :

bash
# Using npm
npm install @strapi/provider-upload-aws-s3 --save

# Using yarn
yarn add @strapi/provider-upload-aws-s3

Le package fonctionne avec les projets JavaScript et TypeScript.

3. Configuration de base

Créez ou modifiez le fichier de configuration du plugin à config/plugins.js (ou config/plugins.ts pour TypeScript). Le provider attend un objet imbriqué sous upload.config.

js
// config/plugins.js
module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        // Options spécifiques au provider
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            Bucket: env('AWS_BUCKET'),
            // Bucket privé – ne PAS définir ACL à public-read
            ACL: 'private',
            // Expiration de l’URL signée en secondes (par défaut 900 s)
            signedUrlExpires: env.int('AWS_SIGNED_URL_EXPIRES', 15 * 60),
          },
        },
        // URL de base CDN facultative (p. ex., CloudFront)
        // baseUrl: env('AWS_CDN_URL'),
      },
    },
  },
});

Points clés :

  • provider: 'aws-s3' indique à Strapi d’utiliser le provider AWS S3.
  • Toutes les options du SDK AWS v3 se trouvent sous s3Options.
  • Le paramètre ACL: 'private' déclenche la génération automatique d’URL signées pour chaque fichier téléchargé. Si vous utilisez public-read, les URLs sont renvoyées sous forme d’URL S3 classiques.
  • signedUrlExpires contrôle la durée de validité de l’URL signée. La valeur par défaut est 15 minutes (900 secondes).

4. Activer l’accès privé et les URLs signées

Lorsque le bucket est privé, le service d’upload de Strapi appelle automatiquement getSignedUrl pour chaque fichier. L’URL signée contient les paramètres de requête X‑Amz‑* requis, ce qui permet aux consommateurs front‑end de télécharger l’actif sans exposer le bucket publiquement.

Si vous avez besoin d’une stratégie de signature personnalisée (par exemple, rotation des clés), vous pouvez surcharger le provider en créant le répertoire ./providers/aws-s3 et en implémentant les méthodes isPrivate() et getSignedUrl(file). Dans la plupart des projets, la logique intégrée suffit.

5. Configurer le CORS du bucket

Un bucket privé bloque l’accès depuis le navigateur tant que le CORS ne permet pas l’origine de la requête. Ajoutez une règle CORS similaire à celle‑ci dans la console AWS S3 :

json
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "HEAD"],
    "AllowedOrigins": ["https://your-strapi-domain.com"],
    "ExposeHeaders": [],
    "MaxAgeSeconds": 3000
  }
]

Cette règle autorise le front‑end Strapi (ou tout domaine de confiance) à récupérer les URLs signées via des requêtes GET.

6. Ajuster la Content Security Policy de Strapi

Strapi fournit un middleware de sécurité (strapi::security) qui définit les directives CSP. Pour autoriser les images et médias provenant de votre bucket S3, étendez contentSecurityPolicy dans config/middlewares.js (ou le nouveau format config/middlewares.{js|ts}) :

js
module.exports = ({ env }) => [
  // … autres middlewares
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          // Ajoutez le domaine du bucket à img-src et media-src
          'img-src': ["'self'", env('AWS_BUCKET_DOMAIN')],
          'media-src': ["'self'", env('AWS_BUCKET_DOMAIN')],
        },
      },
    },
  },
];

Remplacez AWS_BUCKET_DOMAIN par quelque chose comme my-bucket.s3.amazonaws.com. Ainsi le navigateur ne bloquera pas les URLs signées.

7. Options avancées du provider (facultatif)

Le provider propose plusieurs fonctionnalités supplémentaires utiles pour les déploiements à grande échelle ou soumis à des exigences de conformité :

OptionDescription
storageClassChoisissez la classe de stockage S3, par ex. INTELLIGENT_TIERING ou STANDARD_IA.
encryptionActive le chiffrement côté serveur. Exemple : { type: 'aws:kms', kmsKeyId: env('AWS_KMS_KEY_ID') }.
preventOverwrite: trueEmpêche l’écrasement accidentel d’objets existants.
checksumAlgorithmSpécifie l’algorithme de somme de contrôle, par ex. CRC64NVME.
tagsAjoute des tags S3 aux objets pour le suivi des coûts ou les règles de cycle de vie.
multipartUploadAffine les seuils multipart et la taille des parties.

Ces options s’ajoutent sous providerOptions.s3Options dans le même fichier de configuration.

8. Tester la configuration

  1. Téléversez un fichier via l’interface d’administration de Strapi (Bibliothèque média → Téléversement).
  2. Une fois le téléversement terminé, inspectez l’entrée du fichier. L’URL affichée doit ressembler à :
    code
    https://my-bucket.s3.amazonaws.com/your-folder/filename.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=...
  3. Copiez l’URL dans un nouvel onglet du navigateur. Le fichier doit être téléchargé tant que le délai de validité n’est pas écoulé.
  4. Vérifiez qu’une URL directe, non signée (sans chaîne de requête) renvoie 403 Forbidden, confirmant que le bucket est privé.

9. Migration depuis Strapi 4

Strapi 4 supportait également un provider S3, mais la forme de la configuration a changé en v5 :

  • Toutes les options spécifiques à S3 doivent maintenant être imbriquées sous s3Options.
  • Les identifiants sont obligatoires dans un objet credentials ; les anciennes clés accessKeyId/secretAccessKey au niveau supérieur fonctionnent encore mais déclenchent des avertissements de dépréciation.
  • Le paramètre signedUrlExpires par défaut est passé de la configuration du provider aux options params.

Si vous effectuez une mise à jour, remplacez votre ancien config/plugins.js par la structure v5 présentée à la section 3, exécutez npm install @strapi/provider-upload-aws-s3@latest, puis redémarrez Strapi.

10. Déploiement en production

Lors du déploiement sur des environnements tels que Vercel, Railway ou des VPS classiques, assurez‑vous que :

  • Les variables d’environnement (AWS_ACCESS_KEY_ID, AWS_ACCESS_SECRET, AWS_REGION, AWS_BUCKET, etc.) sont définies sur la plateforme d’hébergement.
  • Le rôle IAM attaché à l’hôte (si vous utilisez EC2 ou ECS) possède les permissions S3 requises.
  • Le fichier middleware CSP est inclus dans le build (il vit dans config/ qui est empaqueté avec le projet Strapi).

Un extrait typique de Dockerfile pour la production peut ressembler à :

Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app
COPY --from=builder /app/build ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/config ./config
EXPOSE 1337
CMD ["node", "server.js"]

Le dossier config contient la configuration du provider S3 et les ajustements CSP, garantissant que le conteneur démarre avec les bons paramètres.

11. Problèmes courants et dépannage

SymptomLikely causeFix
L’URL signée renvoie 403 alors que le bucket est privéRègle CORS manquante ou AllowedOrigins mal orthographiéAjoutez votre domaine Strapi à la configuration CORS du bucket.
L’URL du fichier téléversé est une URL S3 simple (pas de X‑Amz‑ query)ACL définie sur public-read ou omiseRéglez ACL: 'private' dans s3Options.params.
L’upload échoue avec InvalidAccessKeyIdIdentifiants non lus depuis l’environnement ou faute de frappeVérifiez que env('AWS_ACCESS_KEY_ID') et env('AWS_ACCESS_SECRET') sont correctement définis.
CSP bloque les images provenant de S3Domaine du bucket non ajouté aux directives img-src/media-srcMettez à jour config/middlewares.js pour inclure le domaine du bucket.
Après la migration depuis Strapi 4, le provider lève "providerOptions.s3Options is undefined"Ancienne configuration utilisant encore les clés de niveau supérieurDéplacez toutes les options S3 sous s3Options comme indiqué dans l’exemple v5.

Si les problèmes persistent, consultez le forum communautaire de Strapi ou le README officiel du provider pour plus de détails.

A white cloud icon on a glass square with floating data charts and cylinders
Photo de Hazel Z sur Unsplash

12. Résumé

Configurer Strapi 5 pour utiliser Amazon S3 avec des URLs signées privées se résume à quatre étapes principales :

  1. Installer le package officiel @strapi/provider-upload-aws-s3.
  2. Ajouter une configuration de provider qui rend le bucket privé, définit signedUrlExpires et fournit les identifiants via des variables d’environnement.
  3. Ajuster le CORS du bucket et la CSP de Strapi afin que les navigateurs puissent récupérer les URLs signées.
  4. (Facultatif) Activer les options avancées telles que le chiffrement, la classe de stockage ou une logique de signature personnalisée.

Une fois en place, chaque actif média téléversé via Strapi est stocké en toute sécurité dans S3, et le CMS renvoie automatiquement des URLs temporaires qui protègent vos fichiers tout en offrant une intégration front‑end fluide.


Pour les équipes qui souhaitent une historisation complète, le plugin Revisionary peut être ajouté au-dessus de cette configuration, offrant la version des champs, des journaux d’audit et une corbeille — voir la documentation du produit pour plus d’informations.

Mots-clésStrapi 5Amazon S3téléchargement médiaactifs privésURLs signéesCMS headless

Sources

  1. Amazon S3 upload provider – Strapi Documentation
  2. Media Library Providers – Strapi Documentation
  3. AWS S3 provider source code – Strapi GitHub
  4. @strapi/provider-upload-aws-s3 npm package
  5. Migration guide: Amazon S3 provider credentials – Strapi v4 to v5
  6. Provider README – Amazon S3 (Strapi)

L’équipe Revisionary

Les développeurs de Revisionary, un plugin d’historique des versions pour Strapi 5. Nous écrivons sur Strapi, le développement web, l’IA et la sécurité des applications.

Cet article a été rédigé avec l'aide d'une IA.

Tous les articles