Exécuter des scripts au démarrage d'EC2 : Guide complet User Data
Vous venez de lancer une instance EC2 et vous réalisez que vous devez installer Nginx, configurer des variables d'environnement et démarrer un service — à chaque fois, manuellement. L'exécution de scripts au démarrage d'EC2 via User Data est la réponse standard à ce problème, mais les erreurs silencieuses et les malentendus sur le cycle d'exécution font perdre beaucoup de temps en production.
TL;DR : Exécuter des scripts au démarrage d'EC2
| Aspect | Détail |
|---|---|
| Mécanisme | cloud-init lit le champ User Data au premier démarrage |
| Exécution par défaut | Une seule fois, au premier démarrage (first boot) |
| Format requis | Script shell : commence par #!/bin/bash |
| Utilisateur d'exécution | root — pas besoin de sudo |
| Limite de taille | 16 Ko (pour les données brutes avant encodage base64) |
| Logs de débogage | /var/log/cloud-init-output.log |
| Encodage requis | Base64 si passé via AWS CLI (--user-data fileb:// l'encode automatiquement) |
Comment fonctionne User Data sur EC2
Avant de coller votre script quelque part, il faut comprendre ce qui se passe réellement sous le capot. User Data n'est pas un simple hook de démarrage — c'est un mécanisme piloté par cloud-init, un outil open-source préinstallé sur la plupart des AMI Amazon Linux, Ubuntu et RHEL.
Au premier démarrage, l'instance contacte le service de métadonnées EC2 (IMDS) à l'adresse 169.254.169.254 pour récupérer le contenu User Data. cloud-init interprète ensuite ce contenu selon son type : un script shell (shebang #!/bin/bash) est exécuté directement, un cloud-config YAML est traité différemment. Ce guide couvre le cas shell.
(169.254.169.254) participant Script as Script User Data participant Log as /var/log/cloud-init-output.log Kernel->>CloudInit: Démarrage système (systemd) CloudInit->>IMDS: GET /latest/user-data IMDS-->>CloudInit: Contenu du script shell CloudInit->>Script: Exécution en tant que root Script->>Log: stdout + stderr redirigés Script-->>CloudInit: Code de retour CloudInit->>CloudInit: Écriture du marqueur d'exécution
- Instance démarre : le noyau s'initialise, systemd lance les services de base.
- cloud-init s'exécute : il interroge l'IMDS pour récupérer User Data.
- Exécution du script : le script shell est lancé en tant que
root. - Logs capturés : stdout et stderr sont redirigés vers
/var/log/cloud-init-output.log. - Marqueur écrit : cloud-init marque l'exécution comme terminée pour ne pas la rejouer.
Pensez à cloud-init comme à un livreur qui ne sonne qu'une fois. Si vous n'étiez pas là (script en erreur, mauvaise configuration), il ne reviendra pas — sauf si vous lui demandez explicitement.
Étape 1 : Écrire le script User Data pour installer Nginx
Le script doit commencer par un shebang valide. Sans lui, cloud-init traite le contenu comme du cloud-config YAML et votre script ne s'exécute pas — erreur silencieuse garantie.
#!/bin/bash
yum update -y
yum install -y nginx
systemctl enable nginx
systemctl start nginx
Quelques points non négociables :
- Utilisez
yumpour Amazon Linux 2 / AL2023 (avecdnfsur AL2023),apt-getpour Ubuntu. - Le flag
-yest obligatoire — le script s'exécute sans terminal interactif, toute invite bloque indéfiniment. systemctl enablegarantit que Nginx redémarre après un reboot ultérieur.
Étape 2 : Où coller le script User Data dans la console AWS
C'est la question la plus fréquente. La réponse dépend du moment : au lancement initial ou sur une instance existante arrêtée.
Lors du lancement d'une nouvelle instance
- Dans la console EC2, cliquez sur Launch Instance.
- Descendez jusqu'à la section Advanced details (tout en bas du formulaire).
- Localisez le champ User data.
- Sélectionnez As text et collez votre script directement.
- Finalisez le lancement — le script s'exécutera au premier démarrage.
Sur une instance existante (arrêtée)
Vous ne pouvez modifier User Data que sur une instance à l'état stopped. Une instance en cours d'exécution ne permet pas cette modification.
- Arrêtez l'instance (Instance State → Stop).
- Sélectionnez l'instance → Actions → Instance Settings → Edit User Data.
- Collez ou modifiez le script.
- Sauvegardez, puis redémarrez l'instance.
Attention : modifier User Data sur une instance existante ne relance pas automatiquement cloud-init. Par défaut, cloud-init ne s'exécute qu'une fois. Voir l'étape 5 pour forcer une ré-exécution.
Étape 3 : Passer User Data via AWS CLI
En production, vous ne passez pas par la console. Voici la commande complète pour lancer une instance avec User Data depuis le CLI — c'est aussi ce que font CloudFormation et Terraform sous le capot.
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-key-pair \
--security-group-ids sg-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 \
--user-data file://userdata.sh \
--region us-east-1
Le préfixe file:// indique au CLI de lire le fichier local et de l'encoder automatiquement en base64 avant envoi. N'encodez pas manuellement votre script si vous utilisez cette syntaxe — vous double-encoderiez.
Pour vérifier le User Data actuellement associé à une instance :
aws ec2 describe-instance-attribute \
--instance-id i-0123456789abcdef0 \
--attribute userData \
--region us-east-1 \
--query 'UserData.Value' \
--output text | base64 --decode
Étape 4 : Vérifier que le script s'est exécuté correctement
Le script a tourné, mais Nginx ne répond pas. Avant de réécrire quoi que ce soit, consultez les logs — c'est là que tout se passe.
Connectez-vous en SSH à l'instance et exécutez :
sudo cat /var/log/cloud-init-output.log
Ce fichier capture la sortie complète du script (stdout + stderr). Une erreur de package manquant, un timeout réseau ou un nom de service incorrect apparaîtra ici clairement.
Pour vérifier l'état global de cloud-init :
sudo cloud-init status --long
Pour confirmer que Nginx tourne effectivement :
systemctl status nginx
Étape 5 : Forcer la ré-exécution de User Data (cas avancé)
Situation classique : vous avez modifié le script User Data sur une instance existante et redémarré — mais rien ne se passe. cloud-init a déjà marqué ce boot comme traité.
Pour forcer cloud-init à ré-exécuter User Data au prochain démarrage, supprimez les marqueurs d'état :
sudo rm -rf /var/lib/cloud/instances/
sudo rm -rf /var/lib/cloud/instance
Puis redémarrez l'instance. cloud-init considérera ce démarrage comme un 'first boot' et exécutera à nouveau User Data.
Cette approche est utile pour tester des scripts ou préparer une AMI de base. En production, préférez un outil de gestion de configuration (Ansible, SSM Run Command) pour les modifications post-lancement.
Erreur fréquente : le script silencieux qui ne fait rien
Voici un pattern d'échec réel. Vous collez ce script dans User Data :
yum install -y nginx
systemctl start nginx
L'instance démarre. Nginx n'est pas installé. Vous vérifiez /var/log/cloud-init-output.log — vide ou quasi-vide.
Diagnostic erroné : problème réseau, l'instance ne peut pas atteindre les dépôts yum.
Cause réelle : le script ne commence pas par #!/bin/bash. Sans shebang, cloud-init ne reconnaît pas le contenu comme un script shell exécutable — il l'ignore silencieusement ou tente de l'interpréter comme du cloud-config YAML, ce qui échoue sans message d'erreur visible dans les logs applicatifs.
Correction : toujours commencer par #!/bin/bash sur la première ligne, sans espace ni ligne vide avant.
Le shebang n'est pas une convention de style — c'est le signal que cloud-init utilise pour décider comment traiter votre User Data.
IAM et accès aux ressources depuis User Data
Si votre script doit interagir avec d'autres services AWS (télécharger depuis S3, récupérer un secret depuis Secrets Manager, écrire dans CloudWatch Logs), l'instance doit disposer d'un Instance Profile avec les permissions appropriées.
Exemple de politique IAM minimale pour télécharger un fichier de configuration depuis S3 :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mon-bucket-config/nginx.conf"
}
]
}
Attachez cette politique à un rôle IAM, puis associez ce rôle comme Instance Profile lors du lancement. Le script User Data peut alors appeler aws s3 cp sans credentials explicites — le SDK AWS utilise automatiquement les credentials de l'Instance Metadata Service.
Wrap-up et prochaines étapes pour l'automatisation EC2
L'exécution de scripts au démarrage d'EC2 via User Data couvre la majorité des besoins de bootstrapping : installation de packages, configuration de services, récupération de secrets. Pour aller plus loin :
- AWS Systems Manager Run Command : exécutez des scripts sur des instances déjà en cours d'exécution, sans SSH.
- AWS Systems Manager State Manager : maintenez un état de configuration dans le temps, pas seulement au démarrage.
- Launch Templates : stockez User Data dans un template réutilisable pour Auto Scaling Groups.
- EC2 Image Builder : intégrez l'installation de Nginx directement dans une AMI personnalisée pour des démarrages plus rapides.
Documentation officielle de référence : AWS EC2 User Data — Guide utilisateur.
Glossaire
| Terme | Définition |
|---|---|
| User Data | Champ de configuration EC2 permettant de passer un script ou des directives cloud-config exécutés au démarrage de l'instance. |
| cloud-init | Outil open-source préinstallé sur la plupart des AMI Linux, responsable de l'initialisation de l'instance et de l'exécution de User Data. |
| IMDS (Instance Metadata Service) | Service accessible à 169.254.169.254 depuis l'instance, fournissant les métadonnées et User Data à cloud-init. |
| Instance Profile | Conteneur IAM qui attache un rôle IAM à une instance EC2, permettant au code s'exécutant sur l'instance d'appeler des API AWS. |
| Shebang | Première ligne d'un script (#!/bin/bash) indiquant à l'interpréteur quel programme utiliser pour exécuter le fichier. |
Commentaires
Enregistrer un commentaire