Plik .htaccess to jedno z najważniejszych narzędzi konfiguracyjnych na serwerach Apache, szczególnie przy hostingu współdzielonym.

W praktyce to zwykły plik tekstowy (nazwa od „Hypertext Access”), który pozwala zarządzać funkcjonalnością, bezpieczeństwem i wydajnością witryny bez edycji globalnej konfiguracji serwera. Dzięki .htaccess wdrożysz przekierowania, logikę rewrite, zabezpieczenia hasłem, kompresję oraz cache – bez dostępu do plików głównych Apache.

Najczęstsze i najpraktyczniejsze zastosowania pliku .htaccess obejmują:

  • przekierowania adresów i kanonizację domeny,
  • wdrażanie przyjaznych URL-i (rewrite),
  • ochronę katalogów i plików (np. wp-config.php),
  • blokowanie botów, IP oraz hotlinkowania,
  • kompresję GZIP i nagłówki cache,
  • wymuszanie HTTPS i dodatkowe reguły bezpieczeństwa.

Niniejszy przewodnik wyjaśnia fundamenty oraz praktyczne przykłady użycia .htaccess – od podstaw po rozwiązania produkcyjne.

Fundamenty i definicja pliku .htaccess

Czym dokładnie jest plik .htaccess

Plik .htaccess to lokalny plik konfiguracyjny Apache HTTP Server, przetwarzany przy każdym żądaniu dotyczącym katalogu, w którym się znajduje (oraz jego podkatalogów).

To zwykły plik tekstowy ze zrozumiałymi dla Apache dyrektywami – każda w osobnej linii. Komentarze poprzedza się znakiem #. Pozwala to precyzyjnie sterować zachowaniem serwera bez edycji konfiguracji globalnej.

W systemach Unix/Linux nazwa rozpoczynająca się kropką oznacza plik ukryty. Warto uniemożliwić jego publiczne wyświetlanie, ponieważ może zdradzać szczegóły zabezpieczeń. .htaccess działa głównie na Apache, ale jest obsługiwany również m.in. przez LiteSpeed (z drobnymi różnicami w implementacji).

Historia i znaczenie w ekosystemie Apache

.htaccess powstał, aby umożliwić elastyczne modyfikacje konfiguracji w środowiskach z wieloma witrynami na jednym serwerze, gdzie użytkownicy nie mają dostępu do plików globalnych.

Do dziś jest powszechnie używany – prosty, skuteczny i dostępny dla milionów stron. Dokumentacja Apache zaleca jednak, by przy dostępie do konfiguracji głównej wdrażać reguły właśnie tam (lepsza wydajność). Dla hostingu współdzielonego .htaccess pozostaje podstawowym narzędziem.

Lokalizacja, struktura i zasady działania pliku .htaccess

Gdzie się znajduje i jak działa

Najczęściej umieszcza się go w katalogu głównym witryny (np. public_html). Reguły obowiązują w tym katalogu i we wszystkich podkatalogach – możesz zatem tworzyć ogólne zasady wyżej i nadpisywać je lokalnie niżej.

Hierarchia ma znaczenie: reguły z .htaccess w podkatalogu mają pierwszeństwo w tym podkatalogu. To umożliwia granularną kontrolę, np. blokadę wykonywania PHP tylko w /uploads/.

Apache musi pozwalać na działanie .htaccess. Odpowiada za to dyrektywa AllowOverride w konfiguracji głównej. Jeśli ustawisz AllowOverride None – .htaccess będzie ignorowany. Często stosuje się AllowOverride FileInfo lub AllowOverride All, zależnie od potrzeb.

Składnia i edycja bez pułapek

Edytuj .htaccess w czystym trybie tekstowym, bez BOM. Zwróć uwagę na wielkość liter w nazwie – .htaccess to co innego niż .HTACCESS. Na macOS pliki z kropką są domyślnie ukryte – utwórz plik i nazwij go poprawnie po stronie serwera (np. przez FTP).

Używaj komentarzy – pomagają dokumentować reguły i szybciej diagnozować problemy.

Tworzenie i edycja pliku .htaccess

Proces tworzenia pliku .htaccess

Otwórz edytor tekstu (np. Notepad++, Sublime Text), wpisz minimalny zestaw dyrektyw i testuj etapami. Po każdej zmianie sprawdzaj działanie witryny.

Przykładowy .htaccess dla WordPress (pretty permalinks) wygląda tak:

# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress

Zapisz plik dokładnie jako .htaccess i prześlij na serwer (FTP/menedżer plików w panelu hostingu).

Przed wprowadzeniem jakichkolwiek zmian wykonaj pełną kopię zapasową .htaccess i witryny. Błąd składni może spowodować 500 Internal Server Error.

Edycja i modyfikacja istniejącego pliku

Pobierz plik, zrób kopię, wprowadź zmiany, a następnie prześlij z powrotem. Dokumentuj modyfikacje w komentarzach i testuj je pojedynczo. W razie wątpliwości wyczyść cache przeglądarki i ewentualny cache serwera.

Aplikacje bezpieczeństwa i kontroli dostępu

Zabezpieczenie pliku .htaccess i plików krytycznych

Aby zablokować publiczny dostęp do .htaccess, dodaj do pliku regułę (składnia Apache 2.2):

<Files ".htaccess">
order allow,deny
deny from all
</Files>

Nowa składnia dla Apache 2.4+ (zalecana):

<Files ".htaccess">
Require all denied
</Files>

Aby chronić wp-config.php w WordPressie (2.2):

<Files "wp-config.php">
order allow,deny
deny from all
</Files>

Wersja dla Apache 2.4+:

<Files "wp-config.php">
Require all denied
</Files>

Blokowanie dostępu na podstawie adresów IP

Aby zablokować konkretny adres IP (Apache 2.2):

order allow,deny
deny from 203.0.113.10
allow from all

Odpowiednik dla Apache 2.4+:

Require all granted
Require not ip 203.0.113.10

Aby zezwolić tylko wybranym adresom IP (2.2):

order deny,allow
deny from all
allow from 198.51.100.5
allow from 203.0.113.10

Wersja dla Apache 2.4+:

Require ip 198.51.100.5 203.0.113.10

Ochrona katalogów hasłem

Najpierw utwórz plik .htpasswd poza katalogiem publicznym. Przykładowa zawartość wygląda tak:

uzytkownik:zaszyfrowane_haslo
inny_uzytkownik:inne_zaszyfrowane_haslo

Następnie w .htaccess wskaż lokalizację .htpasswd. Aby chronić konkretny plik:

<Files "nazwa_pliku.html">
AuthType Basic
AuthName "Ograniczony dostęp"
AuthUserFile /sciezka/do/.htpasswd
Require valid-user
</Files>

Aby chronić cały katalog:

AuthType Basic
AuthName "Ograniczony dostęp"
AuthUserFile /sciezka/do/.htpasswd
Require valid-user

Blokowanie botów i hotlinkowania

Aby zablokować określonego bota po nagłówku User-Agent:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^.*BadBot.* [NC]
RewriteRule .* - [F,L]
</IfModule>

Aby zapobiec hotlinkowaniu obrazów z innych domen:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?twoja-domena\.pl [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]
</IfModule>

Optymalizacja wydajności i cachowanie

Włączenie kompresji GZIP

Kompresja GZIP potrafi zmniejszyć rozmiar transferu nawet o 70% i dać natychmiastowy efekt.

Włącz GZIP dla typowych zasobów tekstowych:

<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
</IfModule>

Obrazy (JPEG/PNG/WebP) są już skompresowane – nie kompresuj ich ponownie. Moduł doda też nagłówek Vary: Accept-Encoding.

Implementacja cachowania w przeglądarce

Ustaw daty wygaśnięcia nagłówkami Expires oraz zasady Cache-Control – dla zgodności ze starszymi i nowszymi przeglądarkami.

Przykład nagłówków Expires dla różnych typów zasobów:

<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>

Przykład nagłówka Cache-Control z długą ważnością statycznych plików:

<IfModule mod_headers.c>
<FilesMatch "\.(js|css|png|jpg|jpeg|gif|webp|svg)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>

Stosowanie obu rodzajów nagłówków maksymalizuje skuteczność cache i kompatybilność.

Przekierowania i przepisywanie adresów URL

Fundamentalne przekierowania HTTP

Najpopularniejsze kody to 301 (trwałe) i 302 (tymczasowe). 301 przenosi wartość SEO na nowy adres, 302 – nie.

Porównanie najważniejszych cech przekierowań 301 i 302:

Typ Znaczenie Przeznaczenie Wpływ SEO
301 Stałe przeniesienie Zmiana struktury, migracje, kanonizacja Przekazuje większość autorytetu na nowy URL
302 Tymczasowe przeniesienie Testy A/B, sezonowe kampanie Nie przenosi w pełni autorytetu

Najprostszy przykład 301:

Redirect 301 /stara-strona.html https://przyklad.com/nowa-strona.html

Dla bardziej złożonych scenariuszy użyj mod_rewrite i RewriteRule.

Przekierowania domeny i wersji z/bez www

Aby wymusić wersję bez www dla konkretnej domeny:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.domena\.pl$ [NC]
RewriteRule ^(.*)$ https://domena.pl/$1 [L,R=301]

Aby wymusić wersję z www dla konkretnej domeny:

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.domena\.pl$ [NC]
RewriteRule ^(.*)$ https://www.domena.pl/$1 [L,R=301]

Wymuszenie HTTPS i szyfrowanego połączenia

HTTPS jest standardem bezpieczeństwa i rankingowym czynnikiem SEO. Przekierowanie całego ruchu na HTTPS:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Niestandardowe strony błędów i zarządzanie błędami

Definiowanie niestandardowych stron błędów

Aby wyświetlić własną stronę dla błędu 404:

ErrorDocument 404 /error404.html

Przykładowe definicje dla kilku popularnych kodów:

ErrorDocument 400 /errors/400.html
ErrorDocument 401 /errors/401.html
ErrorDocument 403 /errors/403.html
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html

Możesz wskazać również pełny adres URL (np. dla 403):

ErrorDocument 403 https://inna-strona.com/

Specyficzne zastosowania w WordPressie

Standardowa konfiguracja WordPressa

Pretty Permalinks wymagają aktywnego mod_rewrite. Oto standardowa konfiguracja generowana przez WordPress:

# 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

Dodatkowe bezpieczeństwo dla WordPressa

Zabezpieczenie wp-config.php (Apache 2.4+):

<Files "wp-config.php">
Require all denied
</Files>

Blokowanie wykonywania PHP w katalogu /wp-content/uploads/ – uwaga: w .htaccess nie używamy <Directory>. Wgraj poniższy plik .htaccess bezpośrednio do katalogu uploads:

<FilesMatch "\.php$">
Require all denied
</FilesMatch>

Wyłączenie XML-RPC (częsty cel ataków brute force):

<Files "xmlrpc.php">
Require all denied
</Files>

Blokada skanowania autorów po parametrze ?author=:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} ^author=([0-9]+) [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
</IfModule>

Wymuszenie SSL dla panelu administratora:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^wp-admin(.*)$ https://example.com/wp-admin$1 [R=301,L]

Naprawianie problemów z plikiem .htaccess w WordPressie

Jeśli pojawia się 500 lub 404 dla permalinków, tymczasowo zmień nazwę pliku na .htaccess-old i sprawdź, czy problem ustępuje. Przywróć domyślną sekcję WordPress lub w panelu przejdź do Ustawienia > Bezpośrednie odnośniki i kliknij „Zapisz zmiany”, aby zregenerować plik.

Najlepsze praktyki i wytyczne bezpieczeństwa

Ostrożność i planowanie

W pracy z .htaccess stosuj trzy kluczowe zasady:

  • Kopie zapasowe – zawsze rób backup pliku i bazy danych przed zmianami;
  • Testowanie etapami – dodawaj reguły pojedynczo i natychmiast je sprawdzaj;
  • Dokumentacja zmian – opisuj i datuj reguły w komentarzach dla przyszłych prac.

Nawet drobna literówka może „położyć” stronę – ostrożność to podstawa.

Optymalizacja wydajności

.htaccess jest wygodny, ale każda reguła to dodatkowy koszt parsowania przy każdym żądaniu. Jeśli masz dostęp do konfiguracji głównej, przenoś reguły poza .htaccess. Na hostingu współdzielonym trzymaj plik możliwie krótki i aktualny.

Uwzględnianie uprawnień plików

Zalecane uprawnienia dla WordPressa wyglądają następująco:

  • 755 – katalogi (przechodzenie i odczyt, bez zapisu przez innych);
  • 644 – pliki (odczyt dla wszystkich, zapis tylko dla właściciela);
  • 600 – plik wp-config.php (maksymalne ograniczenie dostępu);
  • 644 – plik .htaccess (edytowalny dla właściciela, czytelny dla serwera).

Poniższe polecenia (uruchamiane przez SSH) pomogą ustawić właściwe uprawnienia:

find /ścieżka/do/wordpress -type d -exec chmod 755 {} \;
find /ścieżka/do/wordpress -type f -exec chmod 644 {} \;
chmod 600 /ścieżka/do/wordpress/wp-config.php
chmod 644 /ścieżka/do/wordpress/.htaccess

Zaawansowane techniki i regex

Wprowadzenie do wyrażeń regularnych w .htaccess

mod_rewrite obsługuje wyrażenia regularne, dzięki czemu możesz precyzyjnie mapować i transformować adresy URL. Oto najważniejsze symbole:

  • ^ – początek ciągu,
  • $ – koniec ciągu,
  • . – dowolny pojedynczy znak,
  • * – zero lub więcej poprzedniego znaku,
  • + – jeden lub więcej poprzedniego znaku,
  • ? – zero lub jeden poprzedni znak,
  • [abc] – dowolny z znaków a, b lub c,
  • (xyz) – grupa, którą można przywołać później,
  • \. – literalna kropka (ucieczka przed kropką).

Przykład zamiany /post-123 na /index.php?p=123:

RewriteRule ^post-([0-9]+)$ /index.php?p=$1 [L]

Warunki rewrite i logika przetwarzania

RewriteCond poprzedza RewriteRule i warunkuje jej wykonanie. Domyślnie warunki łączą się logicznym AND. Przykład wymuszenia HTTPS dla konkretnego hosta:

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Najczęściej używane zmienne w RewriteCond to:

  • %{HTTP_HOST} – nazwa domeny,
  • %{REQUEST_URI} – żądana ścieżka,
  • %{HTTPS} – status HTTPS,
  • %{REQUEST_METHOD} – metoda HTTP (GET/POST itd.),
  • %{QUERY_STRING} – parametry zapytania,
  • %{HTTP_USER_AGENT} – identyfikator przeglądarki/bota.

Dzięki warunkom unikniesz pętli przekierowań i niepożądanych efektów ubocznych.