Cache-Control auf Hetzner konfigurieren
Sicherheitsrelevantes Caching auf Ihrem Hetzner Cloud Server einrichten — mit differenzierten Nginx location blocks für statische Assets, dynamische Seiten und sensible Bereiche wie Login und Dashboard.
Cache-Control auf Hetzner Cloud Servern
Cache-Control ist der HTTP-Header, der bestimmt, ob und wie lange Browser und Proxies Inhalte zwischenspeichern. Aus Security-Perspektive ist er entscheidend: Ohne no-store auf sensiblen Seiten können Login-Daten, Dashboard-Inhalte oder API-Responses im Browser-Cache verbleiben — auch nach dem Logout. Im Wolf-Agents Web Security Check fließt Cache-Control mit 8 von 166 Punkten in die Bewertung ein.
Auf einem Hetzner Cloud Server (CX, CPX, CAX oder Dediziert) haben Sie volle Kontrolle über die Webserver-Konfiguration. Das ermöglicht eine differenzierte Caching-Strategie: aggressives Caching für statische Assets, Revalidierung für dynamische Seiten und striktes no-store für sensible Bereiche. Beachten Sie dabei die Besonderheiten des Hetzner Load Balancers und der Hetzner CDN-Integration, die eigene Cache-Header hinzufügen können.
Caching-Strategie nach Content-Typ definieren
Auf einem Hetzner vServer läuft typischerweise Nginx (Standard bei Hetzner Apps) oder Apache. Die richtige Cache-Strategie unterscheidet drei Kategorien: Statische Assets mit Fingerprinting bekommen maximales Caching, dynamische Seiten erhalten kurze Caches mit Revalidierung und sensible Bereiche wie Login, Dashboard und API dürfen nie gecacht werden.
# /etc/nginx/conf.d/cache-control.conf
# Statische Assets: aggressives Caching (1 Jahr)
location ~* \.(css|js|woff2|woff|ttf|eot|svg|png|jpg|jpeg|webp|avif|gif|ico)$ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
add_header Vary "Accept-Encoding" always;
} # Dynamische Seiten: kurzer Cache mit Revalidierung
location / {
add_header Cache-Control "public, max-age=0, must-revalidate" always;
add_header Vary "Accept-Encoding, Cookie" always;
} # Sensible Bereiche: kein Caching
location /login {
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
add_header Pragma "no-cache" always;
}
location /dashboard {
add_header Cache-Control "no-store, no-cache, must-revalidate, private" always;
add_header Pragma "no-cache" always;
}
location /api/ {
add_header Cache-Control "no-store, private" always;
} location-Block die add_header-Direktiven des äußeren Blocks vollständig. Wenn Sie in einem Location-Block einen einzelnen Header setzen, gehen alle anderen Header des übergeordneten Blocks verloren. Definieren Sie daher alle Header in jedem Block explizit. Apache-Konfiguration mit mod_expires und mod_headers
Wenn Ihr Hetzner Server Apache verwendet, benötigen Sie die Module mod_expires (für automatische Expiry-Zeiten nach MIME-Typ) und mod_headers (für explizite Cache-Control-Header auf sensiblen Bereichen). Aktivieren Sie beide Module mit sudo a2enmod expires headers.
# /etc/apache2/conf-available/cache-control.conf
<IfModule mod_expires.c>
ExpiresActive On
# Statische Assets: 1 Jahr
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
# HTML: keine automatische Zwischenspeicherung
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
<IfModule mod_headers.c>
# Sensible Bereiche: kein Caching
<LocationMatch "^/(login|dashboard|api)">
Header always set Cache-Control "no-store, no-cache, must-revalidate, private"
Header always set Pragma "no-cache"
</LocationMatch>
# Vary-Header für Content Negotiation
Header always append Vary "Accept-Encoding"
</IfModule> Aktivieren Sie die Konfiguration mit sudo a2enconf cache-control && sudo systemctl reload apache2. Falls mod_expires fehlt, gibt Apache keinen Fehler aus — die Direktiven werden stillschweigend ignoriert.
Verifizierung und Monitoring
Prüfen Sie die Header mit curl für verschiedene URL-Typen. Achten Sie besonders darauf, dass sensible Bereiche tatsächlich no-store zurückgeben und statische Assets den immutable-Wert enthalten.
# Nginx-Konfiguration testen und laden
sudo nginx -t && sudo systemctl reload nginx
# Apache-Konfiguration testen und laden
sudo apachectl configtest && sudo systemctl reload apache2
# Cache-Control auf statischen Assets prüfen
curl -sI https://ihre-domain.de/assets/style.css | grep -i cache-control
# Erwartet: cache-control: public, max-age=31536000, immutable
# Cache-Control auf Login-Seite prüfen
curl -sI https://ihre-domain.de/login | grep -i cache-control
# Erwartet: cache-control: no-store, no-cache, must-revalidate
# Vary-Header prüfen
curl -sI https://ihre-domain.de | grep -i vary
# Erwartet: vary: Accept-Encoding Häufige Fehler bei Cache-Control auf Hetzner
Hetzner CDN/Load Balancer fügt eigene Cache-Header hinzu
Der Hetzner Load Balancer und externe CDN-Dienste können eigene Cache-Control-Header hinzufügen oder bestehende überschreiben. Das führt zu doppelten Cache-Headern. Prüfen Sie mit curl -sI, ob zwei Cache-Control-Header gesendet werden. Lösung: Setzen Sie Header auf dem Backend und konfigurieren Sie den Load Balancer so, dass er Backend-Header durchreicht statt eigene zu setzen.
Browser cacht sensible Seiten nach Logout
Ohne no-store speichert der Browser die HTML-Seite im Disk-Cache. Ein anderer Nutzer am selben Rechner kann über die Zurück-Taste Dashboard-Inhalte sehen — selbst nach dem Logout. Nur no-store verhindert das vollständig. no-cache allein reicht nicht, da es nur eine Revalidierung erzwingt, die Seite aber trotzdem gecacht bleibt.
Verwechslung: no-cache vs. no-store
no-cache bedeutet: Der Browser darf die Ressource cachen, muss aber vor jeder Verwendung beim Server nachfragen (Revalidierung). no-store bedeutet: Die Ressource darf überhaupt nicht gespeichert werden — weder im Disk- noch im Memory-Cache. Für Login-Seiten, Dashboards und API-Responses ist immer no-store die richtige Wahl.
Fehlender Vary-Header für Content Negotiation
Ohne Vary: Accept-Encoding liefern Proxy-Caches möglicherweise eine gzip-komprimierte Antwort an einen Client, der kein gzip unterstützt (oder umgekehrt). Bei Seiten mit unterschiedlichen Inhalten pro Cookie (z.B. eingeloggt vs. ausgeloggt) ist Vary: Cookie notwendig, damit der Cache die Varianten unterscheidet.
Compliance-Relevanz
Sicherheitsrelevantes Caching ist in mehreren Regelwerken verankert. Ohne korrektes no-store auf sensiblen Seiten riskieren Sie, dass personenbezogene Daten im Browser-Cache verbleiben — ein direkter Verstoß gegen Datenschutzprinzipien.
no-store widerspricht dem Grundsatz der Datenminimierung. no-store können Kartendaten lokal gespeichert werden. Wie steht Ihre Domain bei Cache-Control?
Prüfen Sie es jetzt — kostenlos, ohne Registrierung, mit 166 Prüfpunkte.