Aller au contenu

Aller au sommaire de la doc

while.yaml

while.yaml, à la racine de votre appli, dit ce dont elle a besoin. Votre agent l’écrit, et cette page en donne chaque champ.

Mis à jour le 9 novembre 2026.

Voir en Markdown

while.yaml
apiVersion: while/v1
project: planning
services:
  - name: web
    port: 3000
    health: { path: /health }
databases:
  - name: main

Ce fichier décrit un projet : ses services, ses bases, ses caches, son stockage, ses files, ses tâches planifiées, ses domaines, ses environnements. while en fait l’infrastructure. Un projet sans service web est permis, s’il déclare au moins une base ou une tâche planifiée.

Le fichier

ChampTypeCe qu’il fait
apiVersion (obligatoire)toujours while/v1La version du format : toujours while/v1.
project (obligatoire)texte (minuscules)L’identifiant du projet, en minuscules.
servicesliste de servicesLes services de l’appli. Ils sont facultatifs quand le projet déclare au moins une base ou une tâche planifiée : un projet de données n’a pas toujours de service web.
databasesliste de bases, ou de bases d’autres projetsLes bases PostgreSQL du projet, ou les bases d’autres projets qu’il lit. Quatre au plus.
cachesliste de cachesLes caches Valkey du projet, qui parlent le protocole Redis. Quatre au plus.
bucketsliste de bucketsLes buckets S3 du projet, pour ses fichiers. Quatre au plus.
cronsliste de tâches planifiéesLes tâches planifiées : une commande lancée à heure fixe, dans l’image d’un service, ou construite pour elle quand le projet n’a pas de service. Chaque passage est suivi (historique, échecs, passages manqués), et se relance ou se rattrape à la demande.
environmentsobjetLes réglages propres à un environnement. La clé est le nom de l’environnement : production, preview…
telemetryobjetCe que while garde de l’appli : ses journaux, ses métriques, ses traces et ses erreurs.
telemetry.logstrue ou falsetrue garde la sortie de l’appli dans ses journaux. Par défaut : true.
telemetry.metricstrue ou falsetrue compte les requêtes, les erreurs et les temps de réponse de l’appli. Par défaut : true.
telemetry.tracestrue ou falsetrue garde les traces OpenTelemetry de l’appli. Par défaut : false.
telemetry.errorstrue ou falsetrue donne à l’appli un point d’entrée compatible Sentry, dont while fournit l’adresse (DSN). Par défaut : true.
telemetry.uptimeobjetUne sonde de disponibilité : un chemin de l’appli, appelé à intervalle régulier.
networkobjetLes sorties réseau de l’appli. Internet lui est fermé par défaut (egress: restricted) : une API externe se déclare en connexion (declare_connection), while ajoute sa clé et passe en IPv4 s’il le faut, et l’appli l’appelle par <NOM>_URL. egress: all ouvre Internet en direct, après la validation d’une personne. Un changement vaut à la mise en ligne suivante.
network.egressnone, restricted, allnone ferme tout accès à Internet. restricted (défaut) ferme Internet, sauf les connexions déclarées et la liste allow, qui passent par la sortie de while. all ouvre Internet en direct, en IPv6 comme en IPv4, après validation. Par défaut : restricted.
network.allowliste de textesLes noms d’hôtes permis quand egress vaut restricted. Ils sont appelés par la sortie de while, jamais en direct. Pour une API qui demande une clé, préférez une connexion.

Les services

Chaque entrée de services décrit un service : un site, une API, un worker ou un site statique.

ChampTypeCe qu’il fait
name (obligatoire)texte (minuscules)Le nom du service, en minuscules. Il entre dans son adresse et dans SERVICE_<NOM>_URL.
descriptiontexteUne ligne pour qui ouvre le service, sous son titre dans la page de ses applis (« Les ventes du jour, par magasin ») : 140 caractères au plus, sans rien de technique. Sans elle, la page montre l’adresse.
typeweb, worker, staticweb : un service HTTP, avec son adresse. worker : un processus sans adresse ni sonde HTTP, comme une file de travaux ou un consommateur. static : un site statique, servi avec un cache HTTP. Par défaut : web.
roottextePour un site statique : le dossier à servir une fois le site construit (dist, build, public…). Par défaut : ..
sourcetexteLe chemin des sources dans l’archive envoyée, ou dans le dépôt git. Par défaut : ..
imagetexteUne image déjà construite, dans un registre externe ou dans celui de while, de préférence avec son digest.
dockerfiletexteLe chemin du Dockerfile. Sans lui, while reconnaît le langage et écrit le Dockerfile.
buildobjetLa construction de l’image du service.
build.contexttexteLe dossier de contexte de la construction. Par défaut : ..
build.targettexteL’étage du Dockerfile à construire (—target).
build.argsobjetLes arguments de construction (—build-arg), non secrets : ils restent dans l’historique et la provenance de l’image. Un nom qui ressemble à un secret (TOKEN, KEY, SECRET, PASSWORD) est refusé : passez par secrets.
build.secretsliste de textesLes noms des secrets de construction, comme NPM_TOKEN. Leur valeur se pose à part, avec set_env { build: true } ou la case « pour la construction » des réglages, jamais ici. Ils sont montés le temps d’un RUN dans /run/secrets/<NOM>, jamais dans l’image, et masqués au journal. Une construction ne lit jamais les secrets de l’appli, et l’appli ne reçoit pas ceux de la construction.
build.testtexteLa commande des tests, jouée dans le même bac à sable que la construction. Par défaut, celle du langage reconnu.
build.skip_teststrue ou falsetrue ne joue pas les tests à la construction de ce service. Par défaut : false.
commandliste de textesLa commande qui démarre le service, à la place de celle de l’image, par exemple ["node", "server.js"].
portnombre entierLe port sur lequel le service écoute. while le donne à l’appli dans la variable PORT. Par défaut : 8080. De 1 à 65535.
publictrue ou falsetrue expose le service sur un domaine public. Par défaut : true.
accesspublic, internalpublic ouvre le service à tout Internet. interne le met derrière la connexion de while, ou celle de l’entreprise : l’appli reçoit l’identité dans X-While-Email, X-While-Name, X-While-Groups et X-While-Identity. Sans groupes, emails ni email_domains, les membres de l’organisation entrent. Rendre publique une appli interne, ou changer qui y entre, demande une validation. Par défaut : public.
emailsliste de textesPour l’accès interne : les adresses qui entrent, membres de l’organisation ou non.
domainsliste de textesLes domaines personnalisés du service. while lui donne toujours aussi son adresse par défaut.
healthobjetLa sonde de santé : while appelle ce chemin chaque seconde, et une version ne reçoit du trafic qu’une fois qu’il répond 2xx ou 3xx.
health.pathtexteUn chemin de l’appli. Il commence par un seul « / », sans adresse complète, sans « // », sans contre-oblique ni espace. Par défaut : /health.
health.initial_delay_secondsnombre entierLe délai avant le premier appel de la sonde, en secondes. Par défaut : 0.
health.timeout_secondsnombre entierLe temps que la sonde attend une réponse, en secondes. Par défaut : 3.
health.startup_timeout_secondsnombre entierLe temps qu’une nouvelle version a pour répondre à sa sonde, en secondes, avant d’être refusée (la version en ligne garde le trafic). 120 par défaut, 900 au plus : pour une appli qui migre sa base au démarrage (Metabase, Keycloak). Une version vraiment cassée met alors ce temps à être dite en échec. Par défaut : 120. De 30 à 900.
envobjetLes variables d’environnement. Une valeur { secret: chemin } est lue dans le coffre de while.
resourcesobjetLe processeur et la mémoire réservés pour chaque instance du service.
resources.cpuprocesseur (500m, 1)Une quantité de processeur : 500m pour un demi-vCPU, 1 pour un vCPU. Par défaut : 200m.
resources.memorymémoire (256Mi, 1Gi)Une quantité de mémoire : 256Mi, 1Gi. Par défaut : 192Mi.
resources.diskdisque (1Gi)Pour un worker ou une tâche : le disque de /tmp, sur le disque du nœud et pas en mémoire, qui est aussi la limite de stockage du conteneur. 1 Gio par défaut, 8 Gio au plus. Sans effet sur un service web, dont le /tmp est pris sur sa mémoire. Par défaut : 1Gi.
volumevolumeUn disque qui survit aux mises en ligne, aux redémarrages et à la perte d’un nœud, pour un worker ou une tâche, monté par une instance à la fois. Retiré du while.yaml, il est gardé 7 jours, puis détruit.
scaleobjetLe nombre d’instances du service, entre min et max.
scale.minnombre entierLe nombre d’instances gardées tant que le service ne dort pas (voir veille). 0 est l’ancienne façon de dire sleep: 30m : préférez veille. Par défaut : 1. De 0 à 5.
scale.maxnombre entierLe plafond d’instances quand le trafic monte : 10 au plus si scale.max n’est pas déclaré. Par défaut : 1. De 1 à 5.
usesliste de textesLes bases, caches, stockages ou files dont se sert ce service. Par défaut, tout ce que déclare le projet.
titletexteLe titre que voient les personnes, écrit du point de vue de qui s’en sert (« Lecture des ventes », « Import des commandes, chaque heure ») : 80 caractères au plus, sur une ligne, sans rien de technique. Sans titre, les écrans montrent le nom.
sleepdélai (30m, 2h) ou neverLa mise en veille d’un service web ou d’un site statique. Un délai (30m, 2h) l’endort après ce temps sans requête : la requête suivante le réveille en quelques secondes, et attend sa réponse. non (ou false) lui garde toujours au moins une instance. Par défaut : non en production, 30m dans les autres environnements, comme les prévisualisations. Un service qui dort repart d’une instance au réveil : scale.min ne compte que s’il ne dort pas. Un worker ne dort jamais, une base de production non plus.
groupsliste de textesPour l’accès interne : les groupes de l’organisation qui entrent, faits dans while ou venus de la connexion d’entreprise.
memberstrue ou falsePour l’accès interne avec groupes, emails ou email_domains : true laisse entrer aussi les membres de l’organisation. Sans ce champ, seules les listes entrent. Sans listes, les membres entrent déjà.
email_domainsliste de textesPour l’accès interne : les domaines d’adresse qui entrent. Un domaine vaut exactement : nextmap.io n’ouvre pas fr.nextmap.io.
connectionsliste de noms de connexionsLes connexions de l’organisation, des API externes déclarées dans while, qu’appelle ce service ou cette tâche. Pour « meteo », l’appli reçoit METEO_URL, l’adresse du relais, jeton compris. La clé reste dans while, et chaque appel est tracé.

Les bases

Chaque entrée de databases déclare une base PostgreSQL. Une entrée avec from lit la base d’un autre projet, sans rien créer.

ChampTypeCe qu’il fait
name (obligatoire)texte (minuscules)Le nom de la base, en minuscules. Il entre dans ses variables, comme DB_<NAME>_URL.
enginepostgresLe moteur de la base : postgres, le seul. Par défaut : postgres.
versiontexteLa version de PostgreSQL : 16, 17 ou 18. Par défaut : 17.
sizemémoire (256Mi, 1Gi)Le disque de la base, facturé au Gio par mois. Par défaut : 1Gi.
computeS, M, L, XLLa taille d’une instance : le processeur et la mémoire réservés, avec les réglages de PostgreSQL et du pooler qui suivent. S : 0,1 vCPU et 256 Mo (jusqu’à 1 Go). M : 0,5 vCPU et 1 Go. L : 1 vCPU et 4 Go. XL : 2 vCPU et 8 Go. Un changement de taille redémarre la base. Ne la confondez pas avec size, le disque. Par défaut : S.
pooltransaction, sessionLe mode du pooler (PgBouncer) devant la base. transaction, le défaut : chaque transaction peut prendre une autre connexion au serveur ; beaucoup de clients pour peu de connexions, mais ce qui tient à une session ne dure que sa transaction. session : une connexion au serveur par client connecté, gardée tant qu’il reste connecté ; le pooler n’accepte pas plus de clients que la taille de la base n’a de connexions (S 20, M 60, L 100, XL 140), le client de trop est refusé. Choisissez session pour une appli qui a besoin de sa session : les migrations Liquibase (Metabase, Keycloak) ou Flyway, qui prennent un verrou consultatif de session, un verrou consultatif de session posé par l’appli, LISTEN/NOTIFY, une table temporaire. Par défaut : transaction.
instances1, 2 ou 3Le nombre d’instances PostgreSQL de la base. Avec 1, une seule instance tourne sur le disque d’un nœud, et une panne du nœud se répare par une restauration. Avec 2 ou 3, la base est en haute disponibilité : une ou deux instances de secours sont tenues à jour en continu, et prennent le relais d’elles-mêmes si la principale tombe. Chaque instance a son propre disque (size). Ne le confondez pas avec replica, une réplique en lecture pour query_database.
replicatrue ou falsePrévue : une réplique en lecture, tenue à jour en continu, que lira l’outil query_database des agents. Le champ est accepté dès maintenant. Tant que la réplique n’est pas servie, query_database lit la base principale, dans une transaction en lecture seule, et le dit dans sa réponse. Par défaut : false.
backupobjetLes sauvegardes de la base.
backup.scheduletexteL’heure de la sauvegarde complète du jour, au format cron, en UTC. Par défaut : 0 3 * * *.
backup.retention_daysnombre entierLu mais pas suivi : while garde les sauvegardes 14 jours, pour toutes les bases. Par défaut : 7.
backup.test_restoretrue ou falsewhile rejoue la restauration de chaque sauvegarde, et affiche le résultat. Par défaut : true.

Lire la base d’un autre projet

La base d’un autre projet de la même organisation, que lisent les applis de ce projet : rien n’est créé. La première mise en ligne qui la déclare demande la validation des approbateurs de cette base. Une fois validée, chaque appli lectrice reçoit DB_<NAME>_URL, DB_<NAME>_USER et DB_<NAME>_PASSWORD, un accès en lecture seule que les approbateurs peuvent restreindre à des schémas, des tables ou des colonnes. La base d’une autre organisation est refusée.

ChampTypeCe qu’il fait
nametexte (minuscules)Son nom dans ce projet, qui fait la variable DB_<NAME>_URL. Par défaut, <projet>-<base> (DB_ENTREPOT_MAIN_URL).
from (obligatoire)texte<projet>/<base> : un projet de la même organisation, et le nom de sa base.
accessreadlecture : la seule valeur, la lecture seule. Par défaut : read.
environmenttexteL’environnement de la base source. Par défaut : production.
readersliste de textesLes applis qui la lisent : un service, ou task:<nom>. Sans ce champ, toutes celles du projet.

Les caches

Chaque entrée de caches déclare un cache Valkey, qui parle le protocole Redis.

ChampTypeCe qu’il fait
name (obligatoire)texte (minuscules)Le nom du cache, en minuscules. Il entre dans ses variables, comme CACHE_<NOM>_URL.
enginevalkeyLe moteur du cache : valkey, le seul. Par défaut : valkey.
memorymémoire (256Mi, 1Gi)La mémoire réservée pour le cache. Par défaut : 64Mi.
durabletrue ou falsetrue garde les données sur disque (journal AOF), sans jamais les évincer : pour une file de tâches (BullMQ, Sidekiq, Celery). Sans lui, un redémarrage vide le cache. Par défaut : false.

Les buckets

Chaque entrée de buckets déclare un bucket S3.

ChampTypeCe qu’il fait
name (obligatoire)texte (minuscules)Le nom du bucket, en minuscules. Il entre dans sa variable, comme S3_BUCKET_<NOM>.
publictrue ou falsetrue ouvre la lecture des objets à tous, sans clé, après une validation. Par défaut : false.
corsliste de textesLes origines de plus d’où un navigateur ouvre une URL présignée de ce bucket (https://hôte[:port]). Celles de l’appli y sont déjà.

Les tâches planifiées

Les tâches planifiées : une commande lancée à heure fixe, dans l’image d’un service, ou construite pour elle quand le projet n’a pas de service. Chaque passage est suivi (historique, échecs, passages manqués), et se relance ou se rattrape à la demande.

ChampTypeCe qu’il fait
name (obligatoire)texte (minuscules)Le nom de la tâche, en minuscules.
schedule (obligatoire)texteLe rythme au format cron, en 5 champs, dans le fuseau de timezone (Europe/Paris par défaut) : « 0 3 * * * » lance la tâche chaque jour à 3 h.
command (obligatoire)liste de textesLa commande à lancer, par exemple ["node", "cron.js"].
servicetexte (minuscules)Le service dont la tâche reprend l’image et les variables : le premier service par défaut. Sans service déclaré, ou avec image, source, dockerfile ou build, la tâche est construite pour elle-même.
imagetexteUne image déjà construite pour une tâche sans service, de préférence avec son digest.
sourcetextePour une tâche sans service : le chemin des sources dans l’archive envoyée, ou dans le dépôt git. Par défaut : ..
dockerfiletextePour une tâche sans service : le chemin du Dockerfile. Sans lui, while reconnaît le langage.
buildobjetLa construction de l’image du service.
build.contexttexteLe dossier de contexte de la construction. Par défaut : ..
build.targettexteL’étage du Dockerfile à construire (—target).
build.argsobjetLes arguments de construction (—build-arg), non secrets : ils restent dans l’historique et la provenance de l’image. Un nom qui ressemble à un secret (TOKEN, KEY, SECRET, PASSWORD) est refusé : passez par secrets.
build.secretsliste de textesLes noms des secrets de construction, comme NPM_TOKEN. Leur valeur se pose à part, avec set_env { build: true } ou la case « pour la construction » des réglages, jamais ici. Ils sont montés le temps d’un RUN dans /run/secrets/<NOM>, jamais dans l’image, et masqués au journal. Une construction ne lit jamais les secrets de l’appli, et l’appli ne reçoit pas ceux de la construction.
build.testtexteLa commande des tests, jouée dans le même bac à sable que la construction. Par défaut, celle du langage reconnu.
build.skip_teststrue ou falsetrue ne joue pas les tests à la construction de ce service. Par défaut : false.
envobjetLes variables d’environnement. Une valeur { secret: chemin } est lue dans le coffre de while.
usesliste de textesPour une tâche sans service : les bases, caches, stockages ou files dont elle se sert. Par défaut, tout ce que déclare le projet.
resourcesobjetPar défaut, celles du service repris, et 100 mCPU et 128 Mio pour une tâche sans service.
resources.cpuprocesseur (500m, 1)Une quantité de processeur : 500m pour un demi-vCPU, 1 pour un vCPU.
resources.memorymémoire (256Mi, 1Gi)Une quantité de mémoire : 256Mi, 1Gi.
resources.diskdisque (1Gi)Pour un worker ou une tâche : le disque de /tmp, sur le disque du nœud et pas en mémoire, qui est aussi la limite de stockage du conteneur. 1 Gio par défaut, 8 Gio au plus. Sans effet sur un service web, dont le /tmp est pris sur sa mémoire.
volumevolumeUn disque qui survit aux mises en ligne, aux redémarrages et à la perte d’un nœud, pour un worker ou une tâche, monté par une instance à la fois. Retiré du while.yaml, il est gardé 7 jours, puis détruit.
timeout_secondsnombre entierLa durée maximale d’un passage. Au-delà, il est arrêté et compté « délai dépassé ». Par défaut : 600. De 10 à 21600.
retriesnombre entierLe nombre de nouvelles tentatives après un échec, dans le même passage. Par défaut : 0. De 0 à 5.
concurrencyforbid, allow, replaceforbid empêche deux passages en même temps, et refuse un passage manuel tant qu’un autre tourne. allow permet le chevauchement. replace fait arrêter le passage en cours par le nouveau. Par défaut : forbid.
timezonetexteLe fuseau horaire du rythme, en nom IANA : Europe/Paris, UTC… Par défaut : Europe/Paris.
titletexteLe titre que voient les personnes, écrit du point de vue de qui s’en sert (« Lecture des ventes », « Import des commandes, chaque heure ») : 80 caractères au plus, sur une ligne, sans rien de technique. Sans titre, les écrans montrent le nom.
connectionsliste de noms de connexionsLes connexions de l’organisation, des API externes déclarées dans while, qu’appelle ce service ou cette tâche. Pour « meteo », l’appli reçoit METEO_URL, l’adresse du relais, jeton compris. La clé reste dans while, et chaque appel est tracé.

Les environnements

Les réglages propres à un environnement. La clé est le nom de l’environnement : production, preview…

ChampTypeCe qu’il fait
fromtexte (minuscules)L’environnement de référence dont celui-ci hérite.
servicesliste de objetsLes réglages des services dans cet environnement.
databasesliste de objetsLes réglages des bases dans cet environnement.
ttl_hoursnombre entierLa durée de vie avant la destruction automatique, pour un environnement de prévisualisation. De 1 à 720.

Le schéma complet

Le schéma JSON de while.yaml est public, à https://app.while.sh/schema/while.v1.json. Votre agent le lit pour vérifier son fichier avant de mettre en ligne.

Branchez votre agent, il s’occupe du reste

À coller dans votre agent

Lis while.sh/agents, puis mets mon appli en ligne avec while.

Copier les instructions

Pas besoin de compte pour essayer : votre appli est en ligne tout de suite. Pour la garder, connectez-vous.

Un projet pour votre entreprise ? Parlez à l’équipe : hello@while.sh