Jak ustawić cron WordPress w serwerze zewnętrznym

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 cro­na. 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.

< Powrót

Zapisz się do newslettera


Zadzwoń Napisz