- Dlaczego przenieść WP-Cron na zewnętrzny serwer
- Jak działa WP-Cron w WordPress
- Kiedy pseudo-cron zawodzi
- Korzyści z zewnętrznego CRON-a
- Wyłączenie wbudowanego WP-Cron i przygotowanie WordPressa
- Wyłącz pseudo-cron w wp-config.php
- Sprawdź i uporządkuj istniejące zdarzenia
- Przygotuj endpoint i pomiń cache
- Uwaga przy multisite
- Konfiguracja prawdziwego CRON na serwerze zewnętrznym
- Wymagania i warianty wywołania
- Minimalny wpis w crontab (curl)
- Minimalny wpis w crontab (wget)
- Zapobieganie nakładaniu się uruchomień
- PHP CLI: omijamy HTTP
- WP-CLI: pełna kontrola
- Zabezpieczenie wywołań HTTP
- Systemd Timer zamiast crontab
- Windows Task Scheduler
- Przykłady konfiguracji na popularnych panelach i usługach
- cPanel
- Plesk
- Hostingi współdzielone
- VPS z Nginx/Apache
- Serwery z reverse proxy/CDN
- Monitorowanie, debugowanie i dobre praktyki
- Ustal interwał właściwy dla obciążenia
- Wyjście i logi
- Diagnostyka w WordPress
- Typowe problemy i rozwiązania
- Optymalizacja długich zadań
- Bezpieczeństwo i kontrola dostępu
- Testy obciążeniowe i ewaluacja
- Integracja z narzędziami monitorującymi
- Dobre praktyki konfiguracji serwera
- Kiedy warto użyć alternatyw
Solidne wykonywanie zadań cyklicznych w WordPress nie powinno zależeć od przypadkowych odwiedzin. Przeniesienie mechanizmu WP-Cron na zewnętrzny serwer daje większą przewidywalność, kontrolę i widoczność błędów. Poniżej znajdziesz praktyczną instrukcję: od wyłączenia pseudo-crona, przez ustawienie prawdziwego cron, po zabezpieczenie wywołań i monitoring. Krok po kroku ustawisz stabilny harmonogram dla sklepu, bloga czy portalu — w środowisku produkcyjny, na hostingu współdzielonym i VPS, również z systemd oraz narzędziem WP-CLI.
Dlaczego przenieść WP-Cron na zewnętrzny serwer
Jak działa WP-Cron w WordPress
Domyślnie WordPress korzysta z mechanizmu zwanego pseudo-cronem. Za każdym razem, gdy ktoś odwiedza witrynę, ładowany jest skrypt wp-cron.php i sprawdzane są zaplanowane zadania. Jeśli są zaległości, uruchamiane są zdarzenia (np. publikacja artykułów, wysyłka e-maili, synchronizacje czy czyszczenie cache). Ten model jest wygodny na starcie, ale ma kilka istotnych ograniczeń, które w środowisku produkcyjnym bywają dotkliwe.
Kiedy pseudo-cron zawodzi
Jeśli ruch na stronie jest mały, zadania potrafią nie wystartować w terminie — bo nikt nie odwiedził witryny o zadanym czasie. Z kolei przy dużym ruchu wywołań jest za dużo, co zwiększa obciążenie serwera i może powodować nakładanie się procesów. Dodatkowo warstwy cache i WAF (np. Cloudflare) potrafią blokować lub opóźniać wywołania wp-cron.php. Brak stałych logów utrudnia diagnostykę, a błędy potrafią przechodzić niezauważone.
Korzyści z zewnętrznego CRON-a
- Pełna kontrola nad częstotliwością i oknem czasowym uruchomień.
- Stabilność – zadania uruchamiają się niezależnie od wizyt na stronie.
- Łatwe logowanie, alertowanie i bezpieczeństwo (autoryzacja, allowlist IP).
- Mniejsze obciążenie aplikacji dzięki pojedynczemu, świadomie sterowanemu wyzwalaczowi.
- Lepsza diagnostyka – widzisz kod wyjścia i ewentualne błędy HTTP.
Wyłączenie wbudowanego WP-Cron i przygotowanie WordPressa
Wyłącz pseudo-cron w wp-config.php
Podstawowy krok to zablokowanie automatycznych wywołań. Otwórz plik wp-config.php i dodaj linię (najlepiej nad komentarzem “/* That’s all, stop editing! */”):
define(’DISABLE_WP_CRON’, true);
Po tej zmianie WordPress nie będzie próbował uruchamiać wp-cron.php przy wizytach użytkowników. Dzięki temu to Ty decydujesz, kiedy zostanie wywołany harmonogram.
Sprawdź i uporządkuj istniejące zdarzenia
Przed przesiadką warto zajrzeć, jakie zadania są zaplanowane. Jeśli korzystasz z WP-CLI, uruchom:
wp cron event list
Zobaczysz listę hooków, ich terminy i interwały. Usuń zdublowane lub przeterminowane wpisy, jeśli wiesz, że są zbędne. Aby jednorazowo uruchomić zaległe zdarzenia, możesz użyć:
wp cron event run –due-now
Przygotuj endpoint i pomiń cache
Upewnij się, że ruch do wp-cron.php nie jest cache’owany przez wtyczki, CDN czy reverse proxy. W Cloudflare dodaj Page Rule/Transform Rule omijający cache dla ścieżki domena.pl/wp-cron.php. W przypadku Nginx i Apache zwykle wp-cron.php już jest wyłączone z cache, ale lepiej to potwierdzić.
Uwaga przy multisite
W środowisku wielostanowiskowym (multisite) jeden zewnętrzny wyzwalacz może obsłużyć wszystkie witryny. WP-Cron iteruje po blogach i uruchamia właściwe zadania. Jeśli masz osobne docrooty lub instancje, skonfiguruj osobne wpisy CRON dla każdego vhosta.
Konfiguracja prawdziwego CRON na serwerze zewnętrznym
Wymagania i warianty wywołania
Masz trzy główne sposoby wywołania cronów na zewnątrz:
- HTTP: poprzez curl lub wget wywołujesz wp-cron.php (dobry, gdy PHP działa przez FPM/Apache i chcesz odwzorować prawdziwe żądanie HTTP).
- PHP CLI: uruchamiasz bezpośrednio interpreterem PHP plik wp-cron.php (mniej zależności, ale środowisko może się różnić od HTTP).
- WP-CLI: wykonujesz wp cron event run –due-now (największa kontrola i czytelne wyjście).
Każdy wariant obsłuży zaplanowane zadania. Wybierz ten, który pasuje do infrastruktury i polityk bezpieczeństwa.
Minimalny wpis w crontab (curl)
Najprostsza forma, gdy masz dostęp do crontab na zewnętrznym serwerze:
*/5 * * * * curl -sS -m 55 -A ExternalCron/1.0 https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1 >/dev/null 2>&1
Wyjaśnienie: co 5 minut, w ciszy (s), z raportowaniem błędów (S), timeout 55 s, niestandardowy User-Agent. Parametr doing_wp_cron=1 podpowiada WordPressowi, że wyzwalasz crona celowo. Przekierowanie do /dev/null zapobiega przepełnianiu skrzynki mailowej użytkownika crona.
Minimalny wpis w crontab (wget)
Alternatywa, jeśli wolisz wget:
*/5 * * * * wget -q -O – https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1 >/dev/null 2>&1
Flaga -q ucisza wyjście, -O – wypisuje na STDOUT, który kierujemy do /dev/null.
Zapobieganie nakładaniu się uruchomień
Jeśli wykonanie zadań trwa dłużej niż interwał CRON, instancje mogą się nakładać. Użyj flock, by dopuścić tylko jedną instancję naraz:
*/5 * * * * flock -n /tmp/wp-cron.lock -c „curl -sS -m 55 https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1” >/dev/null 2>&1
Wariant dla wget:
*/5 * * * * flock -n /tmp/wp-cron.lock -c „wget -q -O – https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1” >/dev/null 2>&1
Dzięki flock -n, jeśli blokada istnieje, rozpoczęcie nowej instancji jest pomijane.
PHP CLI: omijamy HTTP
Jeśli serwer zewnętrzny ma dostęp do plików strony (NFS, rsync, dysk sieciowy lub to ten sam host), możesz uruchamiać wp-cron.php bezpośrednio w PHP:
*/5 * * * * /usr/bin/php -d max_execution_time=60 /var/www/twoja-domena/public/wp-cron.php >/dev/null 2>&1
Pamiętaj, aby ścieżka wskazywała właściwy docroot. PHP CLI nie przechodzi przez warstwę HTTP, więc wyniki mogą minimalnie różnić się od wywołań przez FPM/Apache (np. brak niektórych nagłówków serwera), ale do większości zadań to w pełni wystarcza.
WP-CLI: pełna kontrola
WP-CLI oferuje wbudowane komendy do crona. To doskonała metoda, gdy chcesz uruchamiać tylko zaległe zadania, a nie cały mechanizm:
*/5 * * * * cd /var/www/twoja-domena/public && /usr/local/bin/wp cron event run –due-now –quiet –path=/var/www/twoja-domena/public >/dev/null 2>&1
Możesz dodać –url=https://twoja-domena.pl przy multisite lub niestandardowych konfiguracjach. WP-CLI zwróci kod wyjścia ≠ 0 przy błędzie, co ułatwia alertowanie.
Zabezpieczenie wywołań HTTP
Najprościej dodać allowlist IP w serwerze WWW (nawet jeśli CRON działa poza Twoją siecią, ale z publicznym IP). Apache 2.4:
<Files „wp-cron.php”> Require ip 203.0.113.10 </Files>
Nginx:
location = /wp-cron.php { allow 203.0.113.10; deny all; }
Możesz również dodać token w parametrach URL i po stronie WordPressa zweryfikować go w krótkim mu-plugins. Przykład koncepcji: jeśli GET[external_cron_token] ≠ stała z wp-config.php, zakończ żądanie kodem 403. CRON wtedy wywołuje adres: https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1&external_cron_token=SEKRET.
Systemd Timer zamiast crontab
Na nowoczesnych dystrybucjach Linuksa możesz użyć jednostek systemd do precyzyjnego harmonogramu, lepszego logowania i restartów. Utwórz plik usługi, np. /etc/systemd/system/wp-cron@.service z ExecStart uruchamiającym curl lub WP-CLI, a następnie timer /etc/systemd/system/wp-cron@.timer z OnCalendar=*:0/5. Włącz i uruchom: systemctl enable –now wp-cron@twoja-domena.timer. Zaleta: dzienniki w journalctl, retry, integracja z politykami zasobów.
Windows Task Scheduler
Jeśli zewnętrzny serwer to Windows, użyj Harmonogramu zadań. Utwórz zadanie uruchamiające curl.exe lub PowerShell Invoke-WebRequest do wp-cron.php co 5 minut. Pamiętaj o ustawieniu “Uruchom, nawet jeśli użytkownik nie jest zalogowany”, limitach czasu oraz logowaniu wyjścia do pliku, aby móc diagnozować błędy.
Przykłady konfiguracji na popularnych panelach i usługach
cPanel
Wejdź w Cron Jobs, dodaj nowy wpis. Częstotliwość: co 5 minut. Komenda:
/usr/bin/flock -n /tmp/wp-cron.lock -c „/usr/bin/curl -sS -m 55 https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1” >/dev/null 2>&1
W cPanelu możesz też wskazać powiadomienia e-mail. Jeśli dostajesz zbyt dużo wiadomości, kontroluj wyjście przez >/dev/null 2>&1.
Plesk
Zakładka Narzędzia i Ustawienia → Zaplanowane zadania → Dodaj zadanie. Typ: Uruchom komendę. Komenda:
curl -sS -m 55 -A ExternalCron/1.0 https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1
W opcjach zaawansowanych ustaw niekolidujące okna czasowe i powiadomienia e-mail. Jeżeli Plesk stoi za reverse proxy, upewnij się, że wp-cron.php nie jest przez nie blokowany.
Hostingi współdzielone
W panelach wielu hostingów znajdziesz prosty kreator CRON. Jeśli nie ma flock, zwiększ interwał do 10 minut lub użyj tokenu blokującego na poziomie WordPressa (np. transient z czasem życia i warunkiem przerywającym, gdy “w trakcie”). Wsparcie hostingu bywa pomocne w dopuszczeniu konkretnego User-Agent lub IP.
VPS z Nginx/Apache
Na VPS masz pełną swobodę. Polecam: flock + curl, allowlist IP na vhoście dla wp-cron.php, Page Rule/Bypass w CDN oraz logi w osobnym pliku (np. /var/log/wp-cron/twoja-domena.log). Używaj rotacji logów, np. logrotate, aby pliki nie rosły bez kontroli.
Serwery z reverse proxy/CDN
Za Cloudflare dodaj regułę: URI Path equals /wp-cron.php → Bypass Cache, Disable Performance, Allow. W dodatku warto wymusić TLS 1.2+ i ograniczyć dostęp do ścieżki tylko dla Twojego CRON-a (Firewall Rules). Jeśli korzystasz z AWS CloudFront, dodaj Behaviors wyłączające cache dla /wp-cron.php oraz whitelistuj nagłówki istotne dla aplikacji.
Monitorowanie, debugowanie i dobre praktyki
Ustal interwał właściwy dla obciążenia
Nie każda strona potrzebuje co-minutowego wyzwalacza. Dla większości witryn 5 minut to rozsądny kompromis. Sklepy, integracje ERP i duże portale potrzebują częściej; blog informacyjny i małe strony – rzadziej. Najpierw zmierz średni czas pracy zadań, a dopiero później obniżaj interwał. Pamiętaj o flock, by uniknąć kumulacji uruchomień.
Wyjście i logi
Zamiast całkowicie tłumić wyjście, wyślij je do pliku i rotuj. Przykład dla curl:
*/5 * * * * flock -n /tmp/wp-cron.lock -c „curl -s -m 55 https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1” >> /var/log/wp-cron/twoja-domena.log 2>&1
Analizuj kody HTTP (200, 403, 500). Kod 403 zwykle oznacza reguły WAF/serwera WWW (np. brak allowlist IP). Kod 500 wskazuje na błąd PHP w jednym z hooków crona.
Diagnostyka w WordPress
Włącz logowanie błędów na czas testów: w wp-config.php ustaw WP_DEBUG i WP_DEBUG_LOG. Sprawdzaj wp-content/debug.log po każdym uruchomieniu CRON-a. Narzędzia typu Query Monitor lub dedykowane wtyczki do crona pozwalają przejrzeć harmonogram i problematyczne zadania. Polecenie WP-CLI wp cron event list daje szybki wgląd w kolejkę.
Typowe problemy i rozwiązania
- 403 Forbidden: dodaj allowlist IP dla wp-cron.php albo popraw token; sprawdź moduły bezpieczeństwa (ModSecurity, Wordfence).
- 401 Unauthorized: jeśli aktywna jest ochrona katalogu (Basic Auth), dodaj dane uwierzytelniające w curl (-u user:pass) lub nagłówek Authorization.
- 500 Internal Server Error: przejrzyj debug.log; zwykle błąd w hooku lub przekroczony limit czasu/zasobów.
- Nakładanie zadań: dołóż flock, wydłuż interwał, przeorganizuj długie joby na krótsze porcje.
- Cache CDN: wymuś Bypass dla /wp-cron.php.
Optymalizacja długich zadań
Długo trwające prace (np. importy) podziel na mniejsze porcje z użyciem action scheduler lub batchów. Dodaj timeout i mechanizm wznawiania. Używaj transients lub tabeli kolejek, by przechowywać stan zadania. Dzięki temu pojedynczy przebieg CRON nie przekroczy limitów i nie zablokuje kolejki.
Bezpieczeństwo i kontrola dostępu
Poza allowlist IP, rozważ Basic Auth tylko dla wp-cron.php lub specjalnego endpointu. Przykład wywołania: curl -u user:haslo https://twoja-domena.pl/wp-cron.php?doing_wp_cron=1. W MU-Plugin dodaj sprawdzenie tokenu zgodnego ze stałą w wp-config.php (np. CRON_SECRET). W razie nadużyć łatwo zmienisz token bez dotykania CRON-a.
Testy obciążeniowe i ewaluacja
Po wdrożeniu zewnętrznego wyzwalacza wykonaj test: ręcznie uruchom CRON kilka razy (curl do wp-cron.php lub wp cron event run –due-now) i obserwuj logi, czasy oraz obciążenie CPU/RAM. Zmniejszaj interwał ostrożnie. Jeśli zadania stale trwają dłużej niż interwał, przesuń cięższe operacje na noc lub rozbij je na mniejsze kroki.
Integracja z narzędziami monitorującymi
Narzędzia typu UptimeRobot, Healthchecks.io czy Cronitor potrafią monitorować “pingi” po udanym przebiegu CRON-a. Po zakończeniu zadań wywołaj adres typu https://hc-ping.com/uuid, aby potwierdzić zdrowie procesu. W razie braku pingu w określonym czasie otrzymasz alert e-mail/Slack.
Dobre praktyki konfiguracji serwera
- Ustaw limity: timeouty w curl, limity pamięci dla PHP, sensowne wartości max_execution_time.
- Stosuj unikatowe User-Agent dla CRON-a, aby łatwo filtrować logi.
- Trzymaj pliki logów w osobnym katalogu i rotuj je (logrotate lub wbudowane mechanizmy panelu).
- Dokumentuj miejsce konfiguracji (crontab użytkownika, jednostki systemd, panel hostingowy), aby zespół mógł szybko wprowadzać zmiany.
- Zachowaj spójność strefy czasowej (TZ w środowisku CRON-a vs. strefa WordPressa).
Kiedy warto użyć alternatyw
Jeśli masz setki witryn i chcesz centralnego sterowania, rozważ własny serwis orkiestrujący lub narzędzie do kolejek (Redis, RabbitMQ) z workerami, a WordPress niech jedynie planuje zdarzenia. Wtedy zewnętrzny CRON wyzwala pracę workerów. Dla większości wdrożeń jednak klasyczny CRON z curl lub WP-CLI w zupełności wystarcza.
Po wdrożeniu zewnętrznego mechanizmu wyzwalania zadań twoja instalacja WordPress zyskuje przewidywalność, przejrzyste logowanie i większe bezpieczeństwo. Prawidłowo skonfigurowany wpis CRON, dobrze dobrane interwały, sensowne limity i regularna inspekcja logów sprawią, że wp-cron.php będzie działał dokładnie wtedy, kiedy trzeba, i tylko raz — bez przeciążeń i niespodzianek.