Lecture : 13 minutes · Niveau : intermédiaire-avancé · Mise à jour : avril 2026
Faire tourner Strapi en local est trivial. Le faire tourner en production fiable, sécurisé, sauvegardé et déployable sans downtime demande des choix précis. Ce guide rassemble les pratiques opérationnelles pour des PME qui veulent livrer du Strapi sérieux.
Voir aussi → Strapi headless CMS pour PME : guide complet.
Sommaire
- Choix d’hébergement
- Render et Railway : déploiement rapide
- VPS auto-géré
- Docker et conteneurisation
- Configuration production
- Base de données PostgreSQL
- Stockage médias en production
- Sécurité et hardening
- Sauvegardes et reprise
- Monitoring et logs
- Mises à jour Strapi
- FAQ
1. Choix d’hébergement
Strapi est une application Node.js + base de données. Plusieurs options.
PaaS : Render, Railway, Fly.io
Pour : déploiement git push, base PostgreSQL managée incluse, SSL automatique, scaling simple, peu de configuration.
Contre : tarif récurrent qui croît avec l’usage, dépendance plateforme, contraintes parfois (cold start sur tier bas, etc.).
Pour démarrer rapidement : excellent choix.
VPS auto-géré
Hetzner, OVH, Scaleway, hébergeurs ouest-africains.
Pour : contrôle total, prix maîtrisé, pas de surprise tarif au scale.
Contre : maintenance technique à assumer (OS, sécurité, backups). Compétence sysadmin nécessaire.
Strapi Cloud
Service SaaS officiel Strapi.
Pour : zéro infra, support officiel, mises à jour gérées, intégration au tooling Strapi.
Contre : abonnement payant qui croît avec l’usage. Plus cher au scale qu’auto-hébergé.
Kubernetes / cloud avancé
Pour des organisations matures avec plusieurs services. Sur-dimensionné pour la majorité des PME.
Recommandation
- MVP / startup : Render ou Railway. Zéro setup.
- PME établie : VPS Hetzner avec stack Docker, ou Render si pas de compétence DevOps interne.
- Grosse organisation : Strapi Cloud pour le support, ou Kubernetes self-managed pour le contrôle.
2. Render et Railway : déploiement rapide
Render
1. Créer compte render.com
2. Connecter GitHub
3. New Web Service → sélectionner le repo Strapi
4. Build command : npm install && npm run build
5. Start command : npm run start
6. Variables d'env : DATABASE_URL, NODE_ENV, JWT_SECRET, etc.
7. Créer base PostgreSQL via Render → connecter au service
Strapi démarre en quelques minutes. SSL automatique sur le sous-domaine Render.
Railway
Workflow similaire à Render. Interface plus moderne, déploiement plus rapide. Outils de debugging intégrés.
Variables d’env critiques
APP_KEYS=<random>,<random>,<random>,<random>
API_TOKEN_SALT=<random>
ADMIN_JWT_SECRET=<random>
JWT_SECRET=<random>
DATABASE_URL=postgres://...
NODE_ENV=production
HOST=0.0.0.0
PORT=1337
Générer les secrets via openssl rand -hex 32 et les stocker dans la plateforme.
Custom domain
Configurer DNS du domaine vers la plateforme (CNAME), valider, SSL Let’s Encrypt automatique.
3. VPS auto-géré
Stack type Ubuntu 24.04
# Mises à jour
sudo apt update && sudo apt upgrade -y
# Node.js LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install nodejs
# PostgreSQL
sudo apt install postgresql postgresql-contrib
# Caddy ou Nginx pour reverse proxy
sudo apt install caddy
# PM2 ou systemd pour process manager
sudo npm install -g pm2
Setup Strapi
# Cloner le repo
git clone <repo> /var/www/strapi
cd /var/www/strapi
# Installer dépendances
npm install --production=false
# Build
NODE_ENV=production npm run build
# Démarrer avec PM2
pm2 start npm --name strapi -- run start
pm2 save
pm2 startup
Reverse proxy Caddy
api.exemple.com {
reverse_proxy localhost:1337
encode gzip
}
HTTPS Let’s Encrypt automatique.
Sécurité
- Voir Linux sécurité hardening pour les bases
- Firewall UFW : autoriser 22 (SSH), 80, 443 seulement
- SSH par clé uniquement
- Mises à jour de sécurité automatiques
4. Docker et conteneurisation
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN NODE_ENV=production npm run build
FROM node:20-alpine
WORKDIR /app
RUN apk add --no-cache vips-dev # pour sharp (image processing)
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/build ./build
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/public ./public
COPY package.json ./
USER node
EXPOSE 1337
CMD ["npm", "run", "start"]
Docker Compose
services:
strapi:
image: ghcr.io/ma-pme/strapi:latest
restart: unless-stopped
environment:
DATABASE_URL: postgres://strapi:${DB_PASS}@db:5432/strapi
NODE_ENV: production
APP_KEYS: ${APP_KEYS}
JWT_SECRET: ${JWT_SECRET}
depends_on:
db: { condition: service_healthy }
volumes:
- uploads:/app/public/uploads
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: strapi
POSTGRES_USER: strapi
POSTGRES_PASSWORD: ${DB_PASS}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U strapi"]
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports: ["80:80", "443:443"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
volumes:
db-data:
uploads:
caddy-data:
Voir Docker en production pour PME pour les principes.
5. Configuration production
config/server.js
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
url: env('PUBLIC_URL', 'https://api.exemple.com'),
app: { keys: env.array('APP_KEYS') },
});
config/admin.js
module.exports = ({ env }) => ({
auth: {
secret: env('ADMIN_JWT_SECRET'),
},
apiToken: {
salt: env('API_TOKEN_SALT'),
},
url: env('ADMIN_URL', '/admin'),
});
Sécuriser l’admin URL
Par défaut /admin. À renommer pour limiter le scan automatisé :
url: env('ADMIN_URL', '/super-admin-9hY3w'),
Disable preview features dangereuses en prod
- Ne pas exposer le serveur GraphQL playground en prod
- Désactiver
documentationplugin si non utilisé - Restreindre les origines CORS
// config/middlewares.js
module.exports = [
// ...
{
name: 'strapi::cors',
config: {
origin: ['https://www.exemple.com', 'https://exemple.com'],
headers: '*',
},
},
];
6. Base de données PostgreSQL
Setup PostgreSQL
CREATE DATABASE strapi;
CREATE USER strapi WITH ENCRYPTED PASSWORD 'mot_de_passe_fort';
GRANT ALL PRIVILEGES ON DATABASE strapi TO strapi;
\c strapi
GRANT ALL ON SCHEMA public TO strapi;
Configuration recommandée
postgresql.conf (selon RAM disponible) :
shared_buffers = 256MB # 25% de la RAM disponible serveur
effective_cache_size = 1GB # 50-75% de la RAM
work_mem = 16MB
maintenance_work_mem = 64MB
Connection pooling
Strapi ouvre des connexions DB. Pour des trafics importants : PgBouncer en pooler entre Strapi et PostgreSQL. Économise les connexions et améliore la stabilité sous charge.
Backups DB
# Backup quotidien
pg_dump -U strapi -h localhost strapi > /backups/strapi_$(date +%Y%m%d).sql
# Restauration
psql -U strapi -d strapi < backup.sql
À automatiser via cron, externaliser sur S3 ou similaire. Voir Sauvegarde 3-2-1.
MySQL alternative
Strapi supporte aussi MySQL. PostgreSQL généralement préféré pour son support JSON natif et fonctionnalités modernes.
7. Stockage médias en production
Par défaut Strapi stocke dans public/uploads/ local. Pas idéal en production.
Options
- AWS S3 ou compatible (Backblaze B2, Wasabi, Hetzner Object Storage, MinIO self-hosted, Scaleway Object Storage)
- Cloudinary : transformations d’images natives, formats WebP/AVIF auto
- Imagekit : alternative à Cloudinary
- Stockage local + backup : possible mais déconseillé en production
Configuration S3-compatible
npm install @strapi/provider-upload-aws-s3
// config/plugins.js
module.exports = ({ env }) => ({
upload: {
config: {
provider: '@strapi/provider-upload-aws-s3',
providerOptions: {
s3Options: {
credentials: {
accessKeyId: env('AWS_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_SECRET_ACCESS_KEY'),
},
region: env('AWS_REGION'),
endpoint: env('AWS_ENDPOINT'), // pour S3-compatible non-AWS
params: {
ACL: 'public-read',
Bucket: env('AWS_BUCKET'),
},
},
},
},
},
});
Cloudinary
npm install @strapi/provider-upload-cloudinary
Configuration similaire. Cloudinary apporte les transformations à la volée (resize, crop, format) — très pratique pour générer plusieurs tailles d’images sans bloat.
Migration vers stockage externe
Pour migrer un site Strapi avec uploads locaux vers S3 :
- Configurer le provider S3
- Uploader les fichiers existants vers S3 (script ou outil de sync comme rclone)
- Mettre à jour les URLs en base de données
- Tester sur staging
- Switcher en production
8. Sécurité et hardening
Bases de sécurité
- HTTPS strict partout
- Secrets via variables d’environnement uniquement, jamais en dur
- APP_KEYS, JWT_SECRET, ADMIN_JWT_SECRET : générer aléatoirement, ne jamais réutiliser entre projets
- Mises à jour Strapi régulières (versions de sécurité)
- Mises à jour Node.js et dépendances OS
Restrictions admin
- URL admin renommée
- 2FA si module disponible
- Restriction par IP (via Caddy/Nginx) si admin uniquement accédé depuis bureau
- Audit logs (plugin Strapi Enterprise ou tiers)
Permissions par défaut
Strapi sécurise par défaut : tous les endpoints API sont protégés (404 si non explicitement autorisés). Activer uniquement ce qui est nécessaire au frontend public.
CSP et headers de sécurité
// config/middlewares.js
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': ["'self'", 'data:', 'blob:', 'https://res.cloudinary.com'],
'media-src': ["'self'", 'data:', 'blob:'],
},
},
},
},
Rate limiting
Pas natif dans Strapi mais ajoutable via Caddy/Nginx en frontal, ou middleware Strapi custom.
9. Sauvegardes et reprise
Quoi sauvegarder
- Base de données PostgreSQL :
pg_dumpquotidien - Médias uploads : si stockage local, sauvegarder le dossier
public/uploads. Si S3 : provider gère la durabilité, mais activer versioning du bucket. - Code source : Git
.env: sauvegardé séparément en sécurité
Stratégie 3-2-1
- 3 copies des données
- 2 supports différents
- 1 copie hors-site
Voir Sauvegarde 3-2-1 PME africaine.
Test de restauration
Indispensable. Au moins trimestriel. Restaurer un backup dans un environnement isolé, vérifier l’intégrité, documenter le processus.
Disaster recovery
Documenter :
– Comment recréer un Strapi from scratch
– Où sont les sauvegardes
– Variables d’environnement (stockées sécurisément séparément)
– DNS et certificats
Si possible : avoir un environnement de secours pré-configuré, prêt à recevoir un restore.
10. Monitoring et logs
Logs
Strapi log en stdout. En production :
- Render/Railway : logs accessibles dans le dashboard
- Docker :
docker compose logs -f strapi - VPS : centraliser via journald, Loki, ou Logtail
Format JSON pour parsing facile :
// config/logger.js
module.exports = {
level: 'warn',
transport: 'json',
};
Erreurs
Sentry pour capture automatique des erreurs Node.js :
npm install @sentry/node
Configurer dans src/index.js. Tier gratuit suffit pour démarrer.
Métriques
- Uptime Kuma ou Better Uptime : ping externe pour vérifier disponibilité
- Prometheus + Grafana : pour métriques détaillées si besoin
- APM (Datadog, New Relic) : pour tracing avancé sur gros projets
Health check
Strapi expose /_health. Configurer le load balancer / orchestrateur pour le ping.
11. Mises à jour Strapi
Strapi sort des versions régulières (mineures et majeures).
Mises à jour mineures (4.x → 4.y)
Généralement sans changement breaking :
npm install @strapi/strapi@latest
npm run build
pm2 restart strapi
Toujours backup DB avant.
Mises à jour majeures (4 → 5)
Changements API possibles, plugins parfois incompatibles. Workflow :
- Lire le guide de migration officiel
- Préparer un environnement de test (clone production)
- Mettre à jour les dépendances (Strapi + plugins)
- Adapter le code custom si nécessaire
- Tester intégralement (admin + API + frontend)
- Migrer la production avec fenêtre de maintenance
Compter 1-3 jours-homme pour une migration majeure selon complexité.
Sécurité
Surveillance des annonces de sécurité Strapi. Patches de sécurité à appliquer rapidement.
12. FAQ
Render ou VPS auto-géré pour démarrer ?
Render pour vitesse de démarrage et zéro DevOps. VPS pour contrôle et coût maîtrisé au scale. Pour un MVP : Render. Pour une PME établie : VPS si compétence interne, Render sinon.
Strapi tient-il dans 512 Mo de RAM ?
Limite : oui pour démarrer un projet simple. Vite tendu avec contenu volumineux et plusieurs plugins. Cible : 1 Go RAM minimum, 2 Go confortable.
Combien de RAM pour PostgreSQL Strapi ?
512 Mo à 2 Go selon volume. Pour des contenus standards : 1 Go suffit. Pour des médias volumineux ou catalogues massifs : 4 Go+.
Comment éviter le cold start sur Render ?
Plans payants Render (Standard et up) gardent le service tournant. Tier gratuit met en sommeil après inactivité. Pour démarrage instantané : passer en payant ou utiliser un cron externe pour ping périodique.
Stockage local ou S3 pour les médias ?
S3-compatible en production toujours. Stockage local = single point of failure (perte serveur = perte médias) et difficulté de scaling horizontal. Backblaze B2 et Wasabi sont des options abordables.
Mises à jour Strapi cassent souvent ?
Mineures : rarement. Majeures : possibilité. Lire les release notes, tester sur staging, ne jamais migrer en prod sans backup et plan de rollback.
Monitoring quoi en priorité ?
Health endpoint (/_health), erreurs Node.js (Sentry), latence API, espace disque, RAM. Ces 5 indicateurs couvrent la majorité des incidents possibles.
Articles liés (cluster Strapi)
- 👉 Strapi headless CMS pour PME : guide complet (pillar)
- 👉 Strapi content types et API
- 👉 Strapi + Next.js intégration
Article mis à jour le 25 avril 2026. Pour signaler une erreur ou suggérer une amélioration, écrivez-nous.