Jak usunąć index.php z adresu URL w WordPress
Adresy w stylu example.com/index.php/kategoria/wpis to klasyczny objaw tego, że coś poszło nie tak z konfiguracją serwera albo permalinków. Nie jest to groźne dla samej instalacji, ale dla SEO, już tak. Zduplikowane treści, niedziałające linki kanoniczne, problemy z indeksowaniem. Spotykamy to regularnie przy migracjach na nowe serwery i po ręcznych instalacjach WordPressa na VPS-ach bez dopieszczonej konfiguracji Apache czy Nginx.
Skąd w ogóle bierze się index.php w URL
WordPress domyślnie obsługuje wszystkie żądania przez index.php. Kiedy serwer nie jest skonfigurowany pod kątem przepisywania adresów URL (URL rewriting), WordPress nie ma wyjścia, musi dosłownie pokazać ten plik w ścieżce.
Na Apache za przepisywanie odpowiada moduł mod_rewrite i odpowiednio skonstruowany plik .htaccess. Jeśli moduł jest wyłączony albo .htaccess nie istnieje lub jest pusty, dostajesz index.php w każdym adresie. Na Nginx temat wygląda inaczej, bo tam .htaccess w ogóle nie działa i całą logikę trzeba wpisać bezpośrednio w konfigurację bloku serwera.
Krok 1: Sprawdź ustawienia permalinków w panelu
Zanim zaczniesz grzebać w plikach serwera, zajrzyj do Ustawienia → Bezpośrednie odnośniki w panelu administracyjnym. Jeśli masz tam wybraną opcję „Zwykłe” (Plain), WordPress celowo generuje adresy bez żadnej struktury albo właśnie z index.php.
Zmień na dowolną inną strukturę, „Nazwa wpisu” jest najczęstszą i najsensowniejszą, i zapisz. WordPress przy zapisie próbuje automatycznie nadpisać plik .htaccess odpowiednimi regułami. Jeśli ma do niego uprawnienia zapisu, zazwyczaj to wystarczy.
Jeśli po tej operacji index.php nadal jest w URLach, problem leży głębiej.
Krok 2: Sprawdź plik .htaccess (Apache)
Prawidłowy .htaccess dla WordPressa wygląda tak:
apache
# 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
Plik powinien znajdować się w katalogu głównym instalacji WordPressa – tam, gdzie wp-config.php. Jeśli go nie ma, stwórz go ręcznie i wklej powyższą treść. Jeśli jest, ale wygląda inaczej, porównaj z tym wzorcem.
Uprawnienia pliku powinny wynosić 644. Ani 777, ani 444. Pierwsze to zaproszenie dla atakujących, drugie sprawi, że WordPress nie będzie mógł go modyfikować przy zmianach struktury permalinków.
Krok 3: Sprawdź, czy mod_rewrite jest włączony
Tu często leży sedno problemu, szczególnie na świeżo postawionych serwerach i tańszych hostingach współdzielonych. Moduł może być po prostu wyłączony.
Na serwerze z dostępem SSH sprawdzisz to przez:
bash
apache2ctl -M | grep rewrite
Jeśli nie widzisz rewrite_module – moduł jest wyłączony. Włączenie:
bash
sudo a2enmod rewrite
sudo systemctl restart apache2
Na hostingu współdzielonym bez dostępu SSH jedyną opcją jest kontakt z supportem albo sprawdzenie panelu (cPanel, DirectAdmin). Część hostingów ma mod_rewrite wyłączony w tańszych planach. To jeden z powodów, dla których hostingi za kilkanaście złotych miesięcznie potrafią generować więcej problemów niż oszczędności.
Dodatkowo – virtualhost Apache musi mieć ustawione AllowOverride All dla katalogu z WordPressem. Bez tego .htaccess jest ignorowany nawet przy włączonym mod_rewrite.
apache
<Directory /var/www/html>
AllowOverride All
</Directory>
Po każdej zmianie w konfiguracji Apache restart jest obowiązkowy.
Nginx – tu .htaccess nie istnieje
Jeśli serwer działa na Nginx, cały powyższy akapit o .htaccess jest nieistotny. Nginx nie przetwarza tego pliku w ogóle. Reguły przepisywania muszą trafić bezpośrednio do bloku server w konfiguracji serwera.
Standardowa konfiguracja bloku location dla WordPressa na Nginx:
nginx
location / {
try_files $uri $uri/ /index.php?$args;
}
Ta jedna linijka zastępuje całą logikę .htaccess. Bez niej Nginx nie wie, że ma kierować nieistniejące ścieżki do index.php WordPressa – i albo dostaniesz 404, albo właśnie te brzydkie adresy z index.php w środku.
Po zmianie konfiguracji:
bash
sudo nginx -t
sudo systemctl reload nginx
Najpierw test, potem reload. Błąd składni w konfiguracji Nginx potrafi wysypać cały serwer.
WordPress w podkatalogu
Jeśli WordPress nie siedzi w katalogu głównym, tylko np. w /blog albo /sklep, konfiguracja .htaccess wymaga dostosowania RewriteBase:
apache
RewriteBase /blog/
I analogicznie na Nginx – ścieżka w try_files musi uwzględniać podkatalog. Przy migracjach z katalogu głównego do podkatalogu albo odwrotnie to częsty powód, dla którego po przeniesieniu strony nagle połowa linków przestaje działać.
Zapis przez WP-CLI
Jeśli masz dostęp do WP-CLI, możesz wymusić odświeżenie struktury permalinków bez logowania do panelu:
bash
wp rewrite flush --hard
Flaga --hard przebudowuje reguły i nadpisuje .htaccess. Przydatne szczególnie po migracjach albo kiedy panel administracyjny z jakiegoś powodu nie reaguje poprawnie.
Co jeśli nic nie pomaga
Zdarza się, że problem jest głębiej. Mieliśmy przypadek, gdzie .htaccess wyglądał poprawnie, mod_rewrite był włączony, a index.php i tak siedział w URLach. Okazało się, że AllowOverride był ustawiony w konfiguracji domyślnego virtualhostu, ale witryna działała na osobnym vhoście, gdzie tej dyrektywy nie było. Apache stosował konfigurację domyślną zamiast tej z katalogu witryny.
Inna sytuacja: WordPressowe multisite z niestandardową konfiguracją podkatalogów, gdzie reguły .htaccess dla sieci nadpisywały te z instalacji głównej. Tutaj debugging bez dostępu do logów serwera jest praktycznie niemożliwy.
Logi Apache i Nginx to pierwsze miejsce, gdzie warto zajrzeć, zanim zaczniesz losowo edytować pliki konfiguracyjne.
Praktyczna checklista
Większość tych problemów rozwiązuje się w kwadrans. Ale tylko jeśli masz dostęp do serwera i wiesz, gdzie szukać.
