> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.hodi.host/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# Comment configurer un projet avec hodifly.json ?

Hodifly peut prendre ses réglages dans un fichier `hodifly.json` à la racine de votre dépôt, plutôt que dans le formulaire de cPanel. Le fichier est facultatif : sans lui, Hodifly détecte ce qu'est votre projet et le formulaire garde les réglages. Avec lui, le dépôt se configure lui-même, la configuration est versionnée avec votre code et revient en arrière avec lui. Déployer deux fois le même dépôt donne deux projets identiques.

```
{
  "mode": "php",
  "runtime": "php:8.3",
  "docroot": "public",
  "build": "npm run build",
  "persist": ["config/app.yaml", "storage/uploads/"],
  "env": { "required": ["DB_HOST", "DB_USER"] },
  "keepReleases": 5
}
```

Placez-le à la racine du dépôt, ou à la racine du sous-dossier du paquet pour un projet qui vit dans un monorepo. Vous n'avez pas à l'écrire à la main : dans cPanel, ouvrez votre projet et cliquez sur **hodifly.json** pour en générer un à partir des réglages que vous avez déjà.

## Tous les réglages

| Réglage | Ce que ça fait |
| ---- |
| `mode` | Comment le projet est servi : `static`, `node`, `python`, `php` ou `ruby`. Prime sur la détection et sur les réglages du projet. |
| `runtime` | La chaîne qui compile, et pour PHP la version qui sert le site : `node:22`, `php:8.3`, `python:3.12`, `ruby:3.3`, ou `none` pour aucun outillage. Prime sur les réglages du projet, comme `mode`. |
| `install` | Remplace l'installation des dépendances par défaut (`npm ci`, `composer install`). |
| `build` | La commande de build. Une chaîne vide veut dire aucun build : le dépôt est publié tel quel. |
| `output` | Sites statiques uniquement : le dossier produit par votre build (`dist`, `_site`). |
| `docroot` | PHP uniquement : le dossier de front controller dans la release, `public` pour Laravel et Symfony. `"."` sert la racine du dépôt, pour une application qui n'a pas ce dossier. |
| `startup` | Applications Node et Python : le fichier que Passenger exécute pour lancer l'application, relatif à la racine du projet : `server.js`, `dist/main.js` pour un build NestJS, `passenger_wsgi.py`. Voir plus bas. |
| `persist` | Les chemins qui doivent survivre à un déploiement. Voir plus bas. |
| `env.required` | Les **noms** des variables d'environnement sans lesquelles votre projet ne tourne pas. |
| `keepReleases` | Combien de releases garder pour les retours arrière, de 1 à 50. Cinq par défaut. |
| `noindex` | `true` demande aux moteurs de recherche d'ignorer le site, sur chaque réponse. Pour une préproduction. |
| `forceHttps` | Envoie tout visiteur qui arrive en HTTP simple vers l'adresse en `https`. Hodifly le fait déjà tout seul dès que votre domaine a un certificat : ce réglage sert donc surtout à dire `false`. Voir plus bas. |
| `spa` | **Sites statiques uniquement.** Sert `index.html` pour toute adresse qui n'est pas un vrai fichier, pour que les routes d'une application React, Vue ou Angular résistent à un rafraîchissement ou à un lien direct. Déjà automatique quand votre build ressemble à une application monopage : `true` le force, `false` le désactive. |
| `crons` | Des tâches planifiées, écrites comme dans un `vercel.json` : une liste de `{"path": "/api/cron", "schedule": "*/15 * * * *"}`. Chacune appelle cette adresse de votre site selon un horaire. Voir plus bas. |
| `autodeploy` | `false` empêche les push de déployer ; vous déployez à la main depuis cPanel. |
| `previews` | `true` construit une URL de prévisualisation pour chaque pull request. |
| `rebuildEvery` | Reconstruire aussi sur minuterie, en minutes : `0`, `60`, `1440` ou `10080`. |
| `snippets` | Sites statiques uniquement : `{"head": "...", "body": "..."}`, du HTML injecté dans chaque page compilée. |

## Node et Python : le fichier d'entrée

Passenger n'exécute pas `npm start` : il exécute **un fichier**, et `startup` sert à dire lequel. Il accepte un chemin, pas seulement un nom, ce dont une application compilée a besoin :

```
{
  "mode": "node",
  "runtime": "node:22",
  "build": "npm run build",
  "startup": "dist/main.js"
}
```

Trois points à connaître :

- **L'application est quand même lancée depuis la racine du projet**, quelle que soit la profondeur de ce chemin. Les chemins relatifs de votre code, et les dossiers listés dans `persist` (uploads, assets), continuent de fonctionner.
- **Le fichier doit être en CommonJS.** Passenger le charge avec `require()` : une entrée en module ES (un fichier `.mjs`, ou un projet en `"type": "module"`) a besoin d'un petit fichier passerelle à la racine, et `startup` pointe sur la passerelle. Dans un fichier `server.cjs` : `import('./dist/server/server.mjs').catch(e => { console.error(e); process.exit(1); });`. Next.js, Nuxt, Astro, SvelteKit et Remix n'ont besoin de rien de tout ça, Hodifly l'écrit pour eux.
- **Votre serveur doit écouter.** Un build Angular SSR n'écoute que si son `server.mjs` est le module principal, ce qu'il n'est pas sous Passenger : retirez cette condition pour que `listen()` s'exécute toujours, sur `process.env.PORT`.

Vous pouvez aussi le définir dans cPanel, dans le champ **Fichier de démarrage** du projet. Le fichier l'emporte sur le champ.

Une application Ruby n'a pas ce réglage : Rack démarre toujours depuis `config.ru`.

## Ce qu'il ne peut délibérément pas régler

- **Le sous-dossier du paquet et la branche.** C'est par eux que Hodifly trouve ce fichier.
- **Le domaine et le dossier sur votre compte.** Le même dépôt sur deux domaines, ce sont deux projets : l'adresse appartient à l'hébergement, pas au code.
- **Tout ce qui est secret** : les *valeurs* des variables d'environnement, le secret du webhook de déploiement, l'URL du build hook, votre jeton GitLab. Un dépôt est le dernier endroit où ils doivent finir. `env.required` les nomme, cPanel les détient.

## persist : ce qui survit à un déploiement

Chaque déploiement crée une nouvelle release, et les anciennes disparaissent dès qu'il en existe `keepReleases` plus récentes. Tout ce que votre application écrit dans son propre dossier est donc en sursis, et tout ce que votre dépôt ne livre pas est absent de chaque release. `persist` règle les deux : chaque chemin listé est déplacé une fois dans un dossier situé hors de toute release, puis relié dans chaque nouvelle, ce qui lui fait survivre aux déploiements **et** aux retours arrière.

- Un `/` final veut dire **dossier**, sans slash c'est un **fichier**. C'est la seule façon pour Hodifly de savoir quoi créer quand le chemin n'existe encore nulle part.
- **Le premier déploiement fixe le contenu de départ.** Si votre dépôt livre le chemin, cette copie est conservée. Sinon, le chemin est créé vide et le journal de déploiement affiche exactement où, pour que vous le remplissiez en FTP. Rien n'est jamais recopié depuis un fichier `.example` : ce qu'un modèle doit devenir vous appartient.
- **Ensuite, c'est la copie persistée qui gagne.** Une version qui apparaîtrait plus tard dans le dépôt est ignorée.
- Le `storage/` de Laravel, les `var/log` et `var/sessions` de Symfony et toute base SQLite nommée dans votre configuration sont déjà pris en charge. Ne les listez pas.
- Vous ne pouvez pas persister le dossier depuis lequel votre site est servi : il figerait le site sur une release et aucun déploiement ne pourrait plus remplacer le code.

Un retour arrière restaure le code, jamais les données : vos uploads, votre base et votre configuration restent ceux d'aujourd'hui. Voir « [Puis-je revenir en arrière après un mauvais déploiement ?](https://help.hodi.host/fr/article/puis-je-revenir-en-arriere-apres-un-mauvais-deploiement-avec-hodifly-1dw9uxm/) ».

## Tâches planifiées (crons)

`crons` lance des tâches selon un horaire. Il s'écrit exactement comme les `crons` d'un `vercel.json` : un projet qui arrive de Vercel n'a rien à changer.

```
{
  "crons": [
    { "path": "/api/cron/digest", "schedule": "0 7 * * *" },
    { "path": "/wp-cron.php", "schedule": "*/15 * * * *" }
  ]
}
```

- **Une tâche appelle une adresse de votre site.** À chaque échéance, Hodifly demande ce chemin sur le domaine de votre projet, en HTTPS. Votre code y répond comme à n'importe quel visiteur : cela fonctionne de la même façon pour un site statique avec des fonctions API, une application PHP ou une application Node, Python ou Ruby, et c'est toujours la version en ligne qui s'exécute.
- **`schedule`** reprend les cinq champs habituels de cron : minute, heure, jour du mois, mois, jour de la semaine, dans le fuseau horaire du serveur. Les raccourcis comme `@daily` ne sont pas acceptés : écrivez `0 0 * * *`.
- **`path`** commence par `/` et peut porter des paramètres, comme `/cron.php?job=cleanup`.
- **Chaque appel est signé.** N'importe qui connaissant l'adresse peut l'appeler : chaque appel porte donc un en-tête `Authorization: Bearer` contenant la variable d'environnement `CRON_SECRET` du projet. Votre code la compare à `process.env.CRON_SECRET` (ou l'équivalent dans votre langage) et refuse tout le reste.
- **Vous n'avez pas à créer ce secret.** Si le projet n'a pas de `CRON_SECRET`, le déploiement qui ajoute sa première tâche en crée un au hasard et le signale dans le journal de déploiement. Il apparaît dans **Hodifly > votre projet > Variables d'environnement**, où vous pouvez le lire ou le remplacer. Une application Node, Python ou Ruby le reçoit dès ce déploiement ; une application PHP le lit à partir du suivant. Un `CRON_SECRET` que vous avez défini vous-même n'est jamais remplacé.
- Les tâches apparaissent dans **cPanel > Tâches Cron**, dans un bloc marqué comme géré par Hodifly. Ce bloc est réécrit à chaque déploiement : modifiez le fichier plutôt que le bloc. Les tâches que vous ajoutez vous-même en dehors ne sont jamais touchées.
- Retirez la clé (ou le fichier) et le déploiement suivant retire les tâches. Une prévisualisation de pull request n'y touche jamais, et un retour arrière garde celles en place.
- Jusqu'à 20 tâches, avec 5 minutes chacune pour répondre. Si le dépôt contient aussi un `vercel.json` avec des `crons`, la liste de `hodifly.json` la remplace, et le journal de déploiement le signale.

Une application Laravel n'en a pas besoin pour son planificateur : quand votre application planifie des tâches, Hodifly maintient déjà une tâche `schedule:run` chaque minute, en plus de celles que vous listez ici.

## HTTPS : votre site redirige tout seul

Hodifly envoie tout visiteur qui arrive en HTTP simple vers l'adresse en `https` de la même page, avec une redirection permanente. Les sites statiques, les applications PHP et les applications Node, Python ou Ruby en bénéficient toutes, et vous n'avez rien à demander.

Il y a une condition, et c'est toute la raison d'être de `forceHttps` : la redirection n'apparaît qu'une fois qu'un vrai certificat couvre effectivement votre domaine. Le premier déploiement d'un nouveau site arrive presque toujours avant que le certificat soit émis, et envoyer les visiteurs vers un `https` que leur navigateur refuse rendrait le site indisponible jusqu'à son arrivée. Le premier déploiement est donc servi en clair et le signale dans son journal, le certificat est émis, et le déploiement suivant active la redirection de lui-même.

- `"forceHttps": false` désactive la redirection, pour un site qui a une raison de répondre en clair.
- `"forceHttps": true` redirige sans attendre le certificat. À n'utiliser que si vous savez qu'il est déjà là : tant qu'il ne l'est pas, le site est injoignable.

Les adresses que votre autorité de certification vérifie, sous `/.well-known/`, ne sont jamais redirigées : l'émission et le renouvellement continuent de fonctionner en HTTP.

## Quels réglages s'appliquent quand

Hodifly relit le fichier depuis votre code à **chaque déploiement** pour tout ce qui décrit le build : `build`, `install`, `output`, `docroot`, `startup`, `persist`, `env.required`, `keepReleases`, `noindex`, `forceHttps`, `spa` et `crons`. Vous modifiez, vous poussez, c'est fait.

`startup` est dans cette liste à dessein : c'est le build qui décide quel fichier lance votre application, donc déplacer votre point d'entrée ne doit jamais obliger à retourner dans cPanel pour que quelque chose démarre. La valeur utilisée est réenregistrée sur le projet : le champ **Fichier de démarrage** affiche donc ce qui tourne réellement.

`mode` et `runtime` l'emportent eux aussi à chaque déploiement. Ils décident de la façon dont votre application est installée avant toute compilation : Hodifly les lit donc dans votre dépôt, au commit déployé. S'ils diffèrent du projet, le déploiement bascule d'abord le projet (avec la commande de build, le dossier publié et le fichier de démarrage adaptés au nouveau mode), et les premières lignes du journal de déploiement l'indiquent. Ensuite, la page **Réglages** affiche la valeur comme définie par `hodifly.json` : pour la changer, modifiez le fichier et poussez.

> Votre offre d'hébergement décide toujours des types d'application possibles. Si le fichier demande une application Node.js, Python ou Ruby et que votre offre ne les inclut pas, le projet garde son mode actuel et le journal de déploiement explique pourquoi. Revenir à une version construite dans un autre mode est aussi refusé : redéployez plutôt ce commit.

Le reste (`autodeploy`, `previews`, `rebuildEvery`, `snippets`) s'applique à la création du projet, ou quand vous changez son sous-dossier de paquet. Modifier l'un d'eux plus tard dans le fichier suppose de le modifier aussi dans le formulaire.

Là où `hodifly.json` et un « [vercel.json](https://help.hodi.host/fr/article/puis-je-utiliser-un-fichier-verceljson-172supy/) » disent la même chose, `hodifly.json` l'emporte, et le journal de déploiement le signale.

## Vérifier un fichier avant de le pousser

Collez-le dans le validateur sur [hodifly.app/fr/validate](https://hodifly.app/fr/validate/). Il vous dit si le fichier est valide et, plus utile encore, ce qu'il fera exactement au prochain déploiement.

## Bon à savoir

- Un fichier qui n'est pas du JSON valide ne casse jamais un déploiement : il est ignoré, avec un avertissement dans le journal, et le déploiement continue avec les réglages du formulaire.
- Limites : 256 Ko pour le fichier, 500 réglages, 4 Ko par valeur.
- `env.required` est un bon filet de sécurité. S'il manque une variable, le déploiement s'arrête en quelques secondes en la nommant, au lieu de laisser votre site répondre une page blanche.