Backup-Tools neben PHP-Frameworks — .htaccess-Konflikte lösen
Du installierst MySQLDumper oder ein anderes Backup-Tool in einem Unterverzeichnis deiner Website — und bekommst nur eine 404-Seite oder wirst auf die Startseite umgeleitet. Der Grund: Dein PHP-Framework (CodeIgniter, Laravel, WordPress, Symfony) fängt alle Anfragen über URL-Rewriting ab und leitet sie an seinen eigenen Router weiter. Das Backup-Tool wird nie erreicht.
Das Grundproblem: URL-Rewriting
Moderne PHP-Frameworks nutzen mod_rewrite in der .htaccess, um alle Anfragen an eine zentrale index.php zu leiten. Das sieht typischerweise so aus:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Die Bedingungen !-f (keine Datei) und !-d (kein Verzeichnis) sollten eigentlich dafür sorgen, dass existierende Verzeichnisse durchgelassen werden. In der Praxis greift das aber oft nicht — weil die Framework-.htaccess weitere Regeln enthält, weil das Verzeichnis zwar existiert aber die Datei darin nicht direkt aufgerufen wird, oder weil verschachtelte Rewrite-Regeln sich gegenseitig überschreiben.
Die universelle Lösung
Das Muster ist bei allen Frameworks gleich: Du fügst eine RewriteCond hinzu, die dein Backup-Verzeichnis explizit vom Rewriting ausschließt. Die Regel muss vor der eigentlichen RewriteRule stehen.
# Backup-Verzeichnis vom Rewriting ausschließen
RewriteCond %{REQUEST_URI} !^/mysqldumper(/|$)
Das (/|$) am Ende matched sowohl /mysqldumper/ als auch /mysqldumper ohne Trailing Slash.
CodeIgniter
CodeIgniter hat eine der aggressivsten Rewrite-Konfigurationen. Die Standard-.htaccess im Root-Verzeichnis:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
Lösung: RewriteCond-Ausnahme hinzufügen
RewriteEngine On
# Backup-Tool vom Rewriting ausschließen
RewriteCond %{REQUEST_URI} !^/mysqldumper(/|$)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
Achtung bei CodeIgniter 4: CI4 hat die .htaccess im public/-Verzeichnis statt im Root. Die Anpassung muss dort erfolgen:
# public/.htaccess (CodeIgniter 4)
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/mysqldumper(/|$)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
Das Backup-Tool liegt dann unter /public/mysqldumper/ auf dem Dateisystem, erreichbar unter https://deinedomain.de/mysqldumper/.
Laravel
Laravel routet alles durch public/index.php. Die relevante .htaccess liegt in public/:
# public/.htaccess (Laravel Standard)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
Und in public/.htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Lösung: Ausnahme in public/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
# Backup-Tool ausschließen
RewriteRule ^mysqldumper(/|$) - [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Hier nutzen wir eine andere Technik: RewriteRule ^mysqldumper - [L] bedeutet „wenn die URL mit mysqldumper beginnt, tue nichts (-) und stoppe die Regelverarbeitung ([L])“. Das ist bei Laravel oft zuverlässiger als eine RewriteCond.
Das Backup-Tool installierst du in public/mysqldumper/.
WordPress
WordPress hat seine Rewrite-Regeln im Root-Verzeichnis. Sie werden automatisch generiert und sehen so aus:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Lösung: Ausnahme VOR dem WordPress-Block
# Backup-Tool vom WordPress-Rewriting ausschließen
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^mysqldumper(/|$) - [L]
</IfModule>
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Wichtig: Setze die Ausnahme vor den # BEGIN WordPress-Kommentar. WordPress überschreibt alles zwischen # BEGIN WordPress und # END WordPress wenn du die Permalink-Einstellungen speicherst. Alles davor bleibt erhalten.
Symfony
Symfony nutzt je nach Version unterschiedliche Verzeichnisstrukturen:
- Symfony 3:
web/.htaccess - Symfony 4+:
public/.htaccess
Lösung für Symfony 4+ (public/.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
# Backup-Tool ausschließen
RewriteRule ^mysqldumper(/|$) - [L]
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* %1/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Das Backup-Tool kommt in public/mysqldumper/.
Das allgemeine Muster
Egal welches Framework — der Ansatz ist immer einer von zwei Wegen:
Variante A: RewriteRule mit Stop-Flag
# VOR den Framework-Regeln einfügen:
RewriteRule ^mysqldumper(/|$) - [L]
Bedeutet: Wenn die URL mit mysqldumper beginnt, stoppe sofort. Kein Rewriting, keine Weiterleitung.
Variante B: RewriteCond als Ausnahme
# Direkt VOR der RewriteRule des Frameworks:
RewriteCond %{REQUEST_URI} !^/mysqldumper
Bedeutet: Wende die nächste RewriteRule nur an, wenn die URL nicht mit /mysqldumper beginnt.
Variante A ist in der Regel zuverlässiger, weil sie unabhängig von der Position funktioniert. Variante B ist fragiler — sie gilt nur für die unmittelbar folgende RewriteRule.
Mehrere Verzeichnisse ausschließen
Wenn du mehrere Tools oder Verzeichnisse vom Rewriting ausschließen willst:
# Variante A: Mehrere RewriteRules
RewriteRule ^mysqldumper(/|$) - [L]
RewriteRule ^phpmyadmin(/|$) - [L]
RewriteRule ^adminer(/|$) - [L]
# Variante B: Eine RewriteCond mit Alternation
RewriteCond %{REQUEST_URI} !^/(mysqldumper|phpmyadmin|adminer)(/|$)
Troubleshooting
Änderung zeigt keine Wirkung
- Browser-Cache leeren (oder Inkognito-Modus nutzen)
- Prüfen, ob
mod_rewriteaktiv ist:apache2ctl -M | grep rewrite - Prüfen, ob
AllowOverride Allin der vHost-Konfiguration gesetzt ist - Apache neustarten nach Änderungen an der vHost-Config:
systemctl restart apache2
Rewrite-Debugging aktivieren
# In der vHost-Konfiguration (nicht .htaccess!):
LogLevel alert rewrite:trace3
# Dann im Error Log:
tail -f /var/log/apache2/error.log
Das zeigt dir Schritt für Schritt, welche Rewrite-Regeln greifen und warum. Vergiss nicht, das Log-Level danach wieder zurückzusetzen — trace3 erzeugt sehr viel Output.
Eigene .htaccess im Backup-Verzeichnis
Zusätzlich zur Ausnahme im Framework kannst du eine eigene .htaccess im Backup-Verzeichnis anlegen, die das Rewriting explizit deaktiviert:
# mysqldumper/.htaccess
RewriteEngine Off
Das ist ein guter Fallback, falls die Ausnahme in der Haupt-.htaccess nicht greift.
Mehr zur Installation und Ersteinrichtung von MySQLDumper findest du im Installations-Guide.