Une machine qu'on configure à la main après son démarrage est une machine qu'on ne saura pas recréer. Cette leçon montre comment préparer une instance au moment où elle démarre, avec une image système et un fichier de configuration lu par cloud-init, puis comment elle obtient des identifiants temporaires auprès du service de métadonnées. Elle montre aussi, mesures à l'appui, ce que cette configuration de démarrage laisse derrière elle sur le disque, parce que c'est le point où l'on se croit à tort protégé.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Situer cloud-init dans la préparation d'une machine au démarrage, sans y toucher ensuite (l'écriture pas à pas d'un fichier est l'objet de la leçon suivante).
- Distinguer ce qui appartient à l'image de ce qui appartient au démarrage.
- Créer une machine sans adresse publique, et dire par où elle sort pour installer ses paquets.
- Vérifier ce que cloud-init conserve sur le disque, et qui peut le lire.
- Protéger le service de métadonnées, cible d'une classe d'attaques connue.
Prérequis
Section intitulée « Prérequis »Aucune connaissance préalable du réseau n'est nécessaire : les deux notions utiles sont définies ici. Un réseau privé est un réseau interne au cloud, sans accès direct depuis Internet : les machines qu'on y rattache s'y parlent par des adresses privées. Une passerelle (gateway) est l'équipement qui relie ce réseau privé à Internet pour que ses machines puissent sortir. Le module Réseau approfondit les deux, dans les leçons sur le réseau privé et ses sous-réseaux et sur les tables de routage et les passerelles.
Pour rejouer la commande de création sans compte cloud, il faut le client
scw (version 2.65.1) et l'émulateur Feint
0.13.0 lancé (feint serve dans un terminal, ou le conteneur présenté dans
l'installation de Feint), avec scw
pointé sur lui par eval "$(feint env scaleway)". Le réseau privé se crée sur
place, dans la leçon.
L'image, et la préparation au démarrage
Section intitulée « L'image, et la préparation au démarrage »Une image est le disque de départ de votre machine. Trois façons de faire cohabitent, et le choix a des conséquences sur la sécurité comme sur le temps de démarrage.
| Approche | Comment | Ce qu'elle coûte |
|---|---|---|
| Image officielle plus configuration au démarrage | cloud-init installe et configure | démarrage plus long, dépendances externes |
| Image préparée par vous | construite en amont, prête à l'emploi | un travail de fabrication, et un cycle de mise à jour |
| Image officielle plus configuration manuelle | quelqu'un se connecte et installe | à éviter : rien n'est reproductible |
La troisième ligne mérite son avertissement. Une machine configurée à la main est une machine que personne ne saura recréer à l'identique, y compris celui qui l'a faite. Le jour où elle tombe, l'incident dure le temps de retrouver ce qui avait été installé, et cette durée ne se budgète pas.
cloud-init est le mécanisme standard, présent sur pratiquement toutes les images Linux officielles, quel que soit le fournisseur. Il lit une configuration que vous fournissez à la création et l'applique au premier démarrage.
#cloud-configpackage_update: truepackages: - nginxusers: - name: appli groups: [sudo] shell: /bin/bash ssh_authorized_keys: - ssh-ed25519 AAAA... votre-clewrite_files: - path: /etc/nginx/conf.d/app.conf content: | server { listen 8080; root /var/www/app; }runcmd: - systemctl enable --now nginxCe fichier YAML, qui commence obligatoirement par #cloud-config, s'appelle le
user-data : il crée un utilisateur, installe un paquet, dépose un
fichier et lance une commande, le tout sans que personne se connecte à
la machine.
Comment créer une machine sans adresse publique ?
Section intitulée « Comment créer une machine sans adresse publique ? »Une machine qui n'a pas besoin d'être jointe depuis Internet ne doit pas recevoir d'adresse publique. Une adresse publique est la première des trois conditions pour qu'une machine soit exposée (une adresse joignable, un chemin depuis Internet, une règle qui autorise le trafic), comme l'approfondit la leçon sur le réseau privé et ses sous-réseaux : ne pas la donner supprime d'emblée la surface la plus attaquée. Ce que la machine perd en échange, c'est sa sortie : sans adresse publique, elle ne peut plus télécharger ses paquets au démarrage, sauf si le réseau lui offre un chemin.
Chez Scaleway, on demande explicitement l'absence d'adresse avec ip=none.
L'argument vaut « aucune adresse publique » dans l'aide de la commande ; dans la
console, il s'agit de décocher les cases IPv4 et IPv6 publiques.
SRV=$(scw instance server create name=app-privee type=DEV1-S image=ubuntu_jammy \ ip=none zone=fr-par-1 -o json | jq -r .id)Cette commande ne suffit pas : une machine créée avec ip=none n'a aucune
interface réseau privée, donc aucune sortie, même vers un réseau interne. Il
faut lui en ajouter une, qui la rattache à un réseau privé. Ce réseau
n'existe pas encore : créez-le (le nom lab-amorcage est libre) et gardez son
identifiant dans PN.
PN=$(scw vpc private-network create name=lab-amorcage -o json | jq -r .id)La sortie JSON de la commande est l'objet du réseau lui-même, sans
enveloppe : le champ id s'y lit directement. L'aide de la version 2.65.1 déclare vpc-id
facultatif, et Feint 0.13.0 rattache alors le réseau à un VPC (le réseau virtuel
qui contient les réseaux privés) qu'il crée de lui-même. Sur un vrai compte, ce
rattachement par défaut n'a pas été rejoué ici : passez vpc-id=<ID_VPC> si la
commande le réclame. Rattachez ensuite la machine à ce réseau :
scw instance private-nic create server-id="$SRV" private-network-id="$PN" zone=fr-par-1Avec la version 2.65.1 du client, l'aide de scw instance server create ne
propose toujours pas d'argument de réseau privé : la création de l'interface
reste donc un second geste. Ces trois commandes se rejouent telles quelles sur
Feint 0.13.0, en pointant scw sur l'émulateur. La création du réseau renvoie un identifiant (UUID) de la
forme 7337612c-7b4f-4de8-8448-1b4f41d3261e, chaque exécution en donne un
autre.
Pour vérifier, relisez la machine avec scw instance server get "$SRV" zone=fr-par-1 :
la section Public IPs: ne contient que sa ligne d'en-tête, sans aucune
adresse, et la section Private NICs: liste maintenant l'interface
rattachée (avec -o json, public_ips vaut [] et public_ip vaut null).
Sur un vrai compte, cette machine est facturée tant qu'elle existe. Le
nettoyage se fait dans l'ordre inverse de la création : l'interface, la
machine, puis le réseau. Un réseau qui porte encore une interface refuse sa
suppression (sur Feint : private network still has 1 attached NIC(s)).
NIC=$(scw instance private-nic list server-id="$SRV" zone=fr-par-1 -o json | jq -r '.[0].id')scw instance private-nic delete server-id="$SRV" private-nic-id="$NIC" zone=fr-par-1scw instance server terminate "$SRV" zone=fr-par-1 with-ip=true with-block=truescw vpc private-network delete "$PN"La première commande n'affiche rien : elle range l'identifiant de l'interface
dans NIC. La suppression de l'interface répond Private-nic has been successfully deleted., celle de la machine Success., et celle du réseau n'affiche qu'un tiret.
L'option with-block=true de terminate retire aussi le disque de la machine. Pour
contrôler que rien ne reste, scw instance server list zone=fr-par-1 -o json | jq length et scw vpc private-network list -o json | jq length doivent
afficher 0 sur un Feint neuf.
Une Public Gateway est un équipement managé qui relie un réseau privé à Internet : elle traduit les adresses privées des machines vers une adresse publique, et c'est par elle qu'une machine sans adresse publique sort. Pour que la vôtre atteigne Internet, par exemple pour que cloud-init installe des paquets, la passerelle doit être rattachée à ce réseau privé. La leçon sur les tables de routage et les passerelles approfondit ce rattachement, que cette leçon ne réalise pas.
Chez OUTSCALE, la réponse dépend de l'endroit où la machine est créée. Dans
un Net, une machine ne reçoit aucune adresse publique par défaut : la
propriété MapPublicIpOnLaunch du sous-réseau vaut false par défaut, et ce
n'est que si vous la passez à true que les cartes réseau créées dans ce
sous-réseau reçoivent une adresse publique. Sinon, on en ajoute une
explicitement, avec les actions CreatePublicIp puis LinkPublicIp. Hors
Net, dans ce qu'OUTSCALE appelle le Cloud public, la machine reçoit au
contraire une adresse publique, sauf si le tag private_only est présent dans
son user-data. Vérifiez dans votre compte que ce Cloud public existe encore
pour vous : la documentation consultée ne le précise pas pour un compte récent.
Avec Incus, la question ne se pose pas dans ces termes, parce qu'il n'y a
pas de notion d'adresse publique. L'instance reçoit une adresse privée du pont
géré par Incus, et sa sortie passe par la traduction d'adresses (NAT) de ce pont,
l'option ipv4.nat. Cette option vaut false par défaut, mais elle est à true
sur un pont créé avec ipv4.address=auto, ce qui est le cas du pont incusbr0
des installations courantes. C'est ce qui permet à la leçon suivante, sur
l'écriture d'un user-data, d'installer des paquets
depuis une machine qui n'a aucune adresse publique.
Les cinq natures de données qu'une instance reçoit au démarrage
Section intitulée « Les cinq natures de données qu'une instance reçoit au démarrage »Parler de « métadonnées » au singulier fait perdre la distinction qui compte pour la sécurité. Une instance reçoit cinq choses différentes, qui n'ont ni la même origine, ni la même durée de vie, ni les mêmes droits de lecture.
| Nature | Qui l'écrit | Ce que c'est | Durée de vie |
|---|---|---|---|
| metadata | le fournisseur | identifiant, zone, type, nom d'hôte | tant que l'instance existe |
| user-data | vous | la configuration cloud-init que vous fournissez | conservée sur le disque après le boot |
| vendor-data | le fournisseur | réglages qu'il impose ou propose par défaut | idem user-data |
| identifiants temporaires | le fournisseur | jeton d'accès lié au rôle de l'instance | quelques heures, renouvelé |
| identité d'instance | le fournisseur | document signé prouvant « je suis cette instance » | à la demande |
La ligne à retenir est la deuxième. Les identifiants temporaires expirent, pas votre user-data : il reste lisible sur le disque, dans le même état qu'au moment de la création de la machine. C'est la seule des cinq natures que vous écrivez, et la seule qui ne se révoque pas.
Que garde cloud-init sur le disque après le premier démarrage ?
Section intitulée « Que garde cloud-init sur le disque après le premier démarrage ? »cloud-init conserve votre user-data en clair sur le disque, définitivement, et tout ce qu'il conserve n'est pas protégé de la même façon. Mesuré le 20 septembre 2026 sur deux machines virtuelles fraîchement démarrées, AlmaLinux 10.2 avec cloud-init 24.4 et Debian 13 avec cloud-init 25.1.4, toutes deux sur la source de données NoCloud :
| Fichier | Droits | Lisible sans privilège |
|---|---|---|
/var/lib/cloud/instance/user-data.txt | -rw------- root:root | non |
/run/cloud-init/instance-data-sensitive.json | -rw------- root:root | non |
/run/cloud-init/instance-data.json | -rw-r--r-- root:root | oui |
/var/lib/cloud/seed/nocloud-net/user-data | -rw-r--r-- root:root | oui |
Les deux premières lignes montrent que cloud-init fait son travail : le
user-data recopié dans /var/lib/cloud/instance/ est en 0600, et la
variante sensible de l'inventaire aussi. La commande cloud-init query
applique la même règle et refuse de servir un compte ordinaire :
# Sans privilège, cloud-init caviarde volontairement sa réponsecloud-init query userdataLa quatrième ligne annule cette protection. Avec la source de données
NoCloud, celle que vous obtenez avec libvirt, Incus, Proxmox ou une clé USB,
le fichier d'amorçage reste sur le disque en 0644 : n'importe quel compte
local relit l'intégralité du user-data, y compris ce que cloud-init s'est
donné la peine de protéger deux répertoires plus loin. Sur un cloud public qui
sert ses données par le service de métadonnées, il n'y a pas de seed sur le
disque et cette ligne disparaît, mais les trois autres restent vraies.
Le service de métadonnées : ce que votre machine sait d'elle-même
Section intitulée « Le service de métadonnées : ce que votre machine sait d'elle-même »Chaque machine du cloud peut interroger une adresse locale spéciale qui lui répond sur sa propre configuration, et, surtout, lui remet des identifiants temporaires. C'est le mécanisme qui rend possible l'identité attachée à la ressource, approfondie dans la leçon sur les identifiants courts : l'application n'embarque aucun mot de passe, elle demande un jeton au moment de s'en servir.
Cette adresse est locale au serveur physique : elle n'est pas routée depuis l'extérieur, elle ne répond qu'aux processus de la machine elle-même, et la réponse lui est propre. C'est justement ce qui en fait une cible : tout ce qui parvient à émettre une requête depuis la machine parle au service de métadonnées avec les droits de la machine.
Comment protéger le service de métadonnées d'un détournement SSRF ?
Section intitulée « Comment protéger le service de métadonnées d'un détournement SSRF ? »La menace principale est la falsification de requête côté serveur, ou SSRF. Une application qui accepte une URL fournie par l'utilisateur et va la chercher peut être détournée pour interroger l'adresse de métadonnées et renvoyer le jeton dans sa réponse. Des compromissions majeures ont eu exactement cette cause, et aucune n'a demandé d'accès préalable à la machine.
Quatre protections, à appliquer ensemble plutôt qu'à choisir :
| Protection | Ce qu'elle casse | Où elle se règle |
|---|---|---|
| Version durcie du protocole | la requête simple qui suffisait à lire le jeton : il faut d'abord obtenir un jeton de session par une requête préalable | à la création de l'instance, puis rendue obligatoire par politique |
| Limite de sauts réseau | la réponse qui ressortait du serveur vers un conteneur ou un proxy | même réglage, côté fournisseur |
| Rôle le plus étroit possible | l'ampleur des dégâts : un rôle qui ne lit qu'un seul seau limite la fuite à ce seau | dans la politique d'accès attachée à l'instance |
| Blocage depuis les conteneurs | l'accès des charges non fiables, qui n'ont aucune raison d'interroger l'adresse | dans l'orchestrateur, la plupart offrent le réglage |
Le contrôle est immédiat, et il se fait depuis la machine : une requête vers l'adresse de métadonnées sans jeton de session préalable doit être refusée si la version durcie est bien imposée. Si elle répond, le réglage n'est pas appliqué, quelle que soit la case cochée dans la console.
À retenir
Section intitulée « À retenir »- L'image porte ce qui est stable, le démarrage porte ce qui est propre à la machine. Mélanger les deux produit une image qu'on ne sait plus reconstruire.
- Une machine sans adresse publique se demande explicitement chez Scaleway (
ip=none), est le comportement par défaut dans un Net OUTSCALE (MapPublicIpOnLaunchàfalse), et n'existe pas sous cette forme avec Incus, où la sortie passe par le NAT du pont. Dans les clouds, sa sortie passe par une passerelle. - cloud-init conserve votre user-data en clair sur le disque, dans
/var/lib/cloud/instance/user-data.txt, bien après le premier démarrage. - Les droits sont corrects là où cloud-init les pose,
0600, etcloud-init querycaviarde sa sortie pour un compte ordinaire. - Avec la source NoCloud, le seed reste en
0644et rend le user-data lisible par tout compte local. Vérifiez-le, ne le supposez pas. - Un secret dans user-data est un secret publié : il part dans les sauvegardes et les images dérivées. Utilisez un rôle d'instance et un gestionnaire de secrets.
- Le service de métadonnées se protège par la version durcie du protocole, la limite de sauts réseau, un rôle étroit et le blocage depuis les conteneurs, les quatre ensemble.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : Cloud-init : automatiser la configuration des VMs cloud
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications