EC2 beim Start automatisch konfigurieren: User Data Scripts richtig einsetzen
Du startest eine neue EC2-Instanz, willst Nginx installiert und konfiguriert haben — ohne danach manuell per SSH draufzugehen. Genau dafür existiert der EC2 User Data-Mechanismus, und wer ihn einmal sauber verstanden hat, baut keine manuell gepflegten AMIs mehr für einfache Installationsaufgaben.
TL;DR: EC2 User Data auf einen Blick
| Aspekt | Detail |
|---|---|
| Ausführungszeitpunkt | Einmalig beim ersten Start der Instanz (per Default) |
| Ausführungskontext | root-Benutzer, kein interaktives Terminal |
| Skriptformat | Shell-Skript (beginnt mit #!/bin/bash) oder cloud-init YAML |
| Wo einfügen (Console) | EC2-Startassistent → 'Advanced details' → Feld 'User data' |
| Wo einfügen (CLI) | Parameter --user-data bei aws ec2 run-instances |
| Logs prüfen | /var/log/cloud-init-output.log auf der Instanz |
| Größenlimit | 16 KB (Base64-kodiert) — bei größeren Skripten S3 verwenden |
Wie EC2 User Data funktioniert
Hinter User Data steckt cloud-init — ein auf fast allen Linux-AMIs vorinstalliertes Initialisierungswerkzeug. Beim ersten Boot fragt cloud-init den Instance Metadata Service (IMDS) unter http://169.254.169.254/latest/user-data ab, liest das Skript aus und führt es als root aus. Das passiert sehr früh im Bootprozess, bevor der Instanz-Status in der Console auf 'running' wechselt.
Wichtig: 'einmalig beim ersten Start' ist das Default-Verhalten. cloud-init markiert den Lauf in /var/lib/cloud/instances/<instance-id>/ als abgeschlossen. Startest du die Instanz später neu (Stop/Start), läuft das Skript nicht erneut — außer du konfigurierst cloud-init explizit anders oder nutzt den Mechanismus 'always' in einer cloud-config.
- EC2-Start: AWS provisioniert die Instanz und hängt das User-Data-Skript an den Metadaten-Endpunkt.
- cloud-init bootstrap: cloud-init läuft in der frühen Bootphase und fragt IMDS ab.
- Skriptausführung: Das Shell-Skript wird als root ausgeführt — hier passiert die Nginx-Installation.
- Statusmarkierung: cloud-init schreibt einen Semaphore-Eintrag, damit das Skript beim nächsten Neustart nicht erneut läuft.
- Instanz bereit: Status-Checks werden grün, die Instanz ist erreichbar.
Nginx automatisch installieren: Das User-Data-Skript
Das folgende Skript installiert Nginx auf einer Amazon Linux 2- oder Amazon Linux 2023-Instanz, aktiviert den Dienst und sorgt dafür, dass er nach jedem Neustart automatisch startet. Jede Zeile hat einen konkreten Grund: set -e bricht das Skript bei Fehlern sofort ab, anstatt still weiterzumachen und eine halb-konfigurierte Instanz zu hinterlassen.
🔽 User-Data-Skript für Nginx (Amazon Linux 2 / AL2023) — zum Aufklappen
#!/bin/bash
set -e
# Paketliste aktualisieren und Nginx installieren
yum update -y
yum install -y nginx
# Nginx aktivieren und sofort starten
systemctl enable nginx
systemctl start nginx
# Optionale Prüfung: Status in Log schreiben
systemctl status nginx >> /var/log/nginx-userdata-install.log 2>&1
Für Ubuntu-basierte AMIs ersetzt du yum durch apt-get:
🔽 User-Data-Skript für Nginx (Ubuntu) — zum Aufklappen
#!/bin/bash
set -e
apt-get update -y
apt-get install -y nginx
systemctl enable nginx
systemctl start nginx
Wo du das Skript in der AWS Console einfügst
Der Einfügepunkt ist nicht sofort offensichtlich — er steckt am Ende des Startassistenten hinter einem aufklappbaren Bereich.
- Öffne die EC2-Console und klicke auf 'Instanz starten'.
- Wähle dein AMI und den Instanztyp wie gewohnt.
- Scrolle im Abschnitt 'Erweiterte Details' (ganz unten auf der Konfigurationsseite) nach unten.
- Suche das Textfeld 'Benutzerdaten' (englisch: 'User data').
- Stelle sicher, dass die Option 'Als Text' ausgewählt ist.
- Füge dein Skript inklusive der Shebang-Zeile (
#!/bin/bash) direkt in das Textfeld ein. - Starte die Instanz — das war's.
Stell dir User Data wie einen Zettel vor, den du dem Techniker mitgibst, bevor er den Server in den Schrank stellt. Er liest ihn einmal beim Einrichten — danach ist der Zettel weg, der Server läuft.
EC2 User Data per AWS CLI starten
In automatisierten Pipelines oder Terraform-losen Deployments ist die CLI der direktere Weg. Das Skript wird als Datei übergeben — das vermeidet Encoding-Probleme beim direkten Einfügen als String.
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name mein-schluessel \
--security-group-ids sg-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 \
--user-data file://nginx-install.sh \
--region us-east-1
Ersetze ami-0abcdef1234567890, mein-schluessel, sg-0123456789abcdef0 und subnet-0123456789abcdef0 mit deinen tatsächlichen Ressourcen-IDs. Die Datei nginx-install.sh enthält das Skript aus dem Abschnitt oben. AWS kodiert den Dateiinhalt automatisch in Base64 — du musst das nicht manuell tun.
Fehlerdiagnose: Wenn Nginx nach dem Start nicht läuft
Hier liegt der häufigste Frustrationspunkt: Die Instanz ist 'running', aber Nginx antwortet nicht. Der erste Reflex ist, die Security Group zu prüfen — Port 80 offen? Meistens ja. Das eigentliche Problem sitzt eine Ebene tiefer.
Das Skript ist fehlgeschlagen, und niemand hat es dir gesagt. cloud-init schreibt die komplette Ausgabe des User-Data-Skripts in eine Logdatei. Das ist dein erster Anlaufpunkt:
# Per SSH auf die Instanz verbinden, dann:
cat /var/log/cloud-init-output.log
Typische Fehlerbilder dort:
- Kein Internetzugang:
yum updateschlägt fehl, weil die Instanz in einem privaten Subnetz ohne NAT Gateway sitzt. Das Skript bricht beiset -esofort ab. - Falsches AMI / falscher Paketmanager:
yumauf Ubuntu oderapt-getauf Amazon Linux — der Befehl existiert nicht, Fehler. - Shebang fehlt: Ohne
#!/bin/bashinterpretiert cloud-init das Skript unter Umständen als cloud-config YAML — und scheitert still.
Den aktuellen User-Data-Inhalt einer laufenden Instanz kannst du so prüfen:
aws ec2 describe-instance-attribute \
--instance-id i-0123456789abcdef0 \
--attribute userData \
--region us-east-1 \
--query 'UserData.Value' \
--output text | base64 --decode
Das dekodiert den Base64-Inhalt direkt im Terminal — nützlich, um zu bestätigen, dass das richtige Skript tatsächlich angekommen ist.
Port 80/443 offen?"]; B -- Nein --> C["Inbound-Regel hinzufügen"]; B -- Ja --> D["cloud-init-Log lesen
/var/log/cloud-init-output.log"]; D --> E{"Fehler im Log?"}; E -- Netzwerkfehler --> F["NAT Gateway / Internet Gateway prüfen"]; E -- Paketmanager-Fehler --> G["Skript an AMI-Typ anpassen"]; E -- Shebang fehlt --> H["#!/bin/bash hinzufügen"]; E -- Kein Fehler --> I["systemctl status nginx prüfen"]; F --> J["Neue Instanz mit korrigiertem Skript starten"]; G --> J; H --> J;
- Nginx antwortet nicht: Ausgangspunkt der Diagnose.
- Security Group prüfen: Port 80/443 in den Inbound-Regeln freigegeben?
- cloud-init-Log lesen:
/var/log/cloud-init-output.logzeigt, ob das Skript erfolgreich war. - Skript-Fehler identifizieren: Netzwerkfehler, falscher Paketmanager, fehlende Shebang.
- Neue Instanz starten: User Data kann an einer laufenden Instanz geändert werden (nur im gestoppten Zustand), aber das Skript läuft erst beim nächsten Start erneut, wenn cloud-init entsprechend konfiguriert ist.
User Data an einer bestehenden Instanz ändern
Das geht — aber nur, wenn die Instanz gestoppt ist. An einer laufenden Instanz lässt sich User Data nicht ändern.
# Instanz stoppen
aws ec2 stop-instances \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
# Warten bis gestoppt
aws ec2 wait instance-stopped \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
# User Data aktualisieren
aws ec2 modify-instance-attribute \
--instance-id i-0123456789abcdef0 \
--user-data file://nginx-install-v2.sh \
--region us-east-1
# Instanz wieder starten
aws ec2 start-instances \
--instance-ids i-0123456789abcdef0 \
--region us-east-1
Denk daran: Auch nach dem Ändern läuft das Skript standardmäßig nicht erneut, weil cloud-init den ersten Lauf bereits als abgeschlossen markiert hat. Für Neustarts mit erneuter Skriptausführung müsste der cloud-init-Status manuell zurückgesetzt werden — das ist für Produktionsinstanzen kein empfohlener Ansatz. Für wiederholbare Konfiguration sind Tools wie AWS Systems Manager oder ein frisches AMI die bessere Wahl.
IAM-Berechtigungen: Was du brauchst
Um Instanzen mit User Data zu starten und deren Attribute zu lesen, benötigt dein IAM-Principal mindestens diese Berechtigungen:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:RunInstances",
"ec2:DescribeInstanceAttribute",
"ec2:ModifyInstanceAttribute",
"ec2:StopInstances",
"ec2:StartInstances"
],
"Resource": "*"
}
]
}
In Produktionsumgebungen solltest du ec2:RunInstances mit Bedingungen auf bestimmte AMIs, Instanztypen oder Tags einschränken. Die vollständige Liste der unterstützten Bedingungsschlüssel findest du in der AWS Service Authorization Reference für EC2.
Weiterführende Schritte und Ressourcen
User Data ist ein solider Einstieg für einfache Bootstrapping-Aufgaben. Sobald die Konfigurationslogik komplexer wird — mehrere Pakete, Konfigurationsdateien, Abhängigkeiten zwischen Diensten — lohnt sich der Blick auf folgende Alternativen:
- AWS Systems Manager Run Command: Skripte auf laufenden Instanzen ausführen, ohne SSH.
- EC2 Image Builder: Reproduzierbare AMIs mit vorinstallierter Software erstellen.
- AWS CloudFormation cfn-init: Deklarative Konfiguration als Teil von CloudFormation-Stacks.
Die offizielle AWS-Dokumentation zu User Data findest du unter: Running commands on your Linux instance at launch.
Glossar: Schlüsselbegriffe
| Begriff | Bedeutung |
|---|---|
| User Data | Metadaten-Feld einer EC2-Instanz, das ein Shell-Skript oder cloud-config YAML beim ersten Start ausführt. |
| cloud-init | Open-Source-Initialisierungswerkzeug, das auf den meisten Linux-AMIs vorinstalliert ist und User Data verarbeitet. |
| IMDS (Instance Metadata Service) | Interner HTTP-Endpunkt (169.254.169.254), über den eine Instanz ihre eigenen Metadaten — einschließlich User Data — abruft. |
| Shebang | Erste Zeile eines Skripts (#!/bin/bash), die dem Betriebssystem mitteilt, welcher Interpreter verwendet werden soll. |
| cloud-init-output.log | Logdatei unter /var/log/, in der cloud-init die gesamte Ausgabe des User-Data-Skripts protokolliert. |
Kommentare
Kommentar veröffentlichen