Strapi : CMS headless self-hosted

Strapi : CMS headless self-hosted

Strapi est un CMS headless open-source, base Node.js. API REST et GraphQL generees automatiquement. Idеal pour decoupler un backoffice (Strapi) d'un frontend (Next.js, Nuxt, mobile).

Strapi : CMS headless self-hosted

Strapi est un CMS headless open-source, base Node.js. API REST et GraphQL generees automatiquement. Idеal pour decoupler un backoffice (Strapi) d'un frontend (Next.js, Nuxt, mobile).

Introduction

Strapi vous permet de :

  • Definir des content types via interface web (Content-Type Builder)
  • Acceder a vos donnees via REST + GraphQL automatiquement
  • Gerer les permissions (roles, plugins)
  • Plugin marketplace (i18n, email, upload S3, etc.)
  • Webhooks, locales, drafts/published

Stack typique : Strapi (backend + admin) + Next.js (frontend) + PostgreSQL (db) + S3/MinIO (medias).

Prerequis

  • VPS Linux 2 vCPU, 4 Go RAM, 20 Go SSD
  • Node.js 18+
  • PostgreSQL 14+
  • Acces root

Etape 1 : Preparer PostgreSQL

sudo apt install -y postgresql
sudo -u postgres psql

CREATE DATABASE strapi;
CREATE USER strapiuser WITH ENCRYPTED PASSWORD 'pass-fort';
GRANT ALL PRIVILEGES ON DATABASE strapi TO strapiuser;
\c strapi
GRANT ALL ON SCHEMA public TO strapiuser;
\q

Etape 2 : Creer le projet Strapi

cd /var/www
npx create-strapi-app@latest strapi --quickstart --no-run

Suivez l'assistant :

  • Choose between databases: postgres
  • Database name: strapi
  • Host: 127.0.0.1
  • Port: 5432
  • Username: strapiuser
  • Password: pass-fort
  • Enable SSL connection: N
cd /var/www/strapi

Etape 3 : Premier demarrage

npm run build
npm run start

Strapi ecoute sur :1337. Visitez http://IP_VPS:1337/admin.

Creez le premier compte admin.

Etape 4 : Definir un Content Type

Dans l'admin : Content-Type Builder > Create new collection type.

Exemple "Article" :

  • title : Text
  • slug : UID (genere depuis title)
  • content : Rich Text (Markdown)
  • cover : Media (single)
  • author : Relation > many-to-one > User
  • publishedAt : Datetime

Save. Strapi genere automatiquement :

  • API REST : GET /api/articles, POST /api/articles, etc.
  • Schema GraphQL si plugin GraphQL installe

Etape 5 : Gerer les permissions

Settings > Users & Permissions Plugin > Roles.

  • Public : qui peut acceder sans auth
  • Authenticated : qui peut acceder en etant logge

Pour rendre les articles lisibles publiquement :

Public > Article > cochez find et findOne.

Etape 6 : Tester l'API

curl http://IP_VPS:1337/api/articles

Reponse JSON. Filtrer / paginer :

curl 'http://IP_VPS:1337/api/articles?filters[title][$contains]=hello&pagination[limit]=10'

Populer les relations :

curl 'http://IP_VPS:1337/api/articles?populate=cover,author'

Etape 7 : Token API pour acces machine

Settings > API Tokens > Create.

Type : Read-only, Full access, ou custom. Notez le token genere (une seule fois affiche).

curl http://IP_VPS:1337/api/articles \
    -H "Authorization: Bearer VOTRE_TOKEN"

Etape 8 : Activer GraphQL

npm install @strapi/plugin-graphql

Restart Strapi. GraphQL playground sur :1337/graphql (en dev).

Exemple query :

query {
  articles {
    data {
      attributes {
        title
        slug
        content
      }
    }
  }
}

Etape 9 : Upload S3 / MinIO

Pour stocker les medias ailleurs que sur disque local :

npm install @strapi/provider-upload-aws-s3

config/plugins.js :

module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        accessKeyId: env('AWS_ACCESS_KEY_ID'),
        secretAccessKey: env('AWS_ACCESS_SECRET'),
        region: env('AWS_REGION'),
        params: {
          Bucket: env('AWS_BUCKET'),
        },
      },
    },
  },
});

.env :

AWS_ACCESS_KEY_ID=xxx
AWS_ACCESS_SECRET=xxx
AWS_REGION=eu-west-3
AWS_BUCKET=mon-bucket

Etape 10 : Mise en prod avec PM2

sudo npm install -g pm2
cd /var/www/strapi
pm2 start npm --name strapi -- start
pm2 startup
pm2 save

Devant Strapi, configurez Nginx en reverse proxy :

server {
    listen 443 ssl http2;
    server_name strapi.votre-domaine.fr;
    
    client_max_body_size 50M;
    
    location / {
        proxy_pass http://localhost:1337;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Etape 11 : Backups

PostgreSQL :

pg_dump -U strapiuser -h 127.0.0.1 strapi | gzip > strapi-$(date +%F).sql.gz

Uploads (si local) :

tar czf strapi-uploads-$(date +%F).tar.gz /var/www/strapi/public/uploads

Strapi a aussi un module export/import :

npx strapi export --no-encrypt
npx strapi import --file export.tar.gz

Etape 12 : Variables d'env critiques

/var/www/strapi/.env :

HOST=0.0.0.0
PORT=1337
APP_KEYS=cle1,cle2,cle3,cle4
API_TOKEN_SALT=...
ADMIN_JWT_SECRET=...
TRANSFER_TOKEN_SALT=...
JWT_SECRET=...
DATABASE_CLIENT=postgres
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapiuser
DATABASE_PASSWORD=pass-fort

⚠️ Generez des secrets robustes en prod :

openssl rand -base64 16

Depannage

"ECONNREFUSED" sur PostgreSQL

Verifiez que PG accepte les connexions locales :

sudo nano /etc/postgresql/14/main/pg_hba.conf
host all all 127.0.0.1/32 md5
sudo systemctl restart postgresql

Admin panel 502

Strapi pas demarre, ou build en cours :

pm2 logs strapi

Verifiez aussi npm run build execute apres chaque update.

Lent au startup

Strapi 4 charge tous les content types, plugins, hooks au boot. Normal de prendre 30s. En cluster, lancez plusieurs instances derriere un load balancer.

Memory issues

Augmentez la RAM du VPS, ou limitez NODE_OPTIONS=--max-old-space-size=2048 dans .env.

Commandes utiles

npm run develop          # mode dev (hot reload)
npm run build            # build production
npm run start            # start production
npm run console          # repl Strapi

npx strapi export --no-encrypt    # backup complet
npx strapi import --file f.tar.gz

# Logs
pm2 logs strapi
sudo tail -f /var/log/postgresql/postgresql-14-main.log

Conclusion

Strapi vous donne :

  • Backoffice editable + API automatique
  • Permissions fines et roles
  • Multi-tenant, i18n, drafts
  • API REST et GraphQL
  • Decouplage backend / frontend

Pour aller plus loin :

  • Couplez avec Next.js pour le frontend (ISR)
  • Activez Cloudinary pour des medias optimises
  • Pour gros volumes, utilisez Strapi Cloud ou un cluster sur Kubernetes

Ressources

Rejoignez notre serveur communautaire Discord

Pour toute question, suggestion ou simplement pour discuter avec la communauté, rejoignez-nous sur Discord !

900+Membres