Kein Cookie Banner mehr nötig: Ghost CMS komplett ohne Third-Party-Requests einsetzen (docker compose)
Schütze die Privatsphäre deiner Leser und beschleunige deine Ghost-Instanz: Mit nur einer Compose File alle Third-Party-Requests eliminieren und Inhalte mit Redis cachen.
Kaum eine Website kommt ohne Third-Party-Requests aus. Dabei handelt es sich um alle Anfragen, die eine Website bei einem Besuch an dritte Server schickt. Im Falle von Ghost sind das:
- JavaScript-Bibliotheken von
cdn.jsdelivr.net(der Code für das Ghost Portal, die Suche und, wenn aktiviert, die Kommentarsektion) - Embeds. Bei einem YouTube-Video werden beispielsweise Video-Metadaten, ein Thumbnail und die im Player verwendeten Schriftarten geladen.
Third-Party-Requests sind nicht per se schlecht: CDNs liefern vielgenutzte Code-Bibliotheken zuverlässig und schnell aus und dank YouTube spart man sich als kleiner Website-Betreiber einiges an Speicherplatz und Bandbreite, wenn man ab und an mal ein Video zeigen möchte. Problematisch werden Third-Party-Requests jedoch, wenn sie personenbezogene Daten weitergeben – wie die IP-Adresse oder Browser-Fingerprinting-Informationen (User-Agent, Referrer). Betreiber_innen müssen dann eine DSGVO-Rechtsgrundlage sicherstellen, Einwilligungen einholen (in der Regel mithilfe aufdringlicher Cookie-Banner) und Datenübermittlungen in Drittländer verhindern. Macht man das nicht, wird es schnell teuer.

Personenbezogene Daten umfassen erst einmal jede Information, mit der Nutzer identifiziert werden können. IP-Adressen, Standortdaten, Browser-Bezeichnungen und Tracking-Cookies ermöglichen Profilbildung und Tracking über mehrere Websites hinweg. Das ist nicht nur ein Datenschutzrisiko, sondern kann auch Performance und Verfügbarkeit beeinträchtigen: Denn für jede Domain muss erst einmal die zugehörige IP-Adresse nachgeschlagen werden. Hat ein externer Anbieter gerade Serverprobleme, so betrifft das alle, die sich auf ihn verlassen. Das passiert häufiger, als man denkt.

Wer seine Ghost-Installation ein bisschen resilienter machen möchte, hat im Grunde zwei Möglichkeiten: Entweder man hostet die Code-Bibliotheken für das Ghost Portal, die Suche und die Kommentarsektion selbst und kümmert sich regelmäßig um Updates. Oder man bezieht weiterhin aktuellsten Versionen der benötigten Dependencies von JSDelivr und speichert sie mithilfe einer effektiven Cache-Policy auf dem eigenen Server zwischen. Wir setzen für diese Anleitung auf Letzteres. Das Prinzip ist simpel:
- Unter
https://meine-website.debetreiben wir ganz normal unsere Ghost-Instanz. - Requests, die mit
https://meine-website.de/proxy/beginnen, leiten wir auf einen kleinen, leichten nginx-Server um.- Dieser schreibt die angeforderte URL auf die Domain unseres CDN um (
https://meine-website.de/proxy/npm/@tryghost/sodo-search@~1.8/umd/sodo-search.min.js=>https://cdn.jsdelivr.net/ghost/sodo-search@~1.8/umd/sodo-search.min.js), - löscht die Besucher-IP und andere personenbezogene Daten aus dem Header,
- lädt die angeforderte Ressource selbst schnell herunter,
- gibt sie der Besucher_in zurück, als hätte sie schon die ganze Zeit auf unserem Server gelegen,
- und speichert sie für einen definierten Zeitraum zwischen.
- Dieser schreibt die angeforderte URL auf die Domain unseres CDN um (
Wenn wir schonmal dabei sind, beschleunigen wir auch die Anfragen an unsere Seite. Dazu nutzen wir den eingebauten Redis Cache Adapter.
Diese Anleitung führt Schritt für Schritt durch das Setup der Docker Compose File, unseres nginx‑Proxies für JSDelivr und YouTube-Embeds, Redis und das notwendige Routing. Das YouTube-Proxy ist auf mein Theme Spectre zugeschnitten, das – wenngleich etwas umständlich – datenschutzfreundliche YouTube-Embeds ermöglicht. Der Rest dieses Setups ist aber unabhängig vom Theme.
Voraussetzungen
- Eine Domain zeigt auf den Server
- Docker und Docker Compose sind installiert
- Das externe Docker‑Netzwerk mit dem Namen proxy muss existieren, weil Ghost und der Nginx‑Proxy darüber von Traefik erreichbar gemacht werden, während sie intern zusätzlich das Default‑Netz gemeinsam nutzen.
- Traefik v3 dient als bereits laufender Edge‑Proxy für TLS und Routing. Wer Unterstützung bei der Installation braucht, findet auf GoNeuland.de eine sehr gute deutschsprachige Schritt‑für‑Schritt‑Anleitung.

Übersicht
Bevor wir in die Konfiguration einsteigen, schauen wir uns an, wie die einzelnen Komponenten zusammenarbeiten. Unser Setup besteht aus drei Docker-Containern, die über das default Netzwerke miteinander kommunizieren.
Ghost ist das Content Management System. Es bedient alle regulären Anfragen wie Blog-Posts, Seiten, das Admin-Panel oder die ActivityPub-API.
Redis ist ein In-Memory-Datenbank-System, das als Cache-Backend fungiert. Ghost speichert dort beispielsweise vorgerenderte Seiten, Statistiken und Suchergebnisse. Redis ist sehr schnell, weil es alles im Arbeitsspeicher hält, und persistent, weil wir die Daten in ein lokales Verzeichnis schreiben. So bleiben Cache-Einträge auch nach einem Neustart erhalten.
Nginx-Proxy ist ein schlanker Webserver-Container, der ausschließlich für Anfragen unter https://meine-website.de/proxy/zuständig ist. Er leitet diese Anfragen an die jeweiligen Drittdienste weiter (JSDelivr für NPM-Pakete, YouTube für Embeds und Thumbnails), entfernt dabei personenbezogene Daten aus den Request-Headern und cached die Antworten lokal. Für Besucherinnen und Besucher sieht es so aus, als kämen alle Ressourcen direkt vom eigenen Server.
Traefik sitzt als Reverse Proxy vor diesen drei Containern und entscheidet anhand der URL, wohin eine Anfrage geschickt wird. Die Proxying-Software stellt aber auch automatisch SSL-Zertifikate aus oder komprimiert Antworten mit gzip. Die Routing-Logik ist einfach:
- Anfragen an
https://meine-website.de/proxy/*→ Nginx-Proxy - Alle anderen Anfragen an
https://meine-website.de/*→ Ghost
Diese Architektur trennt Verantwortlichkeiten sauber: Ghost kümmert sich um Inhalte, Redis um Caching, Nginx um Third-Party-Requests und Traefik um SSL und Routing. Alle Container laufen in Docker, was Deployment, Updates und Wartung vereinfacht. Die gesamte Konfiguration ist in einer docker-compose.yml und wenigen begleitenden Dateien zusammengefasst.
Setup
Repository klonen und ins Projektverzeichnis wechseln
In diesem Beispiel heißt unser Projektordner meine-website.de.
Ordnerstruktur
meine-website.de/
├── docker-compose.yml
├── .env
├── config.production.json
├── nginx-proxy.conf
├── content/ # Ghost-Daten, Themes
├── redis/ # Redis-Persistenz
└── proxy-cache/ # Nginx-Cache.env kopieren und anpassen
Die Datei example.env liefert sinnvolle Defaultwerte für Domain, SMTP‑Mail, Ghost‑HTTP‑Cache und den Redis‑Cache‑Adapter, die in Compose automatisch in den Ghost‑Container injiziert werden. Dabei steuern die HTTP-Caching-Werte Ghosts eigene HTTP‑Cachezeiten für Seiten, Sitemaps und Assets, während die Redis-Cache-Werte die Redis‑Verbindung, TTL und Retry‑Strategien definieren.
Für den Start reicht es, DOMAIN, die Mail‑Werte und optional die TTL‑Werte für Redis und die HTTP‑Caches zu setzen, um Performance‑ und Aktualitätsanforderungen auszubalancieren.
config.production.json und Compose File überprüfen
Der Ghost‑Service ist auf Produktionsbetrieb ausgelegt, lauscht auf Port 2368 und nutzt SQLite über eine Content‑Volume‑Datei, wodurch Backups leicht möglich sind, weil alle Inhalte und die Datenbank unter /var/lib/ghost/content liegen. Zusätzlich bindet Compose eine eigene config.production.json ein, die Ghost sagt, Portal, Suche und Kommentare nicht direkt von CDNs zu laden, sondern über die Proxy‑Pfade des eigenen Hosts zu beziehen.
In docker-compose.yml sollten Container- und Label-Bezeichnungen ggfs. angepasst werden.
nginx-Proxy im Detail
Die Nginx‑Konfiguration definiert zwei Cache‑Zonen: eine für JSDelivr mit 24 Stunden und eine für YouTube mit einer Stunde, passend zum Änderungsverhalten der Ressourcen.
In den /proxy/npm/‑Locations werden die Header Host, X‑Real‑IP und X‑Forwarded‑For geleert, TLS‑SNI aktiviert und mit proxy_cache_use_stale sowie proxy_cache_lock für Belastungsspitzen und Upstream‑Hänger vorgesorgt, was bewährt ist und den Best Practices des Nginx‑Content‑Caching entspricht.
Für YouTube sind getrennte Locations für oEmbed, Thumbnails und Embeds eingerichtet, die ebenfalls Header strippen, Query‑Parameter korrekt durchreichen und per Cache Header den Status sichtbar machen, was Diagnose und Tuning erleichtert.
Traefik‑Routing im Detail
Die Compose‑Labels teilen den Traffic logisch auf: Eine HTTPS‑Router‑Regel schickt Host(${DOMAIN}) mit !PathPrefix(/proxy/) an Ghost, während eine zweite Regel Host(${DOMAIN}) && PathPrefix(/proxy/) den Nginx‑Proxy anspricht, jeweils mit TLS und passenden EntryPoints. Zusätzlich werden ActivityPub‑Routen explizit per separatem Service an https://ap.ghost.org weitergeleitet, womit Ghosts offizieller ActivityPub‑Endpunkt genutzt wird, ohne die Kerninstanz zu verkomplizieren.
Starten, prüfen, beobachten
Zum Starten im Projektordner die folgenden Befehle ausführen:
Die Logs können wie folgt geprüft werden:
Das Starten der drei Services erledigt Compose in einem Rutsch, inklusive Healthchecks, die etwa im Proxy testweise eine JSDelivr‑Ressource über den eigenen Pfad abrufen, um die Kette zu verifizieren.
In den Logs des Proxy helfen die zusätzlichen Header X‑Cache‑Status und X‑Proxy‑Cache zu erkennen, ob eine Ressource gecacht wurde, während Ghosts Healthcheck die Admin‑API unter der Annahme eines HTTPS‑Forwardings prüft, um falsch konfigurierte Proxies früh zu entdecken.
Anpassungen für eigene Bedürfnisse
Cache‑Dauern lassen sich in nginx-proxy.conf je Location feinjustieren, etwa längere Zeiten für Thumbnails und kürzere für oEmbed, was in produktiven Umgebungen je nach Änderungsfrequenz sinnvoll ist.
Ghost‑HTTP‑Cachezeiten und Redis‑TTL können per .env variiert werden, um zwischen aggressiverer Performance und höherer Aktualität abzuwägen, beispielsweise bei häufig aktualisierten Startseiten.
Wer das Spectre‑Theme verwendet, muss das YouTube-Proxying durch folgende Code-Injektion im Site Header aktivieren:
Soweit so gut. Zur Repository geht's hier entlang:
Artikel wurde am 4. Juni 2026 gedruckt. Die aktuelle Version gibt es unter https://spectre.hutt.io/anleitung/ghost-cms-ohne-third-party-requests-einsetzen/.
