
Sanfter Umbau: Der Astro Nginx Reverse Proxy als Brücke zum neuen Frontend

Die Angst vor dem Legacy-Code und die Rettung durch das Strangler Fig Pattern
Kalter Schweiß auf der Stirn, der Puls steigt leicht an – kennst du dieses beklemmende Gefühl, wenn du eine uralte, historisch gewachsene Codebasis öffnen musst? Irgendwo tief im Serverraum läuft ein betagtes PHP-System oder ein in die Jahre gekommenes CMS, das dein Unternehmen am Leben hält. Jeder weiß: Die kleinste unbedachte Änderung an diesem wackeligen Kartenhaus kann zum Totalausfall führen. Die Lösung für genau dieses Dilemma ist ein clever konfigurierter Astro Nginx Reverse Proxy.
Anstatt den Reflex zu bedienen, alles niederzureißen und auf der grünen Wiese neu zu bauen (was oft Budgets sprengt und Deadlines reißt), nutzen wir den Astro Nginx Reverse Proxy für einen sanften Übergang. Wir bauen neue, glänzende Funktionen mit modernster Technologie, während der brüchige Monolith im Hintergrund einfach friedlich weiteratmet.
Willkommen in der Welt des Strangler Fig Patterns (Würgefeigen-Muster). Dieses architektonische Meisterwerk hilft dir dabei, alte monolithische Systeme schrittweise durch moderne Microservices zu ersetzen. Stell dir eine Würgefeige vor, die in der Natur einen alten, sterbenden Baum sanft von oben nach unten umschließt, bis sie irgendwann selbst das Fundament bildet. Genau das machen wir mit deiner Software-Architektur. Wir etablieren eine sogenannte Fassade, die den Datenverkehr intelligent steuert. Ein Teil der Anfragen geht weiterhin zum alten, vertrauten System, während Anfragen für brandneue Features nahtlos zu unserem neuen, modernen Service umgeleitet werden.
Diese schützende Fassade setzen wir technisch um, indem wir einen Astro Nginx Reverse Proxy einrichten. Ein Proxy-Server wird typischerweise eingesetzt, um die Last auf mehrere Server zu verteilen oder Inhalte von verschiedenen Webseiten nahtlos darzustellen. In unserem Setup fungiert Nginx als unbestechlicher Verkehrspolizist. Wenn ein Nutzer beispielsweise deine-domain.de/alte-seite aufruft, winkt Nginx ihn direkt zum alten PHP-System durch. Tippt der Nutzer aber deine-domain.de/neue-kampagne ein, greift Nginx ein und schickt die Anfrage unbemerkt an unser neues, rasend schnelles Frontend, das wir mit Astro gebaut haben.
Warum ausgerechnet Astro? Weil Astro ein Framework ist, das die Vorzüge traditioneller CMS mit den Bedürfnissen moderner Webentwicklung vereint. Es wurde als All-in-One-Lösung konzipiert. Wir können damit kleine, unabhängige Micro-Frontends bauen, die sich perfekt in die bestehende Seite einfügen. Die Magie beginnt genau hier: Wir isolieren das Risiko. Wenn in unserem neuen Astro-Code ein Fehler auftritt, betrifft das ausschließlich die neue Kampagnenseite. Das alte PHP-System, das vielleicht den wichtigen Checkout-Prozess deines Shops abwickelt, bleibt davon völlig unberührt.
Es ist, als würdest du an dein altes Haus einen hochmodernen Wintergarten anbauen. Du musst nicht das ganze Haus abreißen, um die Nachmittagssonne zu genießen. Du öffnest einfach eine neue Tür. Und wie wir diese Tür auf technischer Ebene millimetergenau einbauen, schauen wir uns im nächsten Schritt an.

Nginx als unsichtbarer Verkehrspolizist – Die technische Einrichtung
Wie schaffen wir es nun, dass unser altes PHP-Backend und das brandneue Astro-System friedlich auf demselben Server koexistieren, ohne sich gegenseitig zu blockieren? Die Antwort liegt in der richtigen Konfiguration unseres Webservers. Wir machen Nginx zu unserem unbestechlichen Verkehrspolizisten.
Grundsätzlich ist Nginx unglaublich effizient darin, als sogenannter Reverse Proxy zu agieren. Wenn Nginx eine Anfrage auf diese Weise weiterleitet, nimmt er den Request des Nutzers entgegen, sendet ihn an einen spezifizierten Proxy-Server im Hintergrund, holt die Antwort ab und schickt sie nahtlos an den Client zurück. Der Endnutzer bemerkt von diesem internen Ping-Pong absolut nichts; für ihn sieht es so aus, als käme die gesamte Webseite aus einer einzigen, massiven Quelle.
Das Problem bei der Kombination von Nginx und Astro ist folgendes: Nginx versteht von Haus aus kein JavaScript. Wenn wir Astro also im Server-Side-Rendering-Modus (SSR) betreiben wollen, um dynamische Inhalte auszuliefern, müssen wir einen kleinen Zwischenschritt einbauen. Wir lassen Node.js die generierten Astro-Inhalte auf einem internen, von außen nicht erreichbaren Port laufen (zum Beispiel Port 4321), und weisen Nginx an, als Reverse Proxy für genau diesen Node-Server zu fungieren.
Um diese magische Umleitung zu aktivieren, verwenden wir die proxy_pass Direktive von Nginx, die wir innerhalb eines spezifischen location Blocks platzieren. Wenn wir nun eine neue Kampagnenseite mit Astro gebaut haben, definieren wir einfach einen neuen Pfad. Die Adresse, an die Nginx weiterleitet, kann dabei problemlos als IP-Adresse mit einem spezifischen Port angegeben werden.
Ein rudimentäres Konfigurationsbeispiel sieht dann so aus: Wir definieren location /neue-kampagne/ und sagen Nginx: Alles, was hier ankommt, schiebst du bitte per proxy_pass http://localhost:4321 an unser Astro-Frontend weiter. Der restliche Traffic, der nicht auf diesen Pfad passt, geht weiterhin den gewohnten Weg zu deinem alten PHP-System.
Doch hier lauert eine kleine Falle, die viele Entwickler beim ersten Versuch übersehen. Wenn Nginx die Anfrage intern an den Node-Server weiterreicht, verändert er standardmäßig bestimmte Header-Felder der ursprünglichen Anfrage, wie beispielsweise das "Host"-Feld und "Connection". Dadurch weiß unser Astro-Server plötzlich nicht mehr, von welcher echten IP-Adresse der Nutzer eigentlich kommt oder wie die ursprüngliche Domain lautete.
Um das zu reparieren und dem Proxy-Server im Hintergrund die echten Client-Informationen mitzuteilen, müssen wir die Header-Felder des Client-Requests modifizieren. Wir nutzen dafür die proxy_set_header Direktive. Diese Direktive kann im location Block (oder auch höher im Server-Kontext) platziert werden. Damit setzen wir beispielsweise das "Host"-Feld explizit auf die $host Variable. So bleibt die Illusion perfekt: Astro erhält alle nötigen Informationen, um korrekt zu arbeiten, und der Nginx-Server schirmt die beiden Welten sicher voneinander ab.

Hände an die Tastatur – Echte Nginx- und Astro-Konfigurationen
Damit unser Nginx-Webserver als intelligenter Reverse Proxy arbeiten kann, müssen wir ihm exakte Anweisungen geben. Nginx spricht von Haus aus kein JavaScript. Daher lassen wir unser kompiliertes Astro-Projekt über einen lokalen Node.js-Server auf einem internen Port (z. B. Port 4321) laufen.
Öffne deine Nginx-Konfigurationsdatei (meist unter /etc/nginx/sites-available/deine-domain) und füge folgenden Block in deinen server-Kontext ein. Hier passiert die eigentliche Magie:
1location /neue-kampagne/ {
2 # Der Slash am Ende ist entscheidend! Er sorgt dafür,
3 # dass Nginx den Pfad umschreibt.
4 proxy_pass http://localhost:4321/;
5
6 # Standardmäßig ändert Nginx den "Host" und schließt die Verbindung.
7 # Wir überschreiben das, um Astro die echten Client-Daten zu liefern.
8 proxy_set_header Host $host;
9 proxy_set_header X-Real-IP $remote_addr;
10 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
11 proxy_set_header X-Forwarded-Proto $scheme;
12
13 # Optional: Buffering aktivieren, um den Node-Server zu entlasten,
14 # wenn langsame Clients die Daten herunterladen.
15 proxy_buffering on;
16 proxy_buffer_size 4k;
17}Warum ist das so wichtig? Wenn du in der proxy_pass-Direktive einen konkreten Pfad (hier den simplen Slash /) angibst, ersetzt Nginx den Teil der URL, der mit dem location-Block übereinstimmt. Ohne diesen winzigen Slash am Ende würde Nginx versuchen, die Anfrage falsch weiterzuleiten, und du landest im 404-Nirvana. Zudem puffert Nginx standardmäßig die Antworten (proxy_buffering on), was die Leistung bei langsamen Endgeräten enorm optimiert.
Das alte PHP-System läuft völlig unberührt in einem anderen location-Block weiter. Doch wir sind noch nicht ganz fertig. Unser Astro-Projekt muss wissen, dass es sich ab sofort in einem Unterverzeichnis befindet.
Wenn du das nicht konfigurierst, fordert Astro seine CSS- und JavaScript-Dateien (die sogenannten Assets) hartkodiert vom Hauptverzeichnis der Domain an – was fehlschlägt, weil dort dein altes CMS sitzt. Wir passen daher die astro.config.mjs an:
1import { defineConfig } from 'astro/config';
2import node from '@astrojs/node';
3
4export default defineConfig({
5 // Teilt Astro mit, dass alle Assets unter diesem Pfad liegen
6 base: '/neue-kampagne',
7
8 // Wir nutzen Hybrid-Rendering: Statische Seiten wo möglich,
9 // Server-Side-Rendering (SSR) wo nötig.
10 output: 'hybrid',
11
12 // Der Node-Adapter bereitet das Projekt für unseren internen Port vor.
13 adapter: node({
14 mode: 'standalone'
15 })
16});Mit dem output: 'hybrid' Setting in Astro 2.0+ holst du das Beste aus beiden Welten heraus. Du kannst hochperformante statische Startseiten (SSG) rendern und gleichzeitig API-Endpunkte oder dynamische Formulare serverseitig verarbeiten. Die Performance-Gewinne sind extrem spürbar, und dein Build-Prozess wird nicht mehr durch das Rendern Tausender unwichtiger Unterseiten blockiert.

Server Islands und Micro-Frontends – Dynamik ohne Ladebalken
Wir haben nun die technische Infrastruktur geschaffen. Der Nginx-Verkehrspolizist leitet unsere Nutzer sicher und unsichtbar auf das neue Astro-System um. Doch wie strukturieren wir diese brandneuen Funktionen im Code, ohne sofort den nächsten schwerfälligen Monolithen zu erschaffen?
Die Antwort lautet: Micro-Frontends. Anstatt eine riesige, zusammenhängende Anwendung zu bauen, spalten wir die Weboberfläche in kleinere, völlig unabhängige Einheiten auf. Diese Einheiten können separat entwickelt, getestet und bereitgestellt werden.
Astro bietet für diese Architektur ein absolut geniales Werkzeug: Server Islands. Diese Technologie ermöglicht ein nicht-blockierendes Rendern von Komponenten, die quasi "on demand" (bei Bedarf) geladen werden. Stell dir vor, deine neue Kampagnenseite hat einen extrem rechenintensiven Produktfilter oder einen personalisierten Warenkorb. Anstatt die gesamte Seite warten zu lassen, bis diese dynamischen Daten vom Server berechnet wurden, liefert Astro das statische Grundgerüst der Seite sofort aus. Die dynamischen Teile werden als isolierte "Inseln" nachträglich eingefügt.
Lass uns ansehen, wie elegant das im Astro-Code aussieht:
1---
2// src/pages/neue-kampagne/index.astro
3import HeroBanner from '../../components/HeroBanner.astro';
4import UserCart from '../../components/UserCart.astro';
5import SkeletonLoader from '../../components/SkeletonLoader.astro';
6---
7
8<html lang="de">
9 <body>
10 <HeroBanner title="Sommer-Sale 2026" />
11
12 <UserCart server:defer>
13 <SkeletonLoader slot="fallback" />
14 </UserCart>
15 </body>
16</html>In diesem Setup agiert die SkeletonLoader-Komponente als Platzhalter (Fallback), während das eigentliche Warenkorb-Micro-Frontend im Hintergrund abgerufen wird. Das Resultat? Der Nutzer sieht sofort Inhalte und erlebt eine unglaublich flüssige Performance.
Abhängigkeiten klug verwalten Eine der größten Herausforderungen beim Einsatz von Micro-Frontends ist die Verwaltung gemeinsamer Abhängigkeiten (Dependencies). Da wir mit Astro völlige Freiheit haben, Frameworks wie React, Vue oder Svelte zu mischen, müssen wir aufpassen, dass wir den Browser nicht mit doppelten Bibliotheken überladen.
Astro macht auch das erstaunlich einfach. Wir können eine sogenannte importmap nutzen, um Abhängigkeiten wie React über alle unsere Micro-Frontends hinweg zu teilen. Diese Abhängigkeiten laden wir extrem schnell über ein CDN wie esm.sh:
1<script type="importmap">
2{
3 "imports": {
4 "react": "https://esm.sh/react@18.2.0",
5 "react-dom": "https://esm.sh/react-dom@18.2.0"
6 }
7}
8</script>Was passiert hier? Wenn verschiedene Komponenten auf deiner Seite React benötigen, wird es nicht mehrfach in den finalen Code gebündelt. Stattdessen werden diese Abhängigkeiten beim Build-Prozess als extern markiert und nach dem ersten Laden der Seite im Browser des Nutzers gecacht. Das reduziert Code-Redundanzen drastisch und verbessert die Ladegeschwindigkeit deiner neuen Micro-Frontends erheblich. Deine Hauptanwendung (die Shell) setzt diese einzelnen Fragmente auf dem Server nahtlos zusammen, bevor sie an den Browser geschickt werden.

Der Go-Live – Reibungsloses Deployment
Die lokale Entwicklungsumgebung steht, der Code ist durch Micro-Frontends sauber strukturiert, und unsere Server Islands laden pfeilschnell im Hintergrund. Doch wie bringen wir dieses moderne Setup nun sicher in die Produktion, ohne dass der Live-Betrieb ins Stocken gerät?
Wenn wir unser Astro-Projekt für den Live-Server vorbereiten und npm run build ausführen, durchläuft das Framework einen mehrstufigen Build-Prozess. Da wir uns zuvor für den Hybrid-Modus entschieden haben, erzeugt Astro das Beste aus zwei Welten : Es generiert blitzschnelle statische HTML-Dateien für Seiten, die sich selten ändern (SSG) , und erstellt parallel ein serverseitiges JavaScript-Bundle für unsere dynamischen Micro-Frontends (SSR).
Um diesen generierten Server-Code auf deinem Live-Server auszuführen, benötigen wir einen stabilen Prozess. Da wir den @astrojs/node Adapter im Standalone-Modus verwenden, reicht ein simples Skript. In der professionellen Praxis nutzt man dafür Prozessmanager wie PM2, um sicherzustellen, dass der Node-Server bei einem unerwarteten Fehler sofort automatisch neu startet.
Eine einfache ecosystem.config.js für PM2 sieht so aus:
1module.exports = {
2 apps: [
3 {
4 name: "neue-kampagne-astro",
5 script: "./dist/server/entry.mjs",
6 instances: "max", // Nutzt alle verfügbaren CPU-Kerne
7 exec_mode: "cluster",
8 env: {
9 NODE_ENV: "production",
10 PORT: 4321,
11 HOST: "127.0.0.1" // Nur lokal erreichbar, Nginx schirmt ab
12 }
13 }
14 ]
15};Sobald dieser kleine Node-Server auf dem internen Port 4321 lauscht, übernimmt unser bereits konfigurierter Nginx-Webserver die Arbeit als Reverse Proxy. Nginx nimmt die Anfragen von außen an, puffert die Antworten effizient und schickt sie nahtlos an den Client zurück.

Die sanfte digitale Sanierung
Mit dieser Architektur haben wir das mächtige Strangler Fig Pattern erfolgreich in die Praxis umgesetzt. Wir haben das enorme Risiko und die Kosten eines kompletten System-Neubaus umgangen. Stattdessen haben wir das bestehende, monolithische System schrittweise und ohne Ausfallzeiten durch moderne Microservices ergänzt.
Dein altes PHP-System verrichtet im Hintergrund weiterhin zuverlässig seinen Dienst, während du neue Anforderungen blitzschnell umsetzt. Astro liefert uns dafür die perfekte technologische Basis: Eine herausragende Performance-Optimierung durch partielle Hydratation , ein durch sauberes HTML gestütztes SEO-freundliches Design und die absolute Flexibilität, nahezu jede beliebige Frontend-Bibliothek (wie React oder Vue) nahtlos zu integrieren. Du hast nun das Fundament, um dein Web-Projekt Raum für Raum sicher in die Zukunft zu führen.
Teil der Serie
Veraltete Web-Projekte schrittweise retten
Häufig gestellte Fragen (FAQ)
Ausblick auf Teil 2
Im nächsten Teil der Serie, „Das bestehende CMS behalten, aber ein modernes Design nutzen“, gehen wir einen Schritt weiter. Was ist, wenn die Redakteure ihr geliebtes Contao oder WordPress unbedingt behalten wollen, das Frontend aber dringend einen frischen Anstrich braucht? Wir zeigen dir, wie du die Inhalte über eine REST-API oder GraphQL abgreifst und in eine hochmoderne Oberfläche gießt – die perfekte Trennung von Backend-Logik und Frontend-Design.

Dietrich Bojko
Senior Webentwickler
Webinteger arbeitet seit vielen Jahren produktiv mit
Linux-basierten Entwicklungsumgebungen unter Windows.
Der Fokus liegt auf
performanten Setups mit WSL 2, Docker, PHP, Node.js und modernen
Build-Tools in realen Projekten –
nicht auf theoretischen Beispielkonfigurationen.
Die Artikel dieser Serie entstehen direkt aus dem täglichen Einsatz in Kunden- und Eigenprojekten und dokumentieren bewusst auch typische Fehler, Engpässe und bewährte Workarounds.


