.htaccess to plik konfiguracyjny serwera Apache, który steruje zachowaniem strony. Przekierowania, bezpieczeństwo, cache, blokowanie IP, ochrona plików, permalinki WordPressa, dziesiątki innych ustawień. Leży w katalogu głównym strony (obok wp-config.php) i Apache czyta go przy każdym żądaniu HTTP. Jedna literówka i masz błąd 500 na całej stronie. Backup przed edycją to nie sugestia, tylko zasada.
Spis treści
ToggleCzym jest .htaccess i jak działa
.htaccess (Hypertext Access) to plik tekstowy, który Apache czyta przy każdym żądaniu. Zawiera dyrektywy: instrukcje, jak obsłużyć żądanie. „Przekieruj ten URL na inny”, „zablokuj to IP”, „włącz cache na 30 dni”, „wymuś HTTPS”. Nazwa zaczyna się od kropki, więc w Linuxie i macOS jest to plik ukryty. W FileZilli włączasz „Wymuś wyświetlanie ukrytych plików” (Serwer, Force showing hidden files), żeby go zobaczyć.
.htaccess działa na Apache i LiteSpeedzie, nie na Nginxie. Hosting z Nginxem (bez Apache jako frontend) ignoruje .htaccess. Sprawdzisz to przez nagłówek odpowiedzi: curl -I twojadomena.pl | grep Server.
Domyślny .htaccess WordPressa
WordPress generuje .htaccess sam (Ustawienia, Bezpośrednie odnośniki, Zapisz). Zawartość:
# 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
Reguły robią jedno: przepisują URL-e. Każde żądanie, które nie wskazuje na fizyczny plik ani folder, trafia do index.php (czyli WordPressa). Dzięki temu permalinki (/artykul/tytul/) działają zamiast brzydkich ?p=123.
Ważna zasada: nie edytuj bloku między # BEGIN WordPress i # END WordPress. WordPress nadpisuje go przy każdym zapisaniu permalinków. Własne reguły dorzucasz przed # BEGIN WordPress albo po # END WordPress.
Reguły pod SEO
Wymuszenie HTTPS.
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Każde żądanie HTTP dostaje 301 na HTTPS. Wymagane pod SEO (HTTPS to ranking factor) i bezpieczeństwo. Wstawiasz przed blokiem WordPressa.
Wymuszenie www albo bez www.
# Z www (twojadomena.pl → www.twojadomena.pl)
RewriteCond %{HTTP_HOST} ^twojadomena\.pl [NC]
RewriteRule ^(.*)$ https://www.twojadomena.pl/$1 [L,R=301]
# Albo bez www (www.twojadomena.pl → twojadomena.pl)
RewriteCond %{HTTP_HOST} ^www\.twojadomena\.pl [NC]
RewriteRule ^(.*)$ https://twojadomena.pl/$1 [L,R=301]
Wybierasz jedną wersję i konsekwentnie się jej trzymasz. Dwie wersje to duplikat treści. Google traktuje twojadomena.pl i www.twojadomena.pl jako dwa osobne adresy.
Przekierowanie 301.
# Pojedynczy URL
Redirect 301 /stary-artykul https://twojadomena.pl/nowy-artykul
# Cała domena na nową
RewriteRule ^(.*)$ https://nowadomena.pl/$1 [L,R=301]
301 przenosi około 90% autorytetu SEO ze starego URL na nowy. Używasz przy zmianie URL-i (sluga), usuwaniu stron (redirect na najbliższą tematycznie), zmianie domeny. Nie używaj 302 (tymczasowe) dla trwałych zmian, Google nie przeniesie autorytetu.
Reguły pod wydajność
Browser cache (Expires headers).
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-font-woff2 "access plus 1 year"
</IfModule>
Mówisz przeglądarce, żeby cache’owała obrazki rok, a CSS i JS miesiąc. Drugi load strony jest dramatycznie szybszy, bo zasoby idą z lokalnego cache. Poprawia LCP w Core Web Vitals.
Kompresja Gzip albo Deflate.
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE application/xml text/xml
AddOutputFilterByType DEFLATE image/svg+xml
</IfModule>
Kompresuje pliki tekstowe (HTML, CSS, JS, JSON, XML, SVG) przed wysłaniem do przeglądarki. Transfer schodzi o 60-80%. Hosting z LiteSpeedem? Włączasz Brotli w panelu, lepsza kompresja niż Gzip, ale konfigurujesz to w panelu hostingu, nie w .htaccess.
Reguły pod bezpieczeństwo
Ochrona wp-config.php.
<Files wp-config.php>
Order Allow,Deny
Deny from all
</Files>
wp-config.php trzyma hasło do bazy. Z zewnątrz nikt nie powinien go widzieć. Reguła blokuje dostęp HTTP, ale nie wpływa na PHP, więc WordPress nadal czyta plik lokalnie.
Ochrona samego .htaccess.
<Files .htaccess>
Order Allow,Deny
Deny from all
</Files>
Blokowanie xmlrpc.php.
<Files xmlrpc.php>
Order Allow,Deny
Deny from all
</Files>
xmlrpc.php to stary interfejs API WordPressa i jeden z głównych wektorów ataków brute force i DDoS amplification. Jeśli nie używasz Jetpacka, aplikacji mobilnej WP albo pingbacków: blokujesz. REST API zastępuje xmlrpc w nowoczesnym WordPressie.
Blokowanie IP.
# Konkretne IP
Deny from 123.456.789.0
# Zakres
Deny from 123.456.
# Pozwól tylko z jednego IP (np. wp-login)
<Files wp-login.php>
Order Deny,Allow
Deny from all
Allow from 89.64.12.34
</Files>
Blokowanie hotlinkingu.
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https://(www\.)?twojadomena\.pl [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,NC,L]
Hotlinking to scenariusz, w którym ktoś wstawia <img src="https://twojadomena.pl/zdjecie.jpg"> na swojej stronie i serwuje obrazek z twojego serwera. Ty płacisz za transfer, on ma darmowe zdjęcie. Reguła blokuje serwowanie obrazków dla domen innych niż twoja.
Diagnostyka, kiedy .htaccess wywala stronę
Błąd 500 po edycji .htaccess:
- FTP, zmień nazwę
.htaccessna.htaccess-broken. - Odświeżasz stronę. Działa? Problem jest w .htaccess.
- Porównujesz z backupem, znajdujesz regułę, która wywala.
- Awaryjnie: wp-admin, Ustawienia, Bezpośrednie odnośniki, Zapisz. WordPress wygeneruje czysty .htaccess.
- Dorzucasz reguły po jednej, testujesz po każdej zmianie.
Najczęstsze błędy: brakujący </IfModule>, literówka w nazwie dyrektywy, dyrektywa nieobsługiwana przez serwer (np. php_value na serwerze z PHP-FPM) albo podwójne RewriteEngine On. Sam zawsze trzymam ostatni działający .htaccess pod nazwą .htaccess-OK, żeby w razie czego wrócić w 5 sekund.
.htaccess a Nginx
Nginx nie obsługuje .htaccess. Konfiguracja siedzi w nginx.conf (albo /etc/nginx/sites-available/). Hosting na Nginxie po prostu ignoruje .htaccess. Odpowiedniki: przekierowania to return 301 w server block, cache to expires w location block, blokady to deny all w location. Na shared hostingu z Nginxem nie masz dostępu do nginx.conf, więc o konfigurację pytasz support.
LiteSpeed obsługuje .htaccess, jest kompatybilny z Apache. Reguły działają tak samo.
Najczęściej zadawane pytania
Gdzie leży plik .htaccess
W katalogu głównym WordPressa, obok wp-config.php, wp-content/, index.php. Nie widzisz? Włącz pokazywanie ukrytych plików w FTP (pliki zaczynające się od kropki są ukryte domyślnie). Nie istnieje? wp-admin, Ustawienia, Bezpośrednie odnośniki, Zapisz. WordPress go wygeneruje.
Czy mogę mieć kilka .htaccess
Tak. .htaccess w katalogu działa na ten katalog i podkatalogi. Możesz mieć osobny w /wp-admin/ (dodatkowe zabezpieczenia) i w /wp-content/uploads/ (blokowanie wykonywania PHP w uploadach). Główny .htaccess w root obowiązuje całą stronę.
Czy .htaccess spowalnia stronę
Minimalnie. Apache czyta plik przy każdym żądaniu (Nginx czyta swój config raz przy starcie). Przy prostym .htaccess (20-30 linii) wpływ jest niezauważalny. Przy 200+ regułach RewriteRule może dorzucić 1-5 ms na żądanie. Dla 99% stron: bez znaczenia.
Czy wtyczki WP modyfikują .htaccess
Tak. LiteSpeed Cache (cache rules), Wordfence (WAF), Yoast SEO (przekierowania), W3 Total Cache (cache headers), iThemes Security (zabezpieczenia). Wtyczki dorzucają swoje bloki między # BEGIN i # END NazwaWtyczki. Nie edytujesz tych bloków ręcznie, bo wtyczka je nadpisze.
Jak przetestować reguły przed wdrożeniem
Najlepiej na stagingu, klonujesz stronę i edytujesz .htaccess na kopii. Na produkcji: backup .htaccess, dodanie reguły, refresh strony. 500? Przywracasz backup przez FTP. Cały cykl trwa sekundy. Sam tak robię nawet przy „drobnych” zmianach, bo .htaccess potrafi być wredny przy najbanalniejszej literówce.






