Die .htaccess-Datei ist eines der leistungsstärksten Konfigurationswerkzeuge für Apache-Webserver. Sie ermöglicht die Steuerung von Weiterleitungen, HTTPS-Erzwingung, Sicherheitsheader, Caching und vieles mehr -- ohne die Hauptserverkonfiguration zu ändern. Dieses umfassende .htaccess-Redirect-Cheatsheet bietet produktionsreife Beispiele zum Kopieren und Einfügen für jedes gängige Szenario.
Grundlegende Weiterleitungen
Weiterleitungen sind die häufigste Verwendung von .htaccess-Dateien. Ob einzelne Seite, ganzes Verzeichnis oder Domain-Migration -- Apaches Redirect- und RewriteRule-Direktiven machen es einfach. Verwenden Sie immer 301-Weiterleitungen (permanent) für SEO, um den Linkwert auf die neue URL zu übertragen.
Einzelne URL weiterleiten
# Redirect a single URL (301 permanent)
Redirect 301 /old-page.html https://example.com/new-page.html
# Using RewriteRule for more control
RewriteEngine On
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
# Redirect with pattern matching (e.g., old product URLs)
RewriteRule ^products/([0-9]+)\.html$ /shop/item/$1 [R=301,L]Gesamtes Verzeichnis weiterleiten
# Redirect entire directory to new location
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1
# Using RewriteRule (preserves subdirectory structure)
RewriteEngine On
RewriteRule ^blog/(.*)$ /articles/$1 [R=301,L]
# Redirect directory but keep filenames
RewriteRule ^old-folder/(.+)$ /new-folder/$1 [R=301,L]Domain-zu-Domain-Weiterleitung
# Redirect entire old domain to new domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]
# Redirect specific domain alias to primary domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^olddomain\.net$ [NC,OR]
RewriteCond %{HTTP_HOST} ^olddomain\.org$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]HTTPS-Erzwingung
Die Erzwingung von HTTPS ist für Sicherheit und SEO unerlässlich. Google verwendet HTTPS als Ranking-Signal, und moderne Browser warnen vor unsicheren HTTP-Verbindungen. Diese Regeln verwenden mod_rewrite, um den gesamten HTTP-Traffic auf HTTPS umzuleiten.
HTTP zu HTTPS (ohne www)
# Force HTTPS (redirect HTTP to HTTPS, non-www)
RewriteEngine On
# Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
# Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]HTTP zu HTTPS (mit www)
# Force HTTPS with www prefix
RewriteEngine On
# Redirect non-www to www
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
# Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]Nicht-www mit HTTPS erzwingen
# Force non-www + HTTPS in a single pass
# Works on shared hosting and most Apache setups
RewriteEngine On
# Handle both www removal and HTTPS enforcement together
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# Alternative: Using environment variables (some hosts)
# RewriteCond %{ENV:HTTPS} !on
# RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]Behandlung des abschließenden Schrägstrichs
Inkonsistente abschließende Schrägstriche erzeugen Duplicate-Content-Probleme, die SEO schaden. Suchmaschinen behandeln /about und /about/ als verschiedene URLs. Wählen Sie einen Stil und erzwingen Sie ihn konsistent auf der gesamten Website.
Abschließenden Schrägstrich hinzufügen
# Add trailing slash to all URLs (except files with extensions)
RewriteEngine On
# Only apply to URLs without a file extension
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.[a-zA-Z0-9]{1,5}$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
# Simpler version (may cause issues with some file types)
# RewriteRule ^(.*[^/])$ $1/ [R=301,L]Abschließenden Schrägstrich entfernen
# Remove trailing slash from all URLs (except directories)
RewriteEngine On
# Do not remove trailing slash from actual directories
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
# Remove trailing slash except for root URL
# RewriteCond %{REQUEST_URI} !^/$
# RewriteRule ^(.*)/$ /$1 [R=301,L]Behandlung von Query-Strings
Die Weiterleitung von URLs mit Query-Strings erfordert besondere Aufmerksamkeit. Standardmäßig hängt Apache den originalen Query-String an das Weiterleitungsziel an. Verwenden Sie die QSA- und ?-Flags zum Beibehalten, Verwerfen oder Ändern von Parametern.
Weiterleitung mit Beibehaltung des Query-Strings
# Redirect preserving the original query string (default behavior)
# /search?q=test -> /find?q=test
RewriteEngine On
RewriteRule ^search$ /find [R=301,L]
# Redirect and APPEND additional query parameters (QSA flag)
# /page?id=5 -> /new-page?id=5&ref=old
RewriteRule ^page$ /new-page?ref=old [R=301,L,QSA]
# Match specific query string and redirect
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^product\.php$ /products/%1? [R=301,L]Weiterleitung mit Verwerfung des Query-Strings
# Redirect and DISCARD all query parameters
# /old-page?any=params -> /new-page (clean URL)
RewriteEngine On
RewriteRule ^old-page$ /new-page? [R=301,L]
# The trailing ? strips the query string
# Discard specific query parameters only
# /page?utm_source=x&id=5 -> /page?id=5 (strip tracking params)
RewriteCond %{QUERY_STRING} (^|&)utm_[^&]*
RewriteRule ^(.*)$ /$1? [R=301,L]Weiterleitung mit Änderung der Parameter
# Rewrite query parameter to path segment
# /index.php?page=about -> /about
RewriteEngine On
RewriteCond %{QUERY_STRING} ^page=(.+)$
RewriteRule ^index\.php$ /%1? [R=301,L]
# Rewrite path segment to query parameter
# /category/electronics -> /shop.php?cat=electronics
RewriteRule ^category/([a-zA-Z0-9-]+)$ /shop.php?cat=$1 [L]
# Rename a query parameter
# /search?q=test -> /search?query=test
RewriteCond %{QUERY_STRING} ^q=(.+)$
RewriteRule ^search$ /search?query=%1 [R=301,L]Benutzerdefinierte Fehlerseiten
Benutzerdefinierte Fehlerseiten verbessern die Benutzererfahrung durch hilfreiche Informationen. Die ErrorDocument-Direktive ermöglicht die Definition benutzerdefinierter Seiten für jeden HTTP-Statuscode.
# Custom error pages
# Place error page files in your document root
# 404 Not Found - page does not exist
ErrorDocument 404 /errors/404.html
# 403 Forbidden - access denied
ErrorDocument 403 /errors/403.html
# 500 Internal Server Error
ErrorDocument 500 /errors/500.html
# 401 Unauthorized - authentication required
ErrorDocument 401 /errors/401.html
# 503 Service Unavailable - maintenance mode
ErrorDocument 503 /errors/maintenance.html
# You can also use inline messages (not recommended for production)
# ErrorDocument 404 "Page not found. Please check the URL."
# Or redirect to an external URL
# ErrorDocument 404 https://example.com/not-found
# ── Maintenance mode (redirect all traffic to maintenance page) ──
# Uncomment during maintenance, recomment when done
# RewriteEngine On
# RewriteCond %{REMOTE_ADDR} !^123\.456\.789\.000$ # Allow your IP
# RewriteCond %{REQUEST_URI} !/errors/maintenance.html$ [NC]
# RewriteCond %{REQUEST_URI} !\.(css|js|png|jpg|gif|ico)$ [NC]
# RewriteRule ^(.*)$ /errors/maintenance.html [R=503,L]Sicherheitsheader über .htaccess
HTTP-Sicherheitsheader schützen Ihre Website vor gängigen Angriffen wie Clickjacking, XSS und Content-Injection. Das Hinzufügen über .htaccess erfordert aktiviertes mod_headers.
# Security headers via .htaccess
# Requires mod_headers to be enabled: a2enmod headers
<IfModule mod_headers.c>
# X-Frame-Options: Prevent clickjacking by blocking iframes
# Options: DENY | SAMEORIGIN | ALLOW-FROM uri
Header always set X-Frame-Options "SAMEORIGIN"
# X-Content-Type-Options: Prevent MIME-type sniffing
Header always set X-Content-Type-Options "nosniff"
# X-XSS-Protection: Enable browser XSS filter (legacy)
Header always set X-XSS-Protection "1; mode=block"
# Referrer-Policy: Control referrer information
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Content-Security-Policy: Control resource loading
# Customize the sources based on your site's needs
Header always set Content-Security-Policy "default-src 'self'; \
script-src 'self' 'unsafe-inline' https://cdn.example.com; \
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \
img-src 'self' data: https:; \
font-src 'self' https://fonts.gstatic.com; \
connect-src 'self' https://api.example.com; \
frame-ancestors 'self';"
# Strict-Transport-Security (HSTS): Force HTTPS for 2 years
# Only add this if your site fully supports HTTPS
Header always set Strict-Transport-Security \
"max-age=63072000; includeSubDomains; preload"
# Permissions-Policy: Disable unused browser features
Header always set Permissions-Policy \
"camera=(), microphone=(), geolocation=(), interest-cohort=()"
# Remove X-Powered-By header (hides PHP/server version)
Header unset X-Powered-By
Header always unset X-Powered-By
</IfModule>
# Hide Apache version in server headers
ServerSignature OffBrowser-Caching-Regeln
Browser-Caching verbessert die Ladezeiten für wiederkehrende Besucher erheblich. Das mod_expires-Modul setzt Cache-Control- und Expires-Header automatisch.
# Browser caching with mod_expires
# Enable the module: a2enmod expires
<IfModule mod_expires.c>
ExpiresActive On
# Default expiration: 1 month
ExpiresDefault "access plus 1 month"
# HTML files: short cache (content changes frequently)
ExpiresByType text/html "access plus 1 hour"
# CSS and JavaScript: long cache (use fingerprinted filenames)
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType text/javascript "access plus 1 year"
# Images: cache for 1 month
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/webp "access plus 1 month"
ExpiresByType image/avif "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 year"
# Fonts: cache for 1 year
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
ExpiresByType application/font-woff "access plus 1 year"
# JSON/XML data: short cache
ExpiresByType application/json "access plus 1 hour"
ExpiresByType application/xml "access plus 1 hour"
# PDF and documents
ExpiresByType application/pdf "access plus 1 month"
</IfModule>
# Alternative: Cache-Control headers with mod_headers
<IfModule mod_headers.c>
# Immutable cache for fingerprinted assets
<FilesMatch "\.(js|css)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
# Short cache for HTML
<FilesMatch "\.html$">
Header set Cache-Control "public, max-age=3600, must-revalidate"
</FilesMatch>
# No cache for dynamic content
<FilesMatch "\.(php|cgi)$">
Header set Cache-Control "no-store, no-cache, must-revalidate"
</FilesMatch>
</IfModule>Gzip-/Brotli-Komprimierung
Komprimierung reduziert die Größe übertragener Antworten um 60-90% und verbessert die Ladezeiten erheblich. Apache unterstützt Gzip (über mod_deflate) und Brotli (über mod_brotli, Apache 2.4.26+).
Gzip-Komprimierung (mod_deflate)
# Gzip compression using mod_deflate
# Enable the module: a2enmod deflate
<IfModule mod_deflate.c>
# Compress text-based content types
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE application/ld+json
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE font/woff
AddOutputFilterByType DEFLATE font/woff2
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
# Do not compress images (already compressed)
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|avif)$ no-gzip
# Handle browser quirks
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# Add Vary header for proper caching
Header append Vary Accept-Encoding
</IfModule>Brotli-Komprimierung (mod_brotli)
# Brotli compression using mod_brotli (Apache 2.4.26+)
# Enable the module: a2enmod brotli
<IfModule mod_brotli.c>
# Compress text-based content types with Brotli
AddOutputFilterByType BROTLI_COMPRESS text/plain
AddOutputFilterByType BROTLI_COMPRESS text/html
AddOutputFilterByType BROTLI_COMPRESS text/xml
AddOutputFilterByType BROTLI_COMPRESS text/css
AddOutputFilterByType BROTLI_COMPRESS text/javascript
AddOutputFilterByType BROTLI_COMPRESS application/xml
AddOutputFilterByType BROTLI_COMPRESS application/xhtml+xml
AddOutputFilterByType BROTLI_COMPRESS application/javascript
AddOutputFilterByType BROTLI_COMPRESS application/json
AddOutputFilterByType BROTLI_COMPRESS application/ld+json
AddOutputFilterByType BROTLI_COMPRESS font/opentype
AddOutputFilterByType BROTLI_COMPRESS font/ttf
AddOutputFilterByType BROTLI_COMPRESS font/woff
AddOutputFilterByType BROTLI_COMPRESS font/woff2
AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
# Brotli compression quality (0-11, default: 11)
# Lower = faster compression, larger files
# Higher = slower compression, smaller files
BrotliCompressionQuality 6
# Brotli window size (10-24, default: 22)
BrotliCompressionWindow 22
</IfModule>
# Fallback: Use Gzip if Brotli is not available
# Both modules can coexist; Apache serves Brotli to
# browsers that support it and Gzip to others.Häufige Fehler und Korrekturen
Das Debuggen von .htaccess-Problemen kann frustrierend sein. Hier sind die häufigsten Fehler und wie man sie vermeidet.
Endlose Weiterleitungsschleifen
Der häufigste Fehler ist eine Weiterleitungsschleife, bei der die umgeschriebene URL erneut auf dieselbe Regel passt. Verwenden Sie immer RewriteCond zur Zustandsprüfung und das [L]-Flag zum Stoppen der Verarbeitung.
# BAD: Creates an infinite loop
# (The rewritten URL "/new" matches "^(.*)$" again)
RewriteRule ^(.*)$ /new/$1 [R=301]
# GOOD: Use RewriteCond to prevent the loop
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/new/ [NC]
RewriteRule ^(.*)$ /new/$1 [R=301,L]
# GOOD: Another approach - check if already redirected
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ /new/$1 [R=301,L]Falsche RewriteBase
RewriteBase definiert den Basis-URL-Pfad für verzeichnisbezogene Umschreibungen. Wenn die .htaccess in einem Unterverzeichnis liegt, muss die RewriteBase diesem Pfad entsprechen.
# If .htaccess is in the document root:
RewriteEngine On
RewriteBase /
# If .htaccess is in /blog/ subdirectory:
RewriteEngine On
RewriteBase /blog/
# If .htaccess is in /app/public/ subdirectory:
RewriteEngine On
RewriteBase /app/public/
# Common mistake: Using RewriteBase /blog when file is at root
# This causes all rewritten URLs to be prefixed with /blogRegelreihenfolge ist wichtig
Apache verarbeitet .htaccess-Regeln von oben nach unten. Wenn eine allgemeine Regel vor einer spezifischen steht, wird sie zuerst übereinstimmen. Platzieren Sie spezifische Regeln immer vor allgemeinen und verwenden Sie das [L]-Flag.
# BAD: General rule before specific rule
RewriteEngine On
RewriteRule ^(.*)$ /index.php?page=$1 [L] # Catches everything!
RewriteRule ^about$ /about-us.html [R=301,L] # Never reached!
# GOOD: Specific rules first, general rules last
RewriteEngine On
RewriteRule ^about$ /about-us.html [R=301,L] # Specific: runs first
RewriteRule ^contact$ /contact-us.html [R=301,L] # Specific: runs second
RewriteCond %{REQUEST_FILENAME} !-f # Skip existing files
RewriteCond %{REQUEST_FILENAME} !-d # Skip existing dirs
RewriteRule ^(.*)$ /index.php?page=$1 [L] # General: fallback| Fehler | Korrektur |
|---|---|
| Fehlendes RewriteEngine On | Fügen Sie immer "RewriteEngine On" am Anfang des Regelblocks hinzu |
| Nicht-escaped Punkte in Mustern | Verwenden Sie \. statt . in Regex-Mustern |
| Vergessenes [L]-Flag | Fügen Sie [L] hinzu, um die Verarbeitung nach einem Treffer zu stoppen |
| Mischung von Redirect und RewriteRule | Bleiben Sie bei einer Methode; Mischen verursacht unvorhersehbares Verhalten |
| Test ohne Leeren des Browser-Caches | 301-Weiterleitungen werden zwischengespeichert; verwenden Sie 302 beim Testen |
| Falsche Dateiberechtigungen für .htaccess | Berechtigungen auf 644 setzen |
Häufig gestellte Fragen
Was ist .htaccess und wo platziere ich die Datei?
.htaccess ist eine verteilte Konfigurationsdatei für Apache-Webserver. Platzieren Sie sie im Stammverzeichnis Ihrer Website (üblicherweise public_html oder www). Sie beeinflusst das Verzeichnis und alle Unterverzeichnisse. Die Datei muss exakt ".htaccess" mit dem führenden Punkt heißen.
Was ist der Unterschied zwischen 301- und 302-Weiterleitungen?
Eine 301-Weiterleitung ist permanent und überträgt den Linkwert zur neuen URL. Eine 302-Weiterleitung ist temporär, Suchmaschinen behalten die Original-URL im Index. Verwenden Sie 301 für permanente Verschiebungen und 302 für temporäre Situationen. Browser cachen 301-Weiterleitungen aggressiv, verwenden Sie daher 302 beim Testen.
Warum funktionieren meine .htaccess-Regeln nicht?
Häufigste Ursachen: 1) mod_rewrite nicht aktiviert; 2) AllowOverride auf None gesetzt; 3) Falsche Dateiberechtigungen (sollte 644 sein); 4) Syntaxfehler (Apache-Fehlerlog prüfen); 5) Browser hat vorherige 301-Weiterleitung zwischengespeichert.
Funktioniert .htaccess mit Nginx?
Nein, .htaccess ist Apache-spezifisch. Nginx unterstützt keine .htaccess-Dateien. Bei Nginx müssen Sie äquivalente Direktiven direkt in die Server-Block-Konfiguration einfügen. Online-Tools können .htaccess-Regeln in Nginx-Syntax konvertieren.
Wie leite ich alte URLs nach einem Redesign weiter?
Erstellen Sie eine Zuordnung alter zu neuer URLs und fügen Sie für jede einen Redirect oder RewriteRule hinzu. Für musterbasierte Änderungen verwenden Sie Regex-Capture-Groups: RewriteRule ^blog/(.*)$ /articles/$1 [R=301,L]. Testen Sie immer mit curl -I.
Wie beeinflusst .htaccess die Website-Performance?
Apache liest .htaccess-Dateien bei jeder Anfrage, was einen geringen Performance-Overhead verursacht. Für hochfrequentierte Websites ist es besser, Regeln in die Apache-Hauptkonfiguration zu verschieben. Für die meisten Websites ist der Einfluss jedoch vernachlässigbar.
Dieses .htaccess-Cheatsheet deckt die wichtigsten Weiterleitungsmuster, Sicherheitskonfigurationen und Performance-Optimierungen ab. Testen Sie Änderungen immer gründlich mit curl, bevor Sie sie in die Produktion deployen, und bewahren Sie ein Backup Ihrer funktionierenden .htaccess-Datei auf.