“Słynna 5-minutowa instalacja” to slogan marketingowy, a nie standard profesjonalny. Domyślna instalacja WordPressa jest “gadatliwa”, nieoptymalna i często niebezpieczna.
Jako programiści nie tylko “instalujemy” WordPressa. Przygotowujemy go do pracy w konkretnym środowisku. Ten przewodnik obejmuje kluczowe stałe konfiguracyjne i techniki utwardzania, które powinny znaleźć się w bazowym zestawie każdego projektu klienckiego w 2026 roku.
Konfiguracja wp-config.php po instalacji WordPressa
To mózg twojej instalacji. Przestań zostawiać go na ustawieniach domyślnych.
Ustawienie WP_ENVIRONMENT_TYPE w wp-config.php
Od WordPressa 5.5, WP_ENVIRONMENT_TYPE jest standardem. Używaj go, aby zapobiec wyciekaniu błędów developerskich na produkcję.
// W wp-config.php
define( 'WP_ENVIRONMENT_TYPE', 'production' ); // 'local', 'development', 'staging', 'production'Następnie w swoim kodzie:
if ( wp_get_environment_type() === 'production' ) {
// Włącz Cache, Wyłącz Błędy
}Wyłączenie edytora plików i wymuszenie SSL w wp-config.php
Uchroń klientów (lub hakerów) przed zepsuciem strony poprzez panel administracyjny.
// Wyłącz Edytor Plików (Edytor Motywu/Wtyczek)
define( 'DISALLOW_FILE_EDIT', true );
// Zablokuj Instalację/Aktualizację Wtyczek (dobre dla niezmiennych wdrożeń)
define( 'DISALLOW_FILE_MODS', true );
// Wymuś SSL w Adminie
define( 'FORCE_SSL_ADMIN', true );Jak ograniczyć liczbę rewizji wpisów w WordPressie
Zabójca bazy danych. Czy naprawdę potrzebujesz 100 wersji strony “O Nas”?
define( 'WP_POST_REVISIONS', 10 ); // Zachowaj ostatnie 10
// LUB
define( 'WP_POST_REVISIONS', false ); // Wyłącz całkowicie (Niezalecane)Jak włączyć WP_DEBUG_LOG bez wyświetlania błędów
Nigdy nie wyświetlaj błędów na frontendzie. Loguj je.
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/tmp/wp-errors.log' ); // Przenieś log poza katalog publiczny!
define( 'WP_DEBUG_DISPLAY', false );
// Loguj zapytania SQL do debugowania wydajności (Wyłącz na produkcji!)
define( 'SAVEQUERIES', false );Jak wyłączyć emoji i XML-RPC w WordPressie
WordPress przychodzi z funkcjami, których 90% stron biznesowych nie potrzebuje: Emoji, oEmbedy i XML-RPC.
Nie instaluj wtyczki, by je wyłączyć. Stwórz Must-Use Plugin (wp-content/mu-plugins/lean-core.php).
<?php
/* Plugin Name: Lean Core */
// 1. Wyłącz Emoji (Oszczędza żądanie HTTP)
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
// 2. Wyłącz XML-RPC (Bezpieczeństwo)
add_filter( 'xmlrpc_enabled', '__return_false' );
// 3. Usuń Wersję WP (Security by Obscurity)
remove_action( 'wp_head', 'wp_generator' );
// 4. Wyłącz Kanały RSS (Jeśli budujesz stronę wizytówkę)
// function wppoland_disable_feed() {
// wp_die( 'Brak kanału, odwiedź naszą stronę główną!' );
// }
// add_action('do_feed', 'wppoland_disable_feed', 1);Wbrew nazwie filtr xmlrpc_enabled z punktu 2 wyłącza tylko metody XML-RPC wymagające uwierzytelnienia, na przykład publikowanie. Pingbacki i inne metody bez uwierzytelnienia dalej odpowiadają pod xmlrpc.php. Blokada całego pliku należy do serwera WWW i ma sens tylko wtedy, gdy nic z niego nie korzysta: Jetpack na przykład łączy się przez XML-RPC.
Zmiana kluczy salt w wp-config.php
Znasz klucze uwierzytelniania w wp-config.php.
define('AUTH_KEY', 'wpisz tutaj swoja unikalna fraze');
// ...Fakt: Ich zmiana natychmiast wylogowuje wszystkich użytkowników. To “Opcja Nuklearna”, jeśli strona zostanie zhakowana. Pro Tip: Zautomatyzuj ich rotację używając skryptu CLI lub Vaulta, jeśli zarządzasz stronami enterprise.
Co ustawić w wp-config.php przed startem strony
Zanim wystartujesz (Launch):
- Ustaw
WP_ENVIRONMENT_TYPEna production. - Ustaw
DISALLOW_FILE_EDITna true. - Ogranicz
WP_POST_REVISIONS. - Przenieś
WP_DEBUG_LOGdo prywatnego folderu. - Wyłącz Emoji/XML-RPC kodem.
Dobrze skonfigurowana instancja WordPressa jest cicha, bezpieczna i szybka.
Jakie permalinki ustawić w WordPressie
Optymalna struktura permalinków
W panelu otwórz Ustawienia, potem Bezpośrednie odnośniki, i wybierz opcję Nazwa wpisu.
Dlaczego:
- Krótsze, czytelniejsze URL-e
- Lepsze dla SEO (słowa kluczowe w URL)
- Łatwiejsze do zapamiętania i udostępniania
Świeża instalacja często ma już czytelne permalinki. Jeśli serwer obsługuje przepisywanie adresów, instalator ustawia /%year%/%monthnum%/%day%/%postname%/ (funkcja rdzenia wp_install_maybe_enable_pretty_permalinks()). Przełącz na Nazwę wpisu przed publikacją pierwszego wpisu: zmiana struktury na działającej stronie zmienia adresy wszystkich wpisów, a stare adresy wymagają wtedy przekierowań.
Struktura kategorii i tagów
- Utwórz podstawowe kategorie (3-7 głównych)
- Zdefiniuj hierarchię (kategorie nadrzędne i podrzędne)
- Ustaw domyślną kategorię (nie “Bez kategorii”)
- Zaplanuj strategię tagów (opcjonalnie, 5-10 tagów na wpis)
Ustawienia mediów WordPress i rozmiary obrazów
Rozmiary obrazów
W panelu otwórz Ustawienia, potem Media.
Zalecane ustawienia:
- Miniatura: 150x150px (zaznacz “Przytnij miniaturę”)
- Średni: 300x300px
- Duży: 1024x1024px
- Pełny rozmiar: Zawsze dostępny
Automatyczna optymalizacja obrazów
<?php
/* Plugin Name: Image Sizes */
add_action( 'init', function () {
remove_image_size( '1536x1536' ); // WordPress 5.3+
remove_image_size( '2048x2048' ); // WordPress 5.3+
} );Z wcześniejszej wersji tego fragmentu zniknęły dwie linie. wp_lazy_loading_enabled domyślnie zwraca już true (natywne loading="lazy" od WordPressa 5.5), a filtr wp_image_editors ustala tylko kolejność, w jakiej WordPress próbuje Imagick i GD, czyli kolejność domyślną. Żaden z nich nic nie optymalizuje przy wgrywaniu. Obrazy szersze lub wyższe niż 2560 px są już zmniejszane przy wgrywaniu przez filtr big_image_size_threshold.
Jak włączyć WebP przy wgrywaniu obrazów w WordPressie
add_filter( 'image_editor_output_format', function ( $formats ) {
$formats['image/jpeg'] = 'image/webp';
$formats['image/png'] = 'image/webp';
return $formats;
} );Poprzednia wersja tego fragmentu używała wp_upload_image_mime_transforms, filtra, którego nie ma w obecnym rdzeniu WordPressa. image_editor_output_format istnieje od WordPressa 5.8 i przypisuje typowi źródłowemu typ, w którym WordPress zapisuje generowane rozmiary; od wersji 6.7 jego wartość domyślna zamienia HEIC i HEIF na JPEG, a fragment zachowuje te wpisy. Imagick albo GD na serwerze musi obsługiwać WebP. Narzędzia > Kondycja witryny > Informacje > Obsługa mediów pokazuje, co jest obsługiwane.
Jak zabezpieczyć WordPressa po instalacji
Zmiana domyślnego prefiksu tabel
Podczas instalacji: Wpisz niestandardowy prefiks zamiast wp_ (np. x7k9_, mysite_, proj23_)
Po instalacji (zaawansowane):
// wp-config.php
$table_prefix = 'x7k9_';RENAME TABLE wp_posts TO x7k9_posts;
RENAME TABLE wp_options TO x7k9_options;
-- ... powtórz dla wszystkich tabel
UPDATE x7k9_options SET option_name = 'x7k9_user_roles' WHERE option_name = 'wp_user_roles';
UPDATE x7k9_usermeta SET meta_key = CONCAT('x7k9_', SUBSTRING(meta_key, 4)) WHERE meta_key LIKE 'wp\_%';WordPress nie ma stałej DB_PREFIX: prefiks siedzi w zmiennej $table_prefix. Samo przemianowanie tabel odcina administratorów, bo role i uprawnienia są zapisane pod kluczami z prefiksem w options (wp_user_roles) i usermeta (wp_capabilities, wp_user_level). Właśnie to naprawiają dwa polecenia UPDATE. Przewodnik Hardening WordPress traktuje własny prefiks jako zaciemnianie: może zablokować część zautomatyzowanych ataków SQL injection zakładających wp_, ale nie zastępuje poprawienia podatnego kodu.
Ochrona pliku wp-config.php
# .htaccess (katalog główny, na samym początku pliku)
<Files "wp-config.php">
Require all denied
</Files>Order allow,deny to składnia Apache 2.2, która na Apache 2.4 działa tylko przez moduł zgodności. Przewodnik Hardening WordPress podaje powyższą formę Require all denied i umieszcza ją na samym początku głównego .htaccess. Nginx ignoruje pliki .htaccess, więc na Nginx ta sama reguła trafia do bloku server.
Blokowanie dostępu do katalogów
# wp-content/uploads/.htaccess
Options -Indexes
# .htaccess (katalog główny, poza # BEGIN WordPress i # END WordPress)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>WordPress nadpisuje wszystko między znacznikami # BEGIN WordPress i # END WordPress przy każdym zapisie permalinków, więc ten blok idzie poza nie, do głównego .htaccess, a nie do wp-includes/: ścieżki w regułach są liczone od katalogu głównego strony. W multisite linia ^wp-includes/[^/]+\.php$ blokuje ms-files.php przy serwowaniu obrazów, a przewodnik Hardening WordPress zaleca tam jej usunięcie kosztem części ochrony.
Ograniczenie prób logowania
<?php
/* Plugin Name: Login Security */
function wppoland_login_key() {
return 'login_attempts_' . md5( $_SERVER['REMOTE_ADDR'] );
}
add_filter( 'authenticate', function ( $user ) {
if ( (int) get_transient( wppoland_login_key() ) >= 5 ) {
return new WP_Error( 'too_many_attempts', 'Zbyt wiele prób logowania. Spróbuj ponownie za godzinę.' );
}
return $user;
}, 30 );
add_action( 'wp_login_failed', function () {
$key = wppoland_login_key();
set_transient( $key, (int) get_transient( $key ) + 1, HOUR_IN_SECONDS );
} );
remove_action( 'wp_head', 'wp_generator' );
add_filter( 'the_generator', '__return_empty_string' );Wcześniejsza wersja liczyła nieudane próby w wp_login_failed i tam wywoływała wp_die(). Ten hook działa po sprawdzeniu hasła, więc poprawne hasło nadal logowało po pięciu porażkach. Filtr authenticate z priorytetem 30 działa po sprawdzeniu loginu i hasła przez rdzeń, a zwrócony tam WP_Error zatrzymuje logowanie. Za CDN albo reverse proxy REMOTE_ADDR zawiera adres proxy i wszyscy odwiedzający dzieliliby jeden licznik: w takim układzie ogranicz logowania na proxy albo przez fail2ban na serwerze.
Dwuskładnikowe uwierzytelnianie (2FA)
Rdzeń WordPressa nie ma drugiego składnika. Wtyczka Two Factor, opublikowana w katalogu WordPress.org z konta WordPress.org, dodaje aplikacje uwierzytelniające (TOTP), kody wysyłane e-mailem i kody zapasowe, a każdy użytkownik włącza ją we własnym profilu. Przewodnik Hardening WordPress zaleca uwierzytelnianie dwuetapowe jako dodatkową warstwę obok hasła. Poniższy fragment robi coś skromniejszego: odrzuca hasła krótsze niż 12 znaków przy zapisie profilu.
// Wymuś silne hasła
add_action('user_profile_update_errors', function($errors) {
$password = $_POST['pass1'];
if (!empty($password) && strlen($password) < 12) {
$errors->add('password_error', 'Hasło musi mieć co najmniej 12 znaków.');
}
});Jak przyspieszyć WordPressa po instalacji
Podstawowa optymalizacja bazy danych
// W wp-config.php
// Ogranicz rewizje postów
define('WP_POST_REVISIONS', 10);
// Automatyczne opróżnianie kosza po 7 dniach
define('EMPTY_TRASH_DAYS', 7);
// Wyłącz edytor plików (bezpieczeństwo + wydajność)
define('DISALLOW_FILE_EDIT', true);Czyszczenie bazy danych
wp transient delete --expired
wp post list --post_type=revision --format=count
wp db optimizeUsunięta wtyczka mu kasowała transienty, porównując option_value z bieżącym czasem, ale czas wygaśnięcia jest zapisany w osobnych wierszach _transient_timeout_, więc kasowała niewłaściwe wiersze. Rdzeń już to robi: wp-admin/admin.php planuje codzienne zdarzenie delete_expired_transients (pomijane, gdy transienty trzyma trwały cache obiektów), a codzienne zdarzenie wp_scheduled_auto_draft_delete usuwa automatyczne szkice starsze niż siedem dni. Przy ustawionym WP_POST_REVISIONS rewizje też nie potrzebują crona do kasowania. Powyższe polecenia WP-CLI uruchamiaj ręcznie, gdy baza wygląda na rozdętą.
Optymalizacja Heartbeat API
add_filter( 'heartbeat_settings', function ( $settings ) {
$settings['interval'] = 120; // domyślnie: 60
return $settings;
} );
add_action( 'init', function () {
if ( ! is_admin() ) {
wp_deregister_script( 'heartbeat' );
}
}, 1 );Domyślny interwał Heartbeat to 60 sekund (mainInterval w heartbeat.js), a nie 15, więc wcześniejsza wartość 60 niczego nie zmieniała. Heartbeat sam zwalnia do 120 sekund, gdy karta przeglądarki jest ukryta. W edytorze przenosi blokady wpisów, więc dłuższy interwał opóźnia ostrzeżenie, że ktoś inny edytuje ten sam wpis.
Usuwanie linków RSD, shortlink i REST API z wp_head
// W mu-plugin: wp-content/mu-plugins/disable-bloat.php
<?php
/* Plugin Name: Disable Bloat */
// Wyłącz emoji
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
// Wyłącz XML-RPC
add_filter('xmlrpc_enabled', '__return_false');
// Wyłącz RSD link
remove_action('wp_head', 'rsd_link');
// Wyłącz Windows Live Writer link
remove_action('wp_head', 'wlwmanifest_link');
// Wyłącz shortlink
remove_action('wp_head', 'wp_shortlink_wp_head');
// Wyłącz REST API link (jeśli nie używasz)
remove_action('wp_head', 'rest_output_link_wp_head');Podstawowe ustawienia SEO w WordPressie
Tytuł witryny, opis i widoczność dla wyszukiwarek
Ustawienia > Ogólne:
- Nazwa witryny: [Twoja marka]
- Opis: jedno krótkie zdanie albo puste pole
Ustawienia > Czytanie:
- Widoczność dla wyszukiwarek: pole "Proś wyszukiwarki o nieindeksowanie witryny" ma być ODZNACZONERdzeń nie wypisuje żadnego meta description, więc opis witryny nim nie jest. W obecnych instalacjach to pole startuje puste, a motywy mogą je pokazywać w nagłówku albo w tytule. Meta description dostarcza wtyczka SEO albo motyw. Pole widoczności dla wyszukiwarek jest w Czytaniu, a nie w Ogólnych, i dopóki jest zaznaczone, WordPress wyłącza też własną mapę witryny.
Struktura permalinków SEO-friendly
W panelu otwórz Ustawienia, potem Bezpośrednie odnośniki, i wybierz opcję Nazwa wpisu.
Mapa witryny (XML Sitemap)
add_filter( 'wp_sitemaps_post_types', function ( $post_types ) {
unset( $post_types['portfolio'] ); // usunięcie typu treści z mapy witryny
return $post_types;
} );Mapa witryny z rdzenia pod /wp-sitemap.xml jest domyślnie włączona od WordPressa 5.5, o ile strona jest widoczna dla wyszukiwarek. Obejmuje wszystkie publiczne typy treści, także własne, więc stara linia $post_types[] = 'portfolio' była zbędna, a do tego błędna: tablica zawiera obiekty WP_Post_Type z nazwą jako kluczem. Filtr przydaje się w drugą stronę, do wyjęcia typu z mapy witryny.
Podstawowa optymalizacja obrazów dla SEO
Wcześniejsza wersja tej sekcji wypełniała puste atrybuty ALT tytułem załącznika i tworzyła tytuły z nazw plików. Drugie robi już rdzeń: media_handle_upload() bierze tytuł załącznika z nazwy pliku. Pierwsze daje teksty ALT w rodzaju “IMG_2041”, które czytnik ekranu odczytuje na głos i które nic nie mówią o obrazie. Tekst ALT pisz dla każdego obrazu w bibliotece mediów, a przy obrazach czysto dekoracyjnych zostaw go pustym.
Jak robić kopie zapasowe WordPressa
Automatyczne kopie zapasowe bazy danych
# crontab -e (użytkownik strony, nie root)
15 3 * * * cd /var/www/example/public && wp db export /home/example/backups/db-$(date +\%F).sql --quiet && find /home/example/backups -name 'db-*.sql' -mtime +7 -deleteWcześniejsza wtyczka mu zapisywała zrzuty w wp-content/uploads/backups, publicznym katalogu, z którego każdy, kto zgadnie nazwę opartą na dacie, pobierze bazę danych. Przekazywała też hasło do bazy w linii poleceń mysqldump, gdzie inni użytkownicy serwera widzą je na liście procesów, i zależała od WP-Cron, który uruchamia się tylko przy odwiedzinach strony. Systemowy cron z wp db export zapisuje poza katalogiem publicznym i działa o czasie.
Konfiguracja zewnętrznych kopii
Zalecane rozwiązania:
- UpdraftPlus - darmowa wersja wystarczająca dla małych stron
- BlogVault - płatne, ale bardzo niezawodne
- WPvivid - dobra alternatywa darmowa
Konfiguracja:
- Kopia codzienna (baza danych)
- Kopia tygodniowa (pełna)
- Przechowywanie: minimum 30 dni
- Lokalizacja zewnętrzna: Google Drive, Dropbox, S3
Konfiguracja SMTP w WordPressie
SMTP zamiast mail()
// W wp-config.php lub mu-plugin
define('SMTP_USER', '[email protected]');
define('SMTP_PASS', 'your-password');
define('SMTP_HOST', 'smtp.gmail.com');
define('SMTP_PORT', '587');
define('SMTP_SECURE', 'tls');
define('SMTP_FROM', '[email protected]');
define('SMTP_NAME', 'Twoja Strona');
// W mu-plugin
add_action('phpmailer_init', function($phpmailer) {
$phpmailer->isSMTP();
$phpmailer->Host = SMTP_HOST;
$phpmailer->SMTPAuth = true;
$phpmailer->Username = SMTP_USER;
$phpmailer->Password = SMTP_PASS;
$phpmailer->SMTPSecure = SMTP_SECURE;
$phpmailer->Port = SMTP_PORT;
$phpmailer->From = SMTP_FROM;
$phpmailer->FromName = SMTP_NAME;
});Jak wysłać testowy e-mail z WordPressa
add_action( 'admin_init', function () {
if ( isset( $_GET['test_email'] ) && current_user_can( 'manage_options' ) ) {
$sent = wp_mail( get_option( 'admin_email' ), 'Test email', 'To jest wiadomość testowa wysłana z WordPressa.' );
wp_die( $sent ? 'OK' : 'wp_mail() returned false' );
}
} );admin_init uruchamia się także przy żądaniach do admin-ajax.php od niezalogowanych odwiedzających, więc bez sprawdzenia uprawnień każdy mógłby zmusić stronę do wysłania maila. W WP-CLI ten sam test to jedna linia: wp eval 'var_dump( wp_mail( get_option( "admin_email" ), "Test", "Test" ) );'.
Monitoring WordPressa i logowanie błędów
Logowanie błędów
// W wp-config.php
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', '/var/log/wp-errors.log'); // Poza katalogiem publicznym
define('WP_DEBUG_DISPLAY', false);
// Logowanie zapytań SQL (tylko w trybie debugowania)
// define('SAVEQUERIES', true);Monitoring uptime
Zalecane narzędzia:
- UptimeRobot
- Pingdom (płatne, ale bardziej zaawansowane)
- Better Uptime (nowoczesna alternatywa)
Rejestrowanie logowań i aktualizacji wpisów
// W mu-plugin: wp-content/mu-plugins/activity-log.php
<?php
/* Plugin Name: Activity Log */
add_action('wp_login', function($user_login, $user) {
error_log('User logged in: ' . $user_login . ' from IP: ' . $_SERVER['REMOTE_ADDR']);
}, 10, 2);
add_action('save_post', function($post_id, $post, $update) {
if ($update && $post->post_status === 'publish') {
error_log('Post updated: ' . $post->post_title . ' by user: ' . get_current_user_id());
}
}, 10, 3);Co sprawdzić przed uruchomieniem strony WordPress
Lista kontrolna przed uruchomieniem strony
- Wszystkie ustawienia SEO poprawne
- Mapa witryny wygenerowana
- Google Search Console skonfigurowane
- Google Analytics zainstalowane
- Polityka prywatności i regulamin dodane
- Formularze kontaktowe przetestowane
- Poczta e-mail działa
- SSL działa (HTTPS)
- Przekierowania między wersją www i bez www skonfigurowane
- Kopia zapasowa wykonana
- Wtyczki cache’ujące skonfigurowane (opcjonalnie)
- CDN skonfigurowane (opcjonalnie)
- Testy wydajności przeprowadzone (PageSpeed Insights)
- Testy responsywności mobilnej
- Testy w różnych przeglądarkach
- 404 strona skonfigurowana
- Favicon dodany
Sprawdzanie sum kontrolnych i dostępu do plików przez WP-CLI i curl
# Testy WP-CLI
wp core verify-checksums
wp plugin verify-checksums --all
wp db check
# Testy bezpieczeństwa
curl -I https://twoja-strona.pl/wp-admin/install.php # zwraca stronę "Już zainstalowano", chyba że serwer ją blokuje
curl -I https://twoja-strona.pl/wp-config.php # 403 z regułą <Files>; bez niej pusta stronaJakie ustawienia WordPressa zmienić po instalacji
Trzy ekrany w Ustawieniach mają wartości domyślne, które liczą się, zanim przyjdzie pierwszy odwiedzający. Dokumentacja ekranu Ogólne opisuje każde pole.
Ogólne. Strefę czasową wybierz jako miasto, a nie przesunięcie UTC. Miasto uwzględnia czas letni, stałe przesunięcie nie, i zaplanowane wpisy publikują się wtedy przez pół roku o godzinę obok. Język witryny ustawiany tutaj to język kokpitu. Nowy adres e-mail administracji nie działa od razu: WordPress wysyła link potwierdzający na nowy adres i do kliknięcia trzyma aktywny stary, więc podaj skrzynkę, którą ktoś czyta. Członkostwo (“Każdy może się zarejestrować”) zostaw wyłączone, chyba że strona potrzebuje otwartej rejestracji, a jeśli potrzebuje, zostaw Subskrybenta jako domyślną rolę nowych użytkowników.
Czytanie. Tu jest pole widoczności dla wyszukiwarek. Kopie stagingowe powinny mieć je zaznaczone, produkcja nie. Ustawienie siedzi w bazie danych, więc wędruje z każdą jej kopią: sprawdzaj je po każdym przeniesieniu ze stagingu na produkcję.
Dyskusja. Nowa instalacja ma domyślnie otwarte komentarze i pingbacki, wyłączone ręczne zatwierdzanie komentarzy i włączone “Autor komentarza musi mieć wcześniej zatwierdzony komentarz”. Na stronie firmowej bez komentarzy zamknij je tutaj przed publikacją. Ustawienie dotyczy nowych wpisów; istniejące zachowują własny stan.
Jak czytać Kondycję witryny po instalacji WordPressa
Narzędzia > Kondycja witryny uruchamia zestaw testów i dzieli wyniki na problemy krytyczne i zalecane usprawnienia (dokumentacja ekranu Site Health). Na nowej stronie przydają się testy, których dotykają ustawienia z tego artykułu:
- Debugowanie włączone. Przy włączonym
WP_DEBUG_LOGtest staje się krytyczny, gdy log błędów PHP leży w katalogu WordPressa, bo wtedy da się go pobrać. Dlatego ścieżka logu wyżej w artykule prowadzi poza katalog publiczny. - Widoczność dla wyszukiwarek. Zgłaszana, dopóki pole “Proś wyszukiwarki o nieindeksowanie” jest zaznaczone (test dodany w WordPressie 6.9).
- Otwarta rejestracja z uprzywilejowaną rolą domyślną. Zgłaszana, gdy każdy może się zarejestrować z rolą wyższą niż Subskrybent (od WordPressa 7.0).
- Aktualizacje w tle, automatyczne aktualizacje wtyczek i motywów, zaplanowane zdarzenia, żądanie loopback. Gdy te testy nie przechodzą, automatyczne aktualizacje i zadania WP-Cron nie działają.
- Stan HTTPS, trwały cache obiektów, cache stron. Testy hostingu. Oba testy cache to zalecenia, nie błędy.
Zakładka Informacje wymienia dane serwera (wersję i rozszerzenia PHP, wersję bazy danych, obsługę edytora obrazów, stałe takie jak WP_DEBUG_LOG i WP_ENVIRONMENT_TYPE) i ma przycisk kopiujący wszystko do schowka. Wklejenie tego do zgłoszenia oszczędza jedną rundę pytań z hostingiem.
Jak działają automatyczne aktualizacje w nowym WordPressie
Są trzy poziomy, ustawiane w różnych miejscach (Configuring automatic background updates):
- Wydania drobne rdzenia (bezpieczeństwo i poprawki) instalują się same od WordPressa 3.7.
- Wydania główne rdzenia. Na stronach zainstalowanych od WordPressa 5.6 opcja
auto_update_core_majorstartuje jako włączona. Strony zaktualizowane ze starszej wersji mają ją nieustawioną. StałaWP_AUTO_UPDATE_COREnadpisuje oba przypadki:truedla wszystkich wydań,'minor'tylko dla drobnych,falsewyłącza aktualizacje rdzenia w tle. - Wtyczki i motywy. Automatyczne aktualizacje są domyślnie wyłączone i włącza się je osobno dla każdej wtyczki lub motywu na ekranach Wtyczki i Motywy; funkcja weszła w WordPressie 5.5.
DISALLOW_FILE_MODS (punkt 5 listy) robi więcej niż ukrycie przycisków instalacji i aktualizacji. Rdzeń sprawdza wp_is_file_mod_allowed( 'automatic_updater' ) przed każdą aktualizacją w tle, więc ta stała zatrzymuje też automatyczne wydania bezpieczeństwa. To w porządku, gdy każda aktualizacja przychodzi przez wdrożenie. Bez takiego procesu strona zostaje na wersji, z którą ją wdrożono, aż ktoś wdroży ponownie.
Czy wyłączyć hasła aplikacji w WordPressie
Hasła aplikacji, dodane w WordPressie 5.6, pozwalają zewnętrznemu narzędziu uwierzytelnić się w REST API nazwą użytkownika i wygenerowanym hasłem zamiast hasła do konta (dokumentacja Application Passwords). Każdy użytkownik tworzy je i unieważnia we własnym profilu. Nowe hasło jest pokazywane raz, zapisywane jako hash i wyświetlane z datą i adresem IP ostatniego użycia. Rdzeń udostępnia tę funkcję tylko na stronach z HTTPS albo gdy WP_ENVIRONMENT_TYPE ma wartość local.
Zostaw ją włączoną, gdy z REST API rozmawia aplikacja mobilna, narzędzie do wdrożeń albo integracja. Na stronie bez żadnej z tych rzeczy jeden filtr wyłącza ją dla wszystkich użytkowników:
add_filter( 'wp_is_application_passwords_available', '__return_false' );Po podejrzeniu włamania unieważnij hasła aplikacji, a nie tylko zmień klucze salt. Nowe klucze kończą wszystkie sesje logowania, ale hasła aplikacji są hashowane stałym kluczem niezależnym od salt, więc działają, dopóki ktoś ich nie unieważni.
Jak ustawić stronę polityki prywatności w WordPressie
Instalator tworzy stronę “Polityka prywatności” jako szkic i przypisuje ją w Ustawienia > Prywatność, ekranie dodanym w WordPressie 4.9.6 (dokumentacja ustawień prywatności). Szkic zawiera proponowane nagłówki i przykładowy tekst, a nie gotową politykę. Ten sam ekran pozwala wybrać inną stronę i prowadzi do przewodnika po polityce prywatności, w którym rdzeń i wtyczki rejestrujące proponowany tekst przez wp_add_privacy_policy_content() opisują, co przechowują.
Wynikają z tego dwie rzeczy. Szkic nie jest publiczny, dopóki ktoś go nie zredaguje i nie opublikuje. A motywy wypisują link do polityki przez the_privacy_policy_link(), który nic nie wyświetla, dopóki przypisana strona nie jest opublikowana, więc “brakujący” link w stopce zwykle oznacza nieopublikowaną stronę. Narzędzia > Eksport danych osobistych i Narzędzia > Usuwanie danych osobistych obsługują wnioski o dostęp i usunięcie danych, które przechowują WordPress i współpracujące z tymi narzędziami wtyczki.
Podsumowanie: 50-punktowa lista kontrolna
Bezpieczeństwo (1-15)
- ✅ Ustaw własny prefiks tabel (przy instalacji, przez
$table_prefix) - ✅ Ustaw silne hasła (min. 12 znaków)
- ✅ Zmień nazwę użytkownika admin
- ✅ Wyłącz edytor plików w panelu
- ✅ Zablokuj instalację wtyczek (opcjonalnie; zatrzymuje też automatyczne aktualizacje)
- ✅ Wymuś SSL w panelu administracyjnym
- ✅ Zabezpiecz wp-config.php przez .htaccess
- ✅ Zablokuj dostęp do katalogów (no indexes)
- ✅ Ogranicz XML-RPC (filtr obejmuje tylko metody z uwierzytelnieniem; zostaw go dla Jetpacka)
- ✅ Ukryj wersję WordPressa
- ✅ Ogranicz próby logowania
- ✅ Skonfiguruj uwierzytelnianie dwuskładnikowe (wtyczka Two Factor)
- ✅ Regularnie rotuj klucze uwierzytelniania (salts)
- ✅ Zainstaluj certyfikat SSL
- ✅ Skonfiguruj zabezpieczenia na poziomie serwera (firewall, ograniczenie prób logowania)
Wydajność (16-25)
- ✅ Ogranicz rewizje postów (5-10)
- ✅ Wyłącz emoji
- ✅ Wyłącz nieużywane funkcje (XML-RPC, RSD)
- ✅ Zoptymalizuj rozmiary obrazów
- ✅ Sprawdź, czy leniwe ładowanie działa (domyślnie od 5.5)
- ✅ Skonfiguruj cache (obiektowy, page cache)
- ✅ Zoptymalizuj Heartbeat API
- ✅ Włącz kompresję GZIP/Brotli
- ✅ Skonfiguruj CDN (opcjonalnie)
- ✅ Zoptymalizuj bazę danych (automatyczne czyszczenie)
SEO (26-35)
- ✅ Ustaw strukturę permalinków “Nazwa wpisu”
- ✅ Ustaw nazwę i opis witryny (opis to nie meta description)
- ✅ Sprawdź mapę witryny z rdzenia pod /wp-sitemap.xml
- ✅ Dodaj stronę do Google Search Console
- ✅ Skonfiguruj Google Analytics / GA4
- ✅ Napisz tekst ALT dla każdego obrazu
- ✅ Utwórz strukturę kategorii
- ✅ Skonfiguruj breadcrumbs
- ✅ Dodaj schemat Organization
- ✅ Przygotuj meta tagi Open Graph
Kopie zapasowe (36-42)
- ✅ Skonfiguruj automatyczne kopie bazy danych
- ✅ Skonfiguruj pełne kopie tygodniowe
- ✅ Przechowuj kopie w zewnętrznej lokalizacji
- ✅ Przetestuj przywracanie z kopii
- ✅ Ustaw retencję kopii (min. 30 dni)
- ✅ Dokumentuj procedurę przywracania
- ✅ Regularnie weryfikuj integralność kopii
Treść i funkcjonalność (43-50)
- ✅ Utwórz strony podstawowe (O nas, Kontakt, Polityka prywatności)
- ✅ Skonfiguruj menu nawigacyjne
- ✅ Przetestuj wszystkie formularze
- ✅ Skonfiguruj SMTP dla poczty
- ✅ Utwórz niestandardową stronę 404
- ✅ Dodaj favicon i ikony PWA
- ✅ Przeprowadź testy wydajności
- ✅ Dokumentuj konfigurację
Zobacz nasz audyt bezpieczeństwa WordPress, jeśli chcesz uporządkować ryzyka i zabezpieczenia serwisu.
Różnice w wp-config.php między stagingiem a produkcją
Ten poradnik podaje WP_DEBUG dwa razy z różnymi wartościami: w sekcji o debugowaniu jako true, w sekcji o monitoringu jako false. Obie wersje są poprawne, każda dla innego środowiska, dlatego ta sama kopia wp-config.php nie powinna trafiać bez zmian na staging i na produkcję. Zanim przeniesiesz plik między serwerami, przejdź przez te stałe:
WP_ENVIRONMENT_TYPE:stagingna kopii testowej,productionna żywej stronie. Od tej wartości zależy każdy warunek oparty nawp_get_environment_type().WP_DEBUG: włączony na stagingu, wyłączony na produkcji.WP_DEBUG_DISPLAYzostajefalsew obu miejscach, a log trafia poza katalog publiczny.SAVEQUERIES: tylko na czas szukania wolnych zapytań, nigdy na produkcji.DISALLOW_FILE_MODS: na produkcji blokuje instalację i aktualizację wtyczek z panelu, więc aktualizacje przechodzą przez wdrożenie albo WP-CLI. Ustal to z klientem, zanim zauważy brak przycisku aktualizacji.- Klucze uwierzytelniania: generowane losowo dla każdej instalacji. Kopia produkcji na stagingu dostaje własny zestaw, a produkcyjnych nie ruszasz, bo ich zmiana wylogowuje wszystkich użytkowników.
Po przeniesieniu pliku uruchom wp core verify-checksums i wp plugin verify-checksums --all z sekcji o testach przed uruchomieniem.







