AWS EC2-Bereitstellungshandbuch für Webanwendungen
EC2 bleibt die flexibelste Rechenoption in AWS für Webanwendungen, die konsistente Leistung, benutzerdefinierte Software-Stacks und vorhersehbare Preise erfordern. Während ECS, EKS und Lambda in der Cloud-nativen Welt mehr Aufmerksamkeit erhalten, erhalten Sie mit EC2 einen Server, den Sie vollständig kontrollieren – keine Komplexität der Container-Orchestrierung, keine Kaltstartlatenz, keine überraschenden Aufrufkosten.
Dieser Leitfaden behandelt die Bereitstellung einer Produktions-Node.js-Webanwendung auf EC2: Instanzauswahl, Sicherheitsgruppenkonfiguration, Anwendungsbereitstellung, Nginx-Reverse-Proxy, SSL mit Cloudflare, Überwachung mit CloudWatch und die laufenden Wartungsmuster, die eine EC2-Bereitstellung fehlerfrei halten.
Wichtige Erkenntnisse
- t3.large ist der richtige Ausgangspunkt für eine Full-Stack-Node.js + PostgreSQL-Bereitstellung
- Verwenden Sie Ubuntu 24.04 LTS – unterstützt bis 2029, umfassend dokumentiert, ausgezeichnete Paketverfügbarkeit
- Elastic IP ist obligatorisch – Ihre EC2-IP ändert sich bei jedem Stopp/Start ohne sie – Sicherheitsgruppen sind zustandsbehaftet – Sie benötigen nur eingehende Regeln; Ausgehend ist normalerweise „Alles zulassen“. – Speichern Sie Ihren Bereitstellungs-SSH-Schlüssel in einer separaten
.pem-Datei; Begebe es niemals Git – Verwenden Sie nach Möglichkeit EC2-Instanzverbindung oder Session Manager anstelle von direktem SSH (keine Schlüsselverwaltung). – Der CloudWatch-Agent liefert Ihnen Speicher- und Festplattenmetriken (standardmäßig nicht verfügbar). – Reserved Instances oder Savings Plans reduzieren die EC2-Kosten um 40–60 % im Vergleich zu On-Demand
Instanzauswahl
Der richtige Instanztyp hängt von Ihrer Arbeitslast ab:
| Arbeitsbelastung | Empfohlene Instanz | vCPU | RAM | Kosten/Monat |
|---|---|---|---|---|
| Light (Blog, kleine App) | t3.small | 2 | 2GB | ~18 $ |
| Mittel (Full-Stack-App) | t3.medium | 2 | 4GB | ~35 $ |
| Produktion (Multiservice) | t3.large | 2 | 8GB | ~70 $ |
| Schwer (API mit hohem Datenverkehr) | c6i.xlarge | 4 | 8GB | ~140 $ |
| Speicherintensiv (ML/Cache) | r6i.large | 2 | 16 GB | ~120 $ |
Für ein Monorepo mit 5 Node.js-Anwendungen (Next.js, NestJS, Docusaurus, 2 Markenseiten) plus Docker-Infrastruktur (PostgreSQL, Redis, Authentik) ist ein t3.large die minimal praktikable Konfiguration. Die t3-Familie nutzt „Burst“-Leistung – die Leistung ist im Normalbetrieb ausgezeichnet, eine anhaltend hohe CPU-Leistung führt jedoch zu einer Drosselung.
Verwenden Sie für konstant hohe CPU-Auslastungen (Videoverarbeitung, ML-Inferenz, starke Kryptografie) stattdessen c6i-Instanzen (rechenoptimiert).
Ersteinrichtung des Servers
Nach dem Start Ihrer EC2-Instanz mit Ubuntu 24.04:
# Connect via SSH
ssh -i your-key.pem [email protected]
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install essential tools
sudo apt install -y \
git curl wget unzip \
build-essential \
nginx \
certbot python3-certbot-nginx \
docker.io docker-compose-plugin \
htop ncdu iotop
# Install Node.js via NVM (allows easy version management)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 22
nvm use 22
nvm alias default 22
# Install pnpm
curl -fsSL https://get.pnpm.io/install.sh | sh -
source ~/.bashrc
# Install PM2 globally
npm install -g pm2
# Install PM2 log rotation immediately
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7
pm2 set pm2-logrotate:compress true
Sicherheitsgruppenkonfiguration
Die Sicherheitsgruppe ist die Firewall Ihrer EC2-Instanz. Konfigurieren Sie es sorgfältig:
Inbound Rules:
┌─────────┬──────────┬─────────────┬──────────────────────────────────┐
│ Type │ Protocol │ Port Range │ Source │
├─────────┼──────────┼─────────────┼──────────────────────────────────┤
│ SSH │ TCP │ 22 │ Your IP only (not 0.0.0.0/0!) │
│ HTTP │ TCP │ 80 │ 0.0.0.0/0 (Cloudflare IPs only) │
│ HTTPS │ TCP │ 443 │ 0.0.0.0/0 (Cloudflare IPs only) │
└─────────┴──────────┴─────────────┴──────────────────────────────────┘
Note: Internal app ports (3000, 3001, 3002, etc.) should NOT be
in the security group — traffic goes through Nginx only
Beschränken Sie für Cloudflare-Proxy-Domänen HTTP/HTTPS auf Cloudflare-IP-Bereiche:
# Cloudflare IPv4 ranges — restrict port 80/443 source to these
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
104.16.0.0/13
104.24.0.0/14
108.162.192.0/18
131.0.72.0/22
141.101.64.0/18
162.158.0.0/15
172.64.0.0/13
173.245.48.0/20
188.114.96.0/20
190.93.240.0/20
197.234.240.0/22
198.41.128.0/17
Dies verhindert den direkten Zugriff auf Ihren Server und umgeht den WAF- und DDoS-Schutz von Cloudflare.
Anwendungsbereitstellung
# Create application directory
sudo mkdir -p /opt/ecosire/app
sudo chown ubuntu:ubuntu /opt/ecosire/app
# Clone the repository
git clone https://github.com/your-org/your-repo.git /opt/ecosire/app
cd /opt/ecosire/app
# Create .env.local from template
cp .env.example .env.local
# Edit with production values
nano .env.local
# Install dependencies
pnpm install --frozen-lockfile
# Build everything
npx turbo run build
# Run database migrations
pnpm --filter @ecosire/db db:migrate
# Start infrastructure (PostgreSQL, Redis, Authentik)
docker compose -f infrastructure/docker-compose.dev.yml up -d
# Wait for services to be healthy
sleep 30
# Start Node.js applications
pm2 start ecosystem.config.cjs
# Save process list for reboot persistence
pm2 save
# Configure PM2 to start on system boot
pm2 startup
# Run the command it outputs
Elastic IP und DNS
Die öffentliche IP einer EC2-Instanz ändert sich jedes Mal, wenn Sie sie stoppen und starten. Elastic IP stellt eine permanente IP bereit:
# In AWS Console:
# 1. EC2 > Network & Security > Elastic IPs
# 2. Allocate Elastic IP address
# 3. Associate it with your instance
# Your IP is now permanent — update Cloudflare DNS to point to it
# A record: ecosire.com → 13.223.116.181 (your Elastic IP)
# A record: api.ecosire.com → 13.223.116.181
# A record: auth.ecosire.com → 13.223.116.181
Stellen Sie diese Datensätze in Cloudflare für den Webverkehr auf „Proxied“ (orangefarbene Wolke) ein. Der Cloudflare-Proxy verbirgt Ihre tatsächliche EC2-IP und bietet so DDoS-Schutz.
Speicher: EBS-Volume-Management
EC2-Instanzen umfassen ein Root-EBS-Volume. Für die Produktion benötigen Sie ausreichend Platz für Build-Artefakte, Protokolle und Docker-Daten:
# Check current disk usage
df -h
# Check which directories are consuming space
ncdu /
# Typical space requirements for a 5-app monorepo:
# - /opt/ecosire/app: ~2GB (code + node_modules + .next builds)
# - Docker data (/var/lib/docker): ~5GB
# - PM2 logs (/var/log/pm2): ~1GB (with rotation)
# - System: ~5GB
# Total: ~13GB minimum, recommend 30GB+ root volume
# If you need to resize an EBS volume (no downtime needed):
# 1. In AWS Console: EC2 > Volumes > Modify Volume
# 2. After resize completes, grow the filesystem:
sudo growpart /dev/xvda 1
sudo resize2fs /dev/xvda1
CloudWatch-Überwachung
EC2 stellt standardmäßig grundlegende CPU- und Netzwerkmetriken bereit. Installieren Sie für Speicher- und Festplattenmetriken den CloudWatch-Agenten:
# Download and install CloudWatch agent
wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
sudo dpkg -i amazon-cloudwatch-agent.deb
# Create configuration
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
// /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
{
"agent": {
"metrics_collection_interval": 60,
"run_as_user": "cwagent"
},
"metrics": {
"append_dimensions": {
"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
"ImageId": "${aws:ImageId}",
"InstanceId": "${aws:InstanceId}",
"InstanceType": "${aws:InstanceType}"
},
"metrics_collected": {
"mem": {
"measurement": ["mem_used_percent"],
"metrics_collection_interval": 60
},
"disk": {
"measurement": ["used_percent"],
"metrics_collection_interval": 60,
"resources": ["/", "/opt/ecosire"]
}
}
},
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/pm2/ecosire-api.err.log",
"log_group_name": "/ec2/ecosire/api-errors",
"log_stream_name": "{instance_id}"
},
{
"file_path": "/var/log/nginx/ecosire-error.log",
"log_group_name": "/ec2/ecosire/nginx-errors",
"log_stream_name": "{instance_id}"
}
]
}
}
}
}
# Start the agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config \
-m ec2 \
-c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json \
-s
Automatisierte Backups
Richten Sie automatisierte PostgreSQL-Backups auf S3 ein:
# Create backup script
cat > /opt/ecosire/scripts/backup-db.sh << 'EOF'
#!/bin/bash
set -e
DATE=$(date +%Y-%m-%d-%H%M%S)
BACKUP_FILE="/tmp/ecosire-db-${DATE}.sql.gz"
S3_BUCKET="s3://your-backups-bucket/postgres"
# Dump the database (connects via Docker network)
docker exec ecosire-postgres pg_dump \
-U ecosire \
-d ecosire_dev \
--no-owner \
--no-privileges \
| gzip > "$BACKUP_FILE"
# Upload to S3
aws s3 cp "$BACKUP_FILE" "$S3_BUCKET/"
# Clean up local file
rm "$BACKUP_FILE"
# Delete backups older than 30 days from S3
aws s3 ls "$S3_BUCKET/" \
| awk '{print $4}' \
| sort \
| head -n -30 \
| xargs -I {} aws s3 rm "$S3_BUCKET/{}" 2>/dev/null || true
echo "Backup complete: ${DATE}"
EOF
chmod +x /opt/ecosire/scripts/backup-db.sh
# Schedule daily backups at 3 AM UTC
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/ecosire/scripts/backup-db.sh >> /var/log/db-backup.log 2>&1") | crontab -
IAM-Rollenkonfiguration
Fügen Sie Ihrer EC2-Instanz eine IAM-Rolle für den AWS-Servicezugriff (S3, CloudWatch, SES) hinzu:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::your-products-bucket",
"arn:aws:s3:::your-products-bucket/*",
"arn:aws:s3:::your-backups-bucket",
"arn:aws:s3:::your-backups-bucket/*"
]
},
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricData",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
Wenn die IAM-Rolle Ihrer Instanz zugeordnet ist, verwenden AWS SDK-Aufrufe automatisch Instanzanmeldeinformationen – es ist kein Zugriffsschlüssel/geheimer Schlüssel in Ihren Umgebungsvariablen erforderlich.
Häufige Fallstricke und Lösungen
Falle 1: Keine elastische IP – IP-Änderungen beim Neustart
Durch das Stoppen und Starten (nicht Neustarten) einer EC2-Instanz wird eine neue öffentliche IP zugewiesen. Ohne eine elastische IP geht Ihr DNS kaputt. Weisen Sie unmittelbar nach dem Start Ihrer Instanz eine elastische IP zu und verknüpfen Sie sie.
Falle 2: SSH-Zugriff gesperrt
Wenn Sie Ihren SSH-Schlüssel verlieren oder sich durch eine Fehlkonfiguration von Sicherheitsgruppen aussperren, verwenden Sie EC2 Instance Connect (browserbasiertes SSH) über die AWS-Konsole oder den Session Manager (erfordert die Installation des SSM-Agenten, der standardmäßig mit Ubuntu geliefert wird). Als letzten Ausweg trennen Sie das Root-EBS-Volume, hängen es an eine andere Instanz an, reparieren die Datei „authorized_keys“ und hängen es erneut an.
Falle 3: Während der Bereitstellung ist nicht genügend Speicherplatz vorhanden
Der Build-Cache .next und node_modules wachsen während der Entwicklung erheblich. Überwachen Sie die Festplattennutzung mit df -h und stellen Sie einen CloudWatch-Alarm auf disk_used_percent > 80 % ein. Der Befehl ncdu (ncdu /) identifiziert, welche Verzeichnisse Speicherplatz verbrauchen.
Falle 4: Speichererschöpfung durch Node.js OOM
Node.js hat ein Standardspeicherlimit (1,4 GB bei 64-Bit), das bei großen Anwendungen zu OOM-Abstürzen führen kann. Legen Sie node_args: '--max-old-space-size=1024' in Ihrer PM2-Ökosystemdatei fest, um die Speichernutzung explizit zu begrenzen. Stellen Sie max_memory_restart etwas höher ein, um bei Überschreitung einen automatischen Neustart durchzuführen.
Falle 5: T3-CPU-Drosselung unter anhaltender Last
T3-Instanzen nutzen „CPU-Credits“ für Spitzenleistung. Längere Vorgänge mit hoher CPU-Leistung (große Builds, umfangreiche Datenbankabfragen) erschöpfen das Guthaben, was zu einer Drosselung der „Grundleistung“ führt. Überwachen Sie CPUCreditBalance in CloudWatch. Wenn das Guthaben ständig aufgebraucht ist, führen Sie ein Upgrade auf eine c6i-Instanz durch oder aktivieren Sie den „unbegrenzten“ Modus (zusätzliche Kosten pro CPU-Stunde über dem Basiswert).
Häufig gestellte Fragen
Soll ich EC2 oder einen verwalteten Dienst wie AWS Elastic Beanstalk verwenden?
EC2 gibt Ihnen die volle Kontrolle: die genaue Node.js-Version, Dateisystemzugriff, die Möglichkeit, Docker-Sidecar-Container auszuführen und benutzerdefinierte Nginx-Konfiguration. Elastic Beanstalk verwaltet die zugrunde liegende Infrastruktur, schränkt jedoch Ihre Optionen ein und erhöht die Komplexität bei der Fehlerbehebung. Für ein Team, das mit der Linux-Serververwaltung vertraut ist, ist EC2 mit PM2 + Nginx einfacher und vorhersehbarer als verwaltete Plattformen. Verwenden Sie Beanstalk, wenn Sie möchten, dass die Plattform die Skalierung und das Gesundheitsmanagement automatisch übernimmt.
Wie gehe ich mit Bereitstellungen ohne Ausfallzeiten auf EC2 um?
Der PM2-Befehl pm2 reload sorgt für null Ausfallzeiten für Cluster-Modus-Prozesse (NestJS-API). Erstellen Sie für Next.js (Fork-Modus) zuerst die neue Version und laden Sie dann PM2 neu. Während der wenigen Sekunden, die PM2 benötigt, um Prozesse zu wechseln, stellt Nginx eingehende Anfragen in die Warteschlange (mit einer kleinen Zeitüberschreitung). Für wirklich null Ausfallzeiten verwenden Sie zwei EC2-Instanzen hinter einem ALB (Application Load Balancer) und stellen diese auf einer bereit, während die andere den Datenverkehr verarbeitet.
Wann sollte ich die automatische Skalierung verwenden?
Die automatische Skalierung erhöht die betriebliche Komplexität erheblich – Zustandsprüfungen, Startvorlagen, Lastausgleichsfunktionen und Überlegungen zur Sitzungsaffinität. Für Anwendungen mit vorhersehbarem Datenverkehr ist eine richtig dimensionierte EC2-Instanz mit vertikaler Skalierung (größerer Instanztyp) einfacher und oft kostengünstiger als horizontale automatische Skalierung. Erwägen Sie die automatische Skalierung, wenn Sie Traffic-Spitzen haben, die mehr als das Fünffache des Basiswerts betragen und die Kosten für den Betrieb einer dauerhaft größeren Instanz die Komplexität der automatischen Skalierung übersteigen.
Wie migriere ich später von EC2 zu Containern?
Beginnen Sie mit der Containerisierung Ihrer Anwendung mit Docker (schreiben Sie eine Docker-Datei für jede App). Testen Sie es lokal mit Docker Compose. Dann wählen Sie zwischen ECS Fargate (serverlose Container, einfacher) oder EKS (Kubernetes, leistungsfähiger, aber komplexer). Die Migration ist unterbrechungsfrei, wenn Sie die Containerisierung inkrementell durchführen – führen Sie die Containerversion hinter demselben Nginx/Cloudflare-Setup aus, überprüfen Sie das Verhalten und stellen Sie dann um.
Was ist die kostengünstigste Möglichkeit, EC2 in der Produktion auszuführen?
Erwerben Sie eine einjährige Reserved Instance (keine oder teilweise Vorauszahlung) für Ihre Basisinstanz – 40 % günstiger als bei Bedarf. Für zusätzliche Kapazität bei Datenverkehrsspitzen verwenden Sie Spot-Instanzen (bis zu 90 % günstiger), wenn Ihre Anwendung Unterbrechungen bewältigen kann. Richten Sie einen CloudWatch-Abrechnungsalarm bei 80 % Ihres Monatsbudgets ein, damit unerwartete Kostensteigerungen frühzeitig erkannt werden. Für produktive Webanwendungen bieten Reserved Instances das beste Gleichgewicht zwischen Kosten und Zuverlässigkeit.
Nächste Schritte
Das Ausführen einer Produktions-Webanwendung auf EC2 erfordert kontinuierliche betriebliche Aufmerksamkeit – Sicherheitspatches, Festplattenverwaltung, Leistungsüberwachung und Bereitstellungsautomatisierung. ECOSIRE führt eine EC2 t3.large-Produktionsinstanz aus, die 5 Anwendungen über mehrere Domänen hinweg bedient, mit automatisierten Backups, CloudWatch-Überwachung und PM2-Bereitstellungen ohne Ausfallzeiten.
Ganz gleich, ob Sie AWS-Infrastrukturberatung, EC2-Bereitstellungseinrichtung oder vollständigen DevOps-Support für Ihre Node.js-Anwendung benötigen, [entdecken Sie unsere Dienste] (/services), um zu erfahren, wie wir Ihnen helfen können.
Geschrieben von
ECOSIRE Research and Development Team
Entwicklung von Enterprise-Digitalprodukten bei ECOSIRE. Einblicke in Odoo-Integrationen, E-Commerce-Automatisierung und KI-gestützte Geschäftslösungen.
Verwandte Artikel
Cloud Hosting for ERP: AWS vs Azure vs Google Cloud
A detailed comparison of AWS, Azure, and Google Cloud for ERP hosting in 2026. Covers performance, cost, regional availability, managed services, and ERP-specific recommendations.
Cloud vs On-Premise ERP in 2026: The Definitive Guide
Cloud vs on-premise ERP in 2026: total cost analysis, security comparison, scalability, compliance, and the right deployment model for your business.
Docker Compose for Development: Local Infrastructure
Docker Compose for local development: PostgreSQL, Redis, Authentik, networking, health checks, volume management, and environment-specific configurations for TypeScript monorepos.