Blueprints
Un blueprint décrit un projet complet — environnements, briques managées, services, domaines, liaisons — dans un fichier YAML que vous pouvez commiter à côté de votre code.
Il sert à deux choses :
- recréer un projet entier ailleurs — un environnement de recette qui ressemble vraiment à la production, un projet repris par un collègue, une remise en route après un incident ;
- ajouter des ressources à un projet existant — un service de plus, une brique managée de plus, décrits dans un fichier partiel.
Vous n’avez pas à choisir entre les deux : c’est le fichier qui désigne le projet visé, par son
identifiant (project.slug). S’il correspond à un projet que vous avez déjà, la plateforme le
complète ; sinon, elle le crée.
Où se trouvent ces actions
Section intitulée « Où se trouvent ces actions »Exporter est une action de la barre d’outils du projet — l’icône de téléchargement, en haut à droite de son écran.
Importer vit ailleurs : dans « Importer », au bas du menu latéral. Ce n’est pas un oubli. Par défaut, le fichier porte lui-même son projet et ses environnements, identifiés par leur slug : l’écran d’un projet ne peut donc pas en être la cible. Pour importer dans un environnement précis, voir Importer dans un environnement.
L’écran d’import renvoie aussi vers le catalogue de blueprints, pour partir d’un exemple complet plutôt que d’une page blanche.
Ce qu’un blueprint ne contient jamais
Section intitulée « Ce qu’un blueprint ne contient jamais »Trois choses en sont absentes, et c’est délibéré.
Aucun secret. Une variable marquée secrète n’y figure que par son nom, jamais par sa valeur. Une variable en clair, elle, y figure avec sa valeur : c’est ce qui permet de recréer ou de dupliquer un environnement à l’identique.
Aucun identifiant technique. Rien de ce qui désigne notre infrastructure n’y apparaît. Un tel identifiant ne voudrait rien dire ailleurs : le fichier ne serait rejouable que chez vous.
Aucun état. Ni statut, ni date de déploiement. Un blueprint décrit ce que vous voulez, pas ce qui tourne à l’instant où vous l’exportez.
Exporter
Section intitulée « Exporter »Depuis la barre d’outils du projet, demandez son blueprint. Vous obtenez un fichier de cette forme :
apiVersion: cassiope.eu/v1alpha2kind: Blueprintproject: slug: mon-projet name: Mon projet environments: - slug: production name: Production addons: - slug: base name: Base principale templateKey: postgresql version: "17" resources: { cpuMillicores: 500, ramMb: 512, diskGb: 10 } services: - slug: api name: API type: web source: gitProvider: github gitRepo: mon-org/mon-api gitBranch: main env: - key: LOG_LEVEL value: info - key: STRIPE_KEY fromSecret: true domains: - hostname: api.mon-domaine.fr bindings: - addon: basefromSecret: true signale une valeur secrète, à fournir au moment de l’import — voir plus bas.
Le fichier décrit aussi :
- les réglages de chaque environnement : type, branche par défaut, préférences de placement, rétention des déploiements ;
- les stacks : le compose d’une stack créée par image (il n’existe que chez nous), l’emplacement du compose et l’override géré d’une stack Git, la capacité de chaque conteneur, les conteneurs exposés, les volumes et les variables ;
- les volumes des services, leur taille et leur point de montage (vides : les données ne sont pas dans le fichier) ;
- les liens entre services et stacks, avec les variables recopiées.
Un fichier cassiope.eu/v1alpha1, produit avant ces ajouts, s’importe toujours.
Prévoir avant d’appliquer
Section intitulée « Prévoir avant d’appliquer »Choisissez votre fichier .yaml, puis demandez l’aperçu. (Un fichier, et non un copier-coller :
un blueprint fait des dizaines de lignes, et un collage tronqué ou ré-indenté ne se voit pas.)
L’aperçu commence par dire lequel des deux usages il s’apprête à jouer — « ce projet n’existe pas encore, il sera créé entièrement », ou « ce projet existe déjà, le fichier y ajoute telles ressources ». Le reste est le détail, ligne à ligne. Il vous dit, sans rien modifier :
| Ce que vous lisez | Ce que ça veut dire |
|---|---|
| à créer | la ressource n’existe pas encore |
| à mettre à jour | elle existe, et le fichier en diffère |
| inchangée | rien à faire |
| hors du fichier | elle existe chez vous, mais ce blueprint ne la décrit pas |
| bloquée | le changement demandé est impossible sans perdre des données |
| valeurs manquantes | des secrets restent à fournir |
L’aperçu vérifie aussi que l’ensemble tient dans votre offre : nombre de projets, d’environnements, de services, de briques et de domaines, puis vCPU, RAM et stockage cumulés de tout ce qui sera créé. Si ça ne tient pas, il indique ce qui dépasse et propose l’offre qui suffirait, ou le support quand la limite est propre à votre compte. L’application n’est alors pas proposée : elle serait refusée avant toute écriture plutôt que de créer la moitié du projet.
Une ressource bloquée arrête l’application entière, avant toute écriture. C’est le cas si vous changez le type d’une brique existante : ce n’est pas une modification, c’est un remplacement — et un remplacement détruit les données. Donnez-lui un autre identifiant, ou supprimez l’ancienne vous-même.
Importer dans un environnement
Section intitulée « Importer dans un environnement »Sur l’écran Importer, le sélecteur « Importer dans » vaut « Selon le fichier » par défaut.
Choisissez un projet puis un environnement pour appliquer le fichier dans celui-ci, quel que
soit le slug qu’il porte (le staging d’un fichier peut ainsi compléter votre dev).
- Le fichier ne doit décrire qu’un seul environnement — exportez l’environnement, pas le projet. Sinon l’import est refusé.
- Le diff ne compare le fichier qu’au contenu de cet environnement : les autres environnements du projet ne sont ni modifiés ni signalés « hors du fichier ».
- Les réglages de l’environnement (type, branche, placement, rétention) ne sont jamais touchés.
- Ce qui existe déjà dans l’environnement (même slug) n’est pas recréé ; seul le manquant est ajouté. Le chemin des variables secrètes à fournir porte le slug de l’environnement choisi.
- Vaut aussi pour une archive avec données : les données ne sont restaurées que dans ce que l’import crée.
Fournir les secrets
Section intitulée « Fournir les secrets »Les valeurs ne sont jamais dans le blueprint. Par l’API ou l’agent, elles forment un second document (values) :
{ "production/api": { "STRIPE_KEY": "sk_live_…" }}Dans l’interface, vous n’écrivez pas ce document : après « Prévisualiser », l’encadré Valeurs secrètes à fournir affiche un champ masqué par variable manquante, groupé par chemin. Tant qu’un champ est vide, « Appliquer » reste grisé. Les valeurs saisies restent dans la page, ne sont jamais enregistrées dans le navigateur, et sont effacées quand vous choisissez un autre fichier.
Le chemin (production/api) est celui que l’aperçu affiche : vous n’avez rien à traduire. Il vaut
aussi pour les variables secrètes d’une stack (production/<stack>).
Deux refus protègent cette étape :
- une valeur manquante arrête l’import. Elle n’est jamais remplacée par une chaîne vide : votre service démarrerait avec une configuration que rien ne distingue d’un choix délibéré, et la panne se découvrirait bien plus tard ;
- une valeur fournie pour une variable que le blueprint ne déclare pas est refusée. Ce document ne sert qu’à remplir les cases prévues, jamais à en ajouter.
Appliquer
Section intitulée « Appliquer »L’application crée ce qui manque et ajuste ce qui diffère — elle n’enlève jamais rien. Elle est rejouable : appliquer deux fois le même fichier ne crée pas de doublon — chaque ressource est retrouvée par son identifiant.
Elle crée les environnements (avec leur type et leurs préférences de placement), les briques, les services (variables, volumes, exposition interne, domaines, liaisons), les stacks et les liens entre services et stacks. Rien n’est déployé par défaut : vous déployez quand vous le souhaitez, ou dans l’ordre de vos dépendances avec l’option décrite plus bas.
Limites à connaître :
- une ressource qui existe déjà n’est pas modifiée (service, stack, réglages d’un environnement). Sa mise à jour toucherait ce que produira son prochain déploiement. Nous ne changeons pas cela en silence : l’aperçu vous le signale, et vous l’appliquez depuis son écran ;
- une liaison est créée, mais pas encore active. Le mot de passe dédié à votre service est généré à son premier déploiement, une fois la brique prête et la machine du service connue ; vous n’avez rien à relancer ;
- un lien prend effet au prochain déploiement du service ou de la stack qui le consomme. Une variable recopiée qui était secrète chez le producteur n’est pas reprise : elle n’est pas dans le fichier ;
- une stack ou une brique peut échouer après la création du reste (compose refusé, dépôt inaccessible, aucune capacité disponible) : le rapport la marque en échec avec sa raison, et vous pouvez la recréer depuis son écran.
Le rapport d’application liste enfin ce qui reste à faire de votre côté :
- les valeurs secrètes à saisir ;
- les valeurs régénérées : une stack Git tire une nouvelle valeur pour les secrets que son compose attend. Remplacez-la si l’ancienne compte, par exemple une clé de signature ;
- les domaines à configurer ;
- le mot de passe d’un registry privé, qui n’est jamais exporté ;
- la clé de déploiement à ajouter à un dépôt Git privé. Elle est posée automatiquement si votre compte GitHub est connecté ; sinon, elle est affichée sur l’écran de la ressource.
Ordre de déploiement
Section intitulée « Ordre de déploiement »Appliquer ne déploie rien. Cochez Déployer après l’application dans l’écran d’import (ou
passez deploy: true à l’API) pour lancer, juste après, le déploiement de ce que l’application
vient de créer. Une ressource qui existait déjà n’est jamais redéployée.
Par défaut, les ressources sont lancées l’une après l’autre. Quand l’une doit passer après une
autre — un collecteur qui se connecte à un broker, une application qui attend que la base ait
exécuté ses migrations — déclarez-le avec dependsOn :
services: - slug: emqx healthcheckCommand: /opt/emqx/bin/emqx ctl status # … - slug: ingestion dependsOn: [emqx] # …- « Après » veut dire après le succès du déploiement de la ressource attendue. Or un déploiement ne réussit que si son healthcheck rend un verdict sain : les scripts de démarrage (migrations, amorçage) sont donc terminés.
- Les ressources sont lancées dans l’ordre des dépendances. Le déploiement de la première peut démarrer la machine de la suivante : l’ordre est séquentiel, pas parallèle.
- Si une ressource échoue, celles qui en dépendent — directement ou non — ne sont pas lancées : elles sont marquées annulées, avec la ressource fautive en cause. Les ressources indépendantes sont déployées normalement.
dependsOnpeut viser un service ou une stack du même environnement. Une dépendance qui n’est pas déployée par cette application (elle existait déjà) n’est pas attendue.- Une référence à une ressource inconnue, à soi-même ou un cycle est refusé à l’aperçu.
Sans healthcheck, l’attente est plus faible. Un service bâti depuis un dépôt Git (hors
Dockerfile) avec un port exposé reçoit un healthcheck par défaut. Un service lancé depuis une image
ou un Dockerfile n’en a aucun tant que vous n’avez pas écrit healthcheckCommand : l’attente ne
porte alors que sur le démarrage du conteneur. L’aperçu vous avertit de ce cas. La commande ne peut
contenir que des lettres, chiffres, espaces et - _ . / : = @ , + (pas de |, && ni $) ;
une commande hors de ce jeu serait ignorée par le moteur, le blueprint la refuse donc.
Limites : dependsOn n’est pas conservé après l’application et n’est pas repris par l’export — il
ne décrit que l’ordre d’un déploiement initial. Si un déploiement ne peut pas être préparé (quota,
aucune capacité disponible), rien n’est lancé et le rapport le dit : l’application, elle, reste faite.
Avec les données : l’archive
Section intitulée « Avec les données : l’archive »Un fichier YAML décrit un projet ; il ne transporte pas son contenu. Pour déplacer ou sauvegarder un projet avec ses données, exportez une archive : bouton Avec les données, à côté de Exporter, dans la barre d’outils du projet. Réservé aux owners et admins du compte.
L’archive contient :
- le blueprint du projet, identique au fichier YAML ;
- le contenu des bases de données qui savent se restaurer (PostgreSQL) ;
- le contenu des volumes de 10 Go et plus.
Elle ne contient jamais de variable secrète, ni les sauvegardes du projet : seulement le contenu actuel, pris au moment de l’export. Les briques qui ne savent pas restaurer une sauvegarde (Redis, MySQL, MinIO…) et les volumes de moins de 10 Go n’y figurent pas : la fenêtre d’export les liste. La préparation se fait en arrière-plan ; l’archive est ensuite téléchargeable 24 heures, puis détruite.
⚠ Des données réelles, parfois personnelles, quittent la plateforme : conservez l’archive avec le même soin que la production.
Importer une archive
Section intitulée « Importer une archive »Sur la page Importer, la seconde carte accepte une archive. La plateforme :
- reçoit le fichier par morceaux (jusqu’à 100 Gio), avec sa progression ;
- le vérifie : l’archive doit avoir été produite par un export Cassiope et ne pas avoir été modifiée depuis (signature, empreinte de chaque donnée). Sinon, elle est refusée et supprimée ;
- montre le plan : ce qui sera créé, votre quota, et ce que deviennent les données.
Un import n’écrase jamais les données de ce qui existe déjà. Une donnée n’est restaurée que dans une base ou un volume que l’import crée ; si la ressource existe déjà dans le projet, la donnée est écartée et le plan le dit.
Appliquer et restaurer crée les ressources, restaure les données, puis déploie ce qui a été créé. Comme pour une duplication, les variables secrètes sont à saisir ensuite : un déploiement qui échoue faute d’une valeur laisse les données en place, il suffit de la saisir et de redéployer. Si une restauration échoue, tout ce que l’import a créé est supprimé — rien de ce qui existait avant.
Une archive vérifiée mais non appliquée sous 24 heures est supprimée. Abandonner la supprime aussitôt.