Découvre comment mettre en place un CMS moderne avec Payload et Next.js, de l'installation locale jusqu'au déploiement sécurisé sur un VPS avec Docker, Nginx et certificat SSL. Suis notre tutoriel pas à pas pour maîtriser le déploiement, la gestion de contenu et l'automatisation du versionning avec Git.
Sommaire
- Lancer Payload en local
- Créer son premier post type sur Payload
- Initialiser le repo Git pour le versionning
- Configuration de Docker
- Configurer le VPS
- Configurer les DNS
- Créer un certificat SSL pour passer en HTTPS
Lancer Payload en local
1. Pré-requis : Installer les outils de base
- Installer Homebrew (le gestionnaire de paquets sur macOS) https://brew.sh/
- Installer Node.js et npm via Homebrew :
1
brew install node- Vérifie les versions installées :
1
2
node -v
npm -v2. Installer & lancer MongoDB via Brew
- Installer MongoDB Community Edition :
(Exemple : MongoDB 8.0 – assure-toi d’adapter la commande selon la version souhaitée)
1
2
brew tap mongodb/brew
brew install mongodb-community@8.0- Lancer MongoDB avec Brew Services :
1
brew services start mongodb-community@8.0- Vérifie que MongoDB tourne :
1
brew services listMongo sera accessible sur mongodb://localhost:27017 (par défaut).Documentation officielle :
3. Créer le projet Next.js
Dans ton dossier de travail, exécute :
1
npx create-payload-appRéponds aux questions :
- Nom du projet
- Choix de la base de données (MongoDB)
- Choix du template (par exemple
blanksi tu veux un projet minimal)
4. Installer l’éditeur de code
Tu peux utiliser Visual Studio Code, par exemple :
5. Lancer le projet en local
- Ouvre le dossier de projet avec VSCode.
- Ouvre le terminal (raccourci : Cmd + J).
- Installe les dépendances :
1
npm i- Lance le projet :
1
npm run dev- Dans ton navigateur, rends-toi à l’adresse : http://localhost:3000
6. Premiers pas sur l’interface payload
- Clique sur “Go to Admin Panel”.
- Crée ton compte admin.
Créer son premier type de contenu sur Payload
1. Créer la liste des Todo dans le back
Objectif : Créer un type de contenu “Todo” (une simple liste de tâches) que tu pourras afficher sur ton site et administrer depuis Payload.
- Dans VSCode, localise le dossier
src/collections. - Crée un fichier
Todo.ts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import type { CollectionConfig } from 'payload'
export const Todo: CollectionConfig = {
slug: 'todo',
admin: {
useAsTitle: 'Tâche',
},
fields: [
{
name: 'Tâche',
type: 'text',
required: true,
},
],
}- Dans le fichier
payload.config.ts(dossiersrc), ajoute la collectionTodo:/
1
2
3
4
5
//avant:
collections: [Users, Media],
//après:
collections: [Users, Media, Todo],- N’oublie pas d’importer
Todoen haut du fichierpayload.config.ts:
1
import { Todo } from './collections/Todo'Une fois le projet relancé, tu verras apparaître ta nouvelle collection “Todo” dans l’admin.
2. Afficher la liste des Todo dans le front
- Ouvre la page principale de ton site :
src/app/(frontend)/page.tsxet modifie son contenu pour récupérer et afficher les tâches :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { getPayload } from 'payload'
import React from 'react'
import config from '@/payload.config'
import './styles.css'
export const dynamic = 'force-dynamic'
export default async function HomePage() {
const payload = await getPayload({ config });
const Todos = await payload.find({
collection: 'todo',
})
return (
<div>
{
Todos.docs?.map((todo) => (
<div key={todo.id}>
<h2>{todo.Tâche}</h2>
</div>
))
}
</div>
)
}Maintenant, chaque tâche créée dans Payload s’affichera sur la page d’accueil.
Initialise le Repo Git pour le versionning
1. Créer un compte sur GitHub
2. Créer une clé SSH
1
ssh-keygen -t rsa -b 4096 -C "votre_email@example.com"- Lorsque l'invite te demande de spécifier un chemin de fichier pour la clé, appuis simplement sur
Entréepour accepter l'emplacement par défaut (~/.ssh/id_rsa). - Ensuite, choisis un mot de passe sécurisé pour la clé SSH ou appuie sur
Entréepour ignorer (optionnel mais recommandé)
3. Démarrer l'agent SSH
Lance l'agent SSH pour gérer la clé :
1
eval "$(ssh-agent -s)"4. Ajouter la clé SSH à l'agent
Ajoute la clé privée à l'agent pour qu'elle soit utilisée automatiquement :
1
ssh-add ~/.ssh/id_rsa5. Copier la clé SSH publique
1
cat ~/.ssh/id_rsa.pubSélectionnez et copiez le contenu affiché.
6. Ajouter la clé SSH à GitHub (ou GitLab, etc.)
- Dans GitHub : Settings > SSH and GPG keys > New SSH key.
- Colle la clé publique, donne-lui un nom explicite (par ex. "VPS" ou "MacBook"), puis valide.
7. Tester la connexion
1
ssh -T git@github.comUn message de bienvenue devrait s’afficher.
8. Créer un repo
- Créer un repo : https://github.com/new
- Choisis le nom du repo, la visibilité (privé ou public)…
- Une fois créé, suis les instructions pour lier ton projet :
1
2
3
git remote add origin git@github.com:beease/payload-test.git
git branch -M main
git push -u origin main- Commit les changements:
1
2
3
git add .
git commit -am "todo"
git pushBravo, tes modifications sont maintenant en ligne, les autres développeurs ayant accès au projet pourront mettre leur version à jour avec tes changements avec la commande git pullConfiguration de Docker
1. Configurer docker compose
- À la racine du projet tu trouveras le fichier docker-compose.yml, il sert à gérer les conteneurs docker. Le template de base de payload inclut déjà une configuration. on va la remplacer par le code suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
services:
payload:
build:
context: .
volumes:
- ./media:/app/media
ports:
- '3000:3000'
depends_on:
- mongo
mongo:
container_name: mongo
image: mongo:latest
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: username
MONGO_INITDB_ROOT_PASSWORD: password
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
nginx:
container_name: webserver
restart: always
image: nginx:latest
ports:
- '80:80'
volumes:
- ./nginx.conf:/etc/nginx/conf.d/nginx.conf:ro
depends_on:
- payload
volumes:
mongodb_data:2. Configuration de l’image docker
- Change le contenu du fichier
Dockerfileà la racine du projet :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
FROM node:22-alpine AS builder
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build:compile
FROM node:22-alpine AS runner
WORKDIR /app
COPY . .
COPY --from=builder /app/package-lock.json ./
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
RUN npm ci --omit=dev
EXPOSE 3000
ENV PORT 3000
CMD ["sh", "-c", "npm run payload migrate && npm run build:generate && node server.js"](Ici, j’utilise Node 22 comme exemple. Adapte si besoin.)
3. Configuration du projet NextJs pour la prod
- Dans le fichier
next.config.mjsactive le mode standalone :
1
2
3
4
5
6
7
8
import { withPayload } from '@payloadcms/next/withPayload'
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "standalone",
}
export default withPayload(nextConfig, { devBundleServerPackages: false })- Dans le fichier
package.jsonà la racine, rajoute ces lignes de script :
1
2
3
4
5
6
"scripts": {
...
"build:compile": "next build --experimental-build-mode compile",
"build:generate": "next build --experimental-build-mode generate",
...
},4. Configuration du serveur Web
- Toujours à la racine, crée un nginx.conf :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
upstream payload {
server payload:3000;
}
server {
listen 80;
listen [::]:80;
server_name [domain] www.[domain];
server_tokens off;
location / {
proxy_pass http://payload;
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-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}- Une fois tout configuré, fais un commit et pousse sur ton repo.
1
2
3
git add .
git commit -am "setup docker & nginx"
git pushConfigurer le VPS
Sur le VPS, Docker se chargera d’installer tout ce dont tu as besoin à l’intérieur des conteneurs. Il te suffit d’installer Git et Docker sur la machine hôte.
1. Installer Git
1
2
3
sudo apt update
sudo apt install git -y
git --version2. Installer Docker
Suis la doc officielle de Docker :
1
2
3
4
5
6
7
8
9
10
11
12
13
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update- Installe les packages Docker :
1
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin- Teste l'installation :
1
sudo docker run hello-world3. Créer une clé SSH Git sur ton VPS
Même principe que sur ta machine locale (voir section C), afin de pouvoir cloner ton repo en SSH.
4. Cloner le projet git
- Sur GitHub, récupère l’URL de clonage SSH :

- Sur ton VPS, place-toi dans le dossier où tu veux cloner :
1
git clone git@github.com:MonCompte/mon-projet.git5. Créer le fichier .env
1
2
cd mon-projet
nano .env- écrire les variables d’environnements :
1
2
DATABASE_URI=mongodb://username:password@mongo:27017/payload?authSource=admin
PAYLOAD_SECRET=[Clef secrète payload] (Dans l’exemple : mongo correspond au nom du conteneur Mongo, défini dans docker-compose.yml.)
Pour sauvegarder et quitter Nano : Ctrl + O puis Ctrl + X (ou Cmd + S, Cmd + X sur Mac si SSH sous iTerm, etc.).
5. Lancer les conteneurs Docker
- Crée les images Docker :
1
sudo docker compose build- Lance les conteneurs Docker :
1
sudo docker compose upLe site est presque en ligne ! Manque plus qu’à configurer les DNS pour lier le nom de domaine à l’adresse physique du VPS`
Configurer les DNS
Dans la configuration DNS de ton nom de domaine, ajoute un enregistrement de type A pointant vers l’adresse IP publique de ton VPS :
Par exemple :
- Type : A
- Valeur : 123.456.789.000 (IP de ton VPS)
Tu peux alors accéder à ton interface admin via : http://mon-domaine.fr/adminCréer un certificat SSL pour passer en HTTPS
1. Configuration Nginx de base pour HTTP :
- Dans ton
docker-compose.yml, ajoute (ou modifie) la config pour Nginx et Certbot :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
services:
nginx:
container_name: webserver
restart: always
image: nginx:latest
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/conf.d/nginx.conf:ro
- ./certbot/www:/var/www/certbot/:ro
- ./certbot/conf/:/etc/nginx/ssl/:ro
depends_on:
- payload
entrypoint: "/bin/sh -c 'while :; do sleep 6h; nginx -s reload; done & nginx -g \"daemon off;\"'"
certbot:
restart: always
image: certbot/certbot:latest
volumes:
- ./certbot/www/:/var/www/certbot/:rw
- ./certbot/conf/:/etc/letsencrypt/:rw
#entrypoint: "/bin/sh -c 'while :; do certbot renew; sleep 12h; done'"- Configure
nginx.conf(version initiale pour la phase HTTP) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
listen [::]:80;
server_name [domain].fr www.[domain].fr;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://[domain]$request_uri;
}
}- Commit et push.
- Sur ton VPS git pull et redémarre docker compose :
1
2
git pull
sudo docker compose down && sudo docker compose up2. Générer le certificat avec Certbot
- Teste d’abord en mode
dry-run: (remplace le nom de domaine par le tiens) :
1
2
3
sudo docker compose run --rm certbot certonly \
--webroot --webroot-path /var/www/certbot/ \
--dry-run -d mon-domaine.frLe message "The dry run was successful" devrait s’afficher.
- Si c’est le cas créer les certificats :
1
2
3
sudo docker compose run --rm certbot certonly \
--webroot --webroot-path /var/www/certbot/ \
-d mon-domaine.fr3. Mettre à jour la configuration Nginx pour HTTPS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
upstream payload {
server payload:3000;
}
# Redirection automatique HTTP -> HTTPS
server {
listen 80;
listen [::]:80;
server_name [domain].fr www.[domain].fr;
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://[domain]$request_uri;
}
}
# Serveur HTTPS
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;
server_name [domain].fr www.[domain].fr;
ssl_certificate /etc/nginx/ssl/live/[domain.fr]/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/[domain.fr]/privkey.pem;
location / {
proxy_pass http://payload;
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-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}- Dans
docker-compose.yml, décommente cette ligne pour renouveler automatiquement le certificat :
1
2
3
4
5
6
7
8
certbot:
restart: always
image: certbot/certbot:latest
volumes:
- ./certbot/www/:/var/www/certbot/:rw
- ./certbot/conf/:/etc/letsencrypt/:rw
==> entrypoint: "/bin/sh -c 'while :; do certbot renew; sleep 12h; done'"
- Commit et push.
- Sur ton VPS git pull et redemarre docker compose :
1
2
git pull
sudo docker compose down && sudo docker compose upFélicitations : ton application Payload est maintenant accessible en HTTPS via : https://[votre-domaine]/adminConclusion
Tu as maintenant un environnement complet pour :
- Développer localement (Payload, MongoDB, Next.js).
- Versionner tes modifications via Git et GitHub.
- Déployer sur un VPS avec Docker + Nginx + Certbot pour obtenir un site en HTTPS.
Bonne continuation ! 🐝


