Sécuriser et configurer Strapi pour la production
Optimisez la sécurité, les middlewares et la configuration serveur pour un site robuste.
Préparer l’environnement et les variables d’environnement
Avant tout, on définit nos variables sensibles dans un fichier .env. Strapi lit ces valeurs via env() :
1# .env2HOST=0.0.0.03PORT=13374APP_KEYS=key1,key2,key35DATABASE_CLIENT=postgres6DATABASE_HOST=db.example.com7DATABASE_PORT=54328DATABASE_NAME=strapi_prod9DATABASE_USERNAME=strapi10DATABASE_PASSWORD=supersecret11DATABASE_SSL=true12DATABASE_URL=postgres://strapi:supersecret@db.example.com:5432/strapi_prod13STRAPI_TOKEN=monTokenPourWebhooks14JWT_SECRET=unAutreSecretTresFort
Sécurise tes secrets
Ne commite jamais ton .env dans Git. Utilise Docker secrets ou ton CI/CD pour injecter
ces valeurs en production.
Configurer le serveur Strapi
On place dans config/server.ts la lecture des variables :
1export default ({ env }) => ({2host: env('HOST', '0.0.0.0'),3port: env.int('PORT', 1337),4app: {5keys: env.array('APP_KEYS'), // ^? Clés de chiffrement pour les cookies et JWT6},7webhooks: {8defaultHeaders: {9Authorization: `Bearer ${env('STRAPI_TOKEN')}`, // ^? Protection des webhooks10},11},12});
Configurer la base de données avec SSL
Dans config/database.ts, on active SSL pour PostgreSQL/MySQL :
1import path from 'node:path';23export default ({ env }) => {4const client = env('DATABASE_CLIENT', 'sqlite');5const commonSsl = env.bool('DATABASE_SSL', false) && {6rejectUnauthorized: env.bool('DATABASE_SSL_REJECT_UNAUTHORIZED', true),7key: env('DATABASE_SSL_KEY', undefined),8cert: env('DATABASE_SSL_CERT', undefined),9ca: env('DATABASE_SSL_CA', undefined),10};1112const connections = {13postgres: {14connection: {15connectionString: env('DATABASE_URL'),16ssl: commonSsl, // ^? Active SSL si DATABASE_SSL=true17},18pool: { min: 2, max: 10 },19},20// ... autres clients (mysql, sqlite)21};2223return {24connection: { client, ...connections[client] },25};26};
Tip
Tester la connexion SSL localement avec psql "sslmode=require ...".
Sécuriser les middlewares HTTP
On utilise le middleware strapi::security pour ajouter des headers HTTP via Helmet :
1export default [2'strapi::errors',3{4name: 'strapi::security',5config: {6contentSecurityPolicy: {7directives: {8defaultSrc: ["'self'"], // ^? Limite les sources de scripts9scriptSrc: ["'self'"],10styleSrc: ["'self'", "'unsafe-inline'"],11imgSrc: ["'self'", 'data:'],12connectSrc: ["'self'"],13},14},15hsts: { maxAge: 31536000, includeSubDomains: true },16xssProtection: true,17frameguard: { action: 'deny' },18noSniff: true,19},20},21'strapi::cors',22'strapi::csrf',23'strapi::poweredBy',24'strapi::logger',25'strapi::query',26'strapi::body',27'strapi::favicon',28'strapi::public',29];
// @callout: Utilise strapi::cors et strapi::csrf pour bloquer
// toute requête croisée non autorisée.
CSRF et CORS
Configure bien les origines (origin) dans config/middlewares.ts si ton front
est sur un domaine différent.
Limiter le nombre de requêtes (rate limiting)
On ajoute un middleware maison ou un plugin pour prévenir les DDoS :
1export default {2enabled: true,3config: {4policy: 'distributed',5points: 100, // 100 requêtes6duration: 60, // par minute7keyPrefix: 'rl:', // préfixe dans Redis (si utilisé)8},9};
Puis on l’injecte dans middlewares.ts :
1@@2- 'strapi::logger',3+ 'strapi::logger',4+ { name: 'plugin::rate-limit', config: {} },
Sécuriser l’interface d’administration
- Change le chemin d’accès par défaut (
/admin) :config/admin.ts1export default ({ env }) => ({2url: env('ADMIN_URL', '/secure-admin'), // ^? URL customisée3auth: {4secret: env('JWT_SECRET'),5},6}); - Active l’HTTPS sur ton proxy (Nginx, Traefik) :
Terminal1# Exemple pour Traefik2labels:3- "traefik.http.routers.strapi-secured.rule=Host(`shop.example.com`)"4- "traefik.http.routers.strapi-secured.tls=true"
Tip
Garde ton chemin /secure-admin secret et partage-le uniquement aux admin.
Déploiement avec Docker Compose
Exemple de fichier docker-compose.yml :
1version: '3.8'2services:3strapi:4image: strapi/strapi:55env_file: .env6volumes:7- ./build:/srv/app/build8- ./config:/srv/app/config9ports:10- "${PORT}:${PORT}"11depends_on:12- db13db:14image: postgres:1415env_file: .env16volumes:17- db_data:/var/lib/postgresql/data18volumes:19db_data: {}
Bonnes pratiques Docker
- Utilise une image officielle
- Ne mappe pas ton dossier
node_modules - Stocke les données en volume
Surveillance et sauvegarde
- Logs : redirige
stdout/stderrvers un outil de monitoring (ELK, Datadog…). - Backups : planifie des dumps de ta base (pg_dump, mysqldump) et de
/public/uploads. - Health check : configure un endpoint
/healthpour Kubernetes ou ton orchestrateur.
Récapitulatif des points clés
- Lire les env via
env()dansconfig/*.ts. - Chiffrer cookies et JWT avec
APP_KEYS/JWT_SECRET. - Activer SSL sur la base de données et le reverse proxy.
- Protéger les routes avec Helmet, CORS, CSRF et rate limiting.
- Sécuriser l’admin en personnalisant l’URL et en forçant HTTPS.
- Docker : séparer code, données et config, utiliser des secrets.
Exercices rapides
- Configurer un middleware
Dansconfig/middlewares.ts, ajoute un headerReferrer-Policy: no-referrer. - Changer le chemin admin
Modifieconfig/admin.tspour que l’UI soit accessible sur/gestion. - Tester le rate limiter
Écris un script Bash qui envoie 200 requêtes à ton API en 30 s. Observe le comportement.
Liens utiles :