Помилки wp-config.php у WordPress: поширені некоректні налаштування й виправлення

Було корисно?

Найшвидший спосіб вивести з ладу здоровий сайт на WordPress — це не поганий плагін. Це «дрібна» зміна в wp-config.php, зроблена під тиском: змінено хост БД, залишено ввімкненим режим налагодження, припущено заголовок від зворотного проксі, напіввстановлено drop-in для кешу.

Оскільки wp-config.php читається рано в процесі завантаження, помилки тут не деградують м’яко. Вони або гучно провалюються, або ще гірше: працюють уривчасто, тихо зливаючи інформацію, пропускаючи cron або пишучи логи до вичерпання диска.

Що насправді робить wp-config.php (і чому помилки болючі)

wp-config.php — це не просто «де зберігається пароль до бази даних». Це панель керування тим, як WordPress завантажується: звідки читає дані, що він вважає за схему/хост запиту, як він логуватиме, який шар кешування намагається завантажити й яким токенам безпеки довіряє.

Більшість конфігурацій читаються пізніше, після ініціалізації фреймворка. WordPress читає wp-config.php рано і часто. Це має два операційні наслідки:

  • Режими відмов проявляються негайно. Синтаксичні помилки, неправильні константи, хибні шляхи для include: ви отримуєте білі екрани, 500-ки або «Error establishing a database connection».
  • Неправильна поведінка може бути тонкою. Сайт «працює», але cron не спрацьовує, cookie адміністратора недійсні, з’являється змішаний контент, об’єктний кеш шаленоюється або логи зростають зі швидкістю, яка вразила б DDoS-бота.

Принципи, які допомагають уникнути проблем

  • Робіть зміни відкотними. Якщо ви не можете відкотити зміни за кілька секунд, ви не «конфігуруєте», ви граєтеся з ризиком.
  • Віддавайте перевагу секретам через оточення. Чим менше закодованих у файлі облікових даних, тим менше шансів, що вони опиняться в гіті, архіві резервних копій або в пастебіні.
  • Не використовуйте wp-config.php як смітник. Це спокуса. Опирайтеся. Якщо ви визначаєте десять несумісних констант, щоб заклеїти поведінку плагіна, ви будуєте пам’ятник майбутнім відмовам.

Один маленький знак тривоги: коли команда каже «це просто налаштування», зазвичай саме тоді слід запланувати maintenance window.

Жарт 1: wp-config.php — як коробка «лломити скло». Якщо ви відкриваєте її без підготовки, то вже маєте проблему.

План швидкої діагностики

Це потік «зупинити кровотечу». Він орієнтований на продакшн: мінімальні зміни, максимум сигналу. Виконуйте кроки у порядку, якщо тільки у вас немає очевидної причини.

Спочатку: підтвердьте клас відмови (PHP parse vs WordPress vs інфраструктура)

  1. Перевірте HTTP-статус і тіло відповіді. 500 з порожнім тілом часто означає PHP fatal/parse; «Error establishing a database connection» — WordPress ловить помилки підключення до БД.
  2. Підслідкуйте логи PHP-FPM / вебсерверу. Якщо бачите «Parse error» з посиланням на wp-config.php, зупиніться й виправте синтаксис перш ніж робити інше.
  3. Перевірте, чи PHP може прочитати файл. Неправильні дозволи можуть виглядати як «відсутній конфіг».

По-друге: перевірте підключення до бази даних з хоста додатка

  1. Розв’яжіть DB host. Дрейф DNS спричиняє реальні відмови.
  2. Підключіться з тими самими обліковими даними. Доведіть, що ім’я користувача/пароль і мережевий шлях дійсні.
  3. Підтвердіть очікування щодо charset/collation. Неправильно вказані значення не завжди блокують завантаження, але можуть корумпувати дані з часом або ламати міграції.

По-третє: оцініть припущення щодо схеми/хоста запиту

  1. За зворотним проксі? Якщо заголовки в $_SERVER не довіряють правильно, ви отримаєте петлі редиректів, змішаний контент або проблеми з входом в адмінку.
  2. Перевірте WP_HOME і WP_SITEURL. Одна неправильна літера може відрізати вас від адмінки через нескінченні редиректи.

По-четверте: шукайте «корисні» перемикачі, що стали тягарем

  1. Режими налагодження. WP_DEBUG увімкнений у продакшні — це тягар для продуктивності і ризик витоку даних.
  2. Drop-in для кешу. Неправильні налаштування Redis/Memcached призводять до дивної поведінки входу й зростання CPU, що маскується під «WordPress повільний».
  3. Налаштування cron. Вимкнення WP-Cron без справжнього системного cron — причина, чому розсилки і задачі зупиняються, а хтось помічає це лише коли маркетинг дзвонить.

Якщо запам’ятати одну річ: доведіть базові речі спочатку — синтаксис, дозволи, доступність БД — перед дискусією про кешування.

Цікаві факти та історія, які стануть у пригоді

  • Факт 1: WordPress історично використовував wp-config-sample.php як шаблон; люди досі копіюють його слово в слово, включно з застарілими припущеннями про salts, debug і дефолти хосту БД.
  • Факт 2: Налаштування $table_prefix існувало частково тому, що WordPress очікував спільні бази даних і кілька установок в одній схемі — поширене в ранньому бюджетному хостингу.
  • Факт 3: «Drop-ins» WordPress (наприклад, object-cache.php) завантажуються раніше за більшість плагінів. Зламаний drop-in може поламати все, поки ваш список плагінів виглядає невинно.
  • Факт 4: Конфіг підтримує define('WP_CACHE', true) переважно для координації з плагінами кешування, але встановлення його без усього стеку — класичне напіввстановлення.
  • Факт 5: DISABLE_WP_CRON з’явився як прагматична відповідь на залежне від трафіку планування. На малопоточних сайтах WP-Cron — це майже «можливо пізніше».
  • Факт 6: Багато хостів запускають PHP під іншим користувачем (пул FPM), ніж ваш SSH-користувач. Права файлів, що «виглядають нормально» в оболонці, можуть бути недоступні PHP.
  • Факт 7: FORCE_SSL_ADMIN з’явився до сучасної норми «все через TLS». Це все ще має значення при розбитому TLS-термінуванні або багаторівневих проксі.
  • Факт 8: WordPress може брати константи БД з змінних оточення. Це не просто тренд «12-factor»; це реальний спосіб уникнути коміту секретів у образи або репозиторії.
  • Факт 9: Канонічне місце wp-config.php може бути на одну директорію вище від документного кореня. Це стара практика жорсткого захисту — і вона досі працює.

Більшість цих функцій виникли через обмеження спільного хостингу і потім перейшли в серйозний продакшн. Ось чому wp-config.php може виглядати як археологічна розкопка.

Практичні завдання: команди, виводи та рішення

Це завдання «запустити зараз». Кожне включає: команду, що означає вивід, і яке рішення прийняти далі. Вони написані для типового Linux-хоста з Nginx/Apache + PHP-FPM + MySQL/MariaDB, але логіка працює й в інших середовищах.

Завдання 1: Перевірити, що wp-config.php існує і не є битим символьним посиланням

cr0x@server:~$ ls -la /var/www/html/wp-config.php
-rw-r----- 1 www-data www-data 3890 Dec 27 10:11 /var/www/html/wp-config.php

Що це означає: Файл існує, є звичайним файлом і читабельний групою веб-користувача. Якщо бачите wp-config.php -> /some/path, підтвердіть, що ціль існує.

Рішення: Якщо відсутній або нечитаємий — виправте шлях/дозволи перед будь-якими іншими діями. WordPress не «обійде» відсутній конфіг.

Завдання 2: Перевірити дозволи (і впіймати пастку «SSH-користувач vs PHP-користувач»)

cr0x@server:~$ namei -l /var/www/html/wp-config.php
f: /var/www/html/wp-config.php
drwxr-xr-x root     root     /
drwxr-xr-x root     root     var
drwxr-xr-x root     root     www
drwxr-xr-x root     root     html
-rw-r----- www-data www-data wp-config.php

Що це означає: Біт виконання директорій дозволяє проходження; фінальний файл читається. Якщо будь-яка директорія на шляху позбавлена виконання для PHP-користувача, PHP не дістанеться до файлу.

Рішення: Виправте дозволи на проходження директорій, а не «chmod 777» для всього. Якщо ви роздумуєте про 777 — відкладіть, випийте кави й зробіть по-людськи.

Завдання 3: Перевірити, що wp-config.php не має PHP-parse помилок

cr0x@server:~$ php -l /var/www/html/wp-config.php
No syntax errors detected in /var/www/html/wp-config.php

Що це означає: PHP може його розпарсити. Типові помилки: зайвий BOM, відсутня крапка з комою, скопійовані «розумні» лапки з таску або зайвий <?php.

Рішення: Якщо синтаксис кричить — виправте це перш за все. Все інше — шум, поки парсинг не пройде.

Завдання 4: Підтвердити наявність констант БД (без широкого виведення секретів)

cr0x@server:~$ sudo -u www-data php -r 'include "/var/www/html/wp-config.php"; echo DB_NAME, "\n", DB_HOST, "\n";'
wordpress_prod
db01.internal

Що це означає: Конфіг завантажується під тим самим користувачем, що й PHP, і константи доступні. Якщо include падає — побачите warning/fatal.

Рішення: Якщо це не вдається — фокусуйтеся на дозволах/шляхах/includes. Якщо вдається — переходьте до перевірки мережі/доступності БД.

Завдання 5: Перевірити DNS-резолюцію для DB_HOST

cr0x@server:~$ getent hosts db01.internal
10.20.30.41 db01.internal

Що це означає: Хост резолюється. Якщо ні — WordPress може багаторазово намагатися й зазнавати невдач, нагромаджуючи PHP-процеси.

Рішення: Якщо DNS не працює — виправте DNS/hosts або тимчасово використайте IP (з планом повернення). Не «лікуйте» WordPress, коли проблема в DNS.

Завдання 6: Перевірити TCP-з’єднання до порту бази даних

cr0x@server:~$ nc -vz db01.internal 3306
Connection to db01.internal 3306 port [tcp/mysql] succeeded!

Що це означає: Мережевий шлях відкритий. Якщо timeout/відмова — це фаєрвол, security group, база вимкнена або невірний порт.

Рішення: Якщо TCP не працює — не міняйте паролі БД. Виправте мережеву доступність спочатку.

Завдання 7: Аутентифікуватися в MySQL тими ж обліковими даними, що й WordPress

cr0x@server:~$ mysql -h db01.internal -u wp_user -p -e "SELECT 1;"
Enter password:
1
1

Що це означає: Облікові дані працюють, і сервер БД відповідає. Якщо аутентифікація провалюється — повідомлення про помилку дуже цінне: «Access denied», «Unknown database» тощо.

Рішення: Якщо аутентифікація не вдається — перевірте DB_USER, DB_PASSWORD і привілеї. Якщо ім’я бази неправильне — виправте DB_NAME, а не створюйте нову порожню схему «щоб воно працювало».

Завдання 8: Ідентифікувати схему/хост запиту з краю (перевірка reverse proxy)

cr0x@server:~$ curl -I http://127.0.0.1 | sed -n '1,10p'
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sat, 27 Dec 2025 10:20:04 GMT
Content-Type: text/html
Content-Length: 162
Location: https://example.com/

Що це означає: Ви бачите редирект. Якщо ви за проксі, що завершує TLS, origin може думати, що це HTTP, і редиректити неправильно.

Рішення: Якщо є петлі редиректів — перевірте WP_HOME/WP_SITEURL і обробку проксі-заголовків перед тим, як лізти у плагіни.

Завдання 9: Перевірити петлю редиректів з публічного хоста

cr0x@server:~$ curl -sS -o /dev/null -D - https://example.com/wp-admin/ | sed -n '1,12p'
HTTP/2 302
date: Sat, 27 Dec 2025 10:21:11 GMT
content-type: text/html; charset=UTF-8
location: https://example.com/wp-login.php?redirect_to=https%3A%2F%2Fexample.com%2Fwp-admin%2F&reauth=1
set-cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; secure; HttpOnly

Що це означає: Нормальний адмiн-потік редиректить на логін. Якщо ви постійно перескакуєте між http/https або різними хостнеймами — конфіг бреше про канонічну URL.

Рішення: Виправте канонічні URL в конфігурації (або в БД) і налаштуйте визначення схеми проксі. Не «вирішуйте» це випадковим плагіном для редиректів.

Завдання 10: Підтвердити режим налагодження і чи ростуть логи

cr0x@server:~$ grep -nE "WP_DEBUG|WP_DEBUG_LOG|WP_DEBUG_DISPLAY" /var/www/html/wp-config.php
92:define('WP_DEBUG', false);
93:define('WP_DEBUG_LOG', true);
94:define('WP_DEBUG_DISPLAY', false);

Що це означає: Debug вимкнено, але логування увімкнено. Така комбінація інколи задумана, але може сильно нарощувати записи, якщо плагіни викидають notices.

Рішення: Якщо дискове використання зростає — або виправте «галасливий» код, або вимкніть debug-логування в продакшні й спрямовуйте помилки в PHP-FPM/syslog з нормальною ротацією.

Завдання 11: Спостерігати за розміром логів і тиском ротації (улюблений інцидент інженера сховища)

cr0x@server:~$ sudo du -sh /var/www/html/wp-content/debug.log
3.6G	/var/www/html/wp-content/debug.log

Що це означає: Файл величезний. На маленькому кореневому розділі це спосіб перетворити «сайт недоступний» на «сервер недоступний».

Рішення: Якщо лог розрісся — зупиніть запис: вимкніть debug-лог, безпечно обріжте файл і додайте ротацію. Також дослідіть, чому він виріс (часто одна повторювана помилка в гарячому шляху).

Завдання 12: Перевірити вільний місце в файловій системі (бо помилки конфігурації впливають на диск)

cr0x@server:~$ df -h /var/www
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   39G  600M  99% /

Що це означає: Ви в один деплой від простою. На 99% MySQL і PHP-FPM починають поводитися непередбачувано.

Рішення: Негайно звільніть місце (логи, старі релізи, кеші), потім знайдіть корінь проблеми (зазвичай debug-логи, резервні копії на тому ж томі або неконтрольовані кеш-папки).

Завдання 13: Підтвердити наявність drop-in для об’єктного кешу та чи WordPress намагається його використовувати

cr0x@server:~$ ls -la /var/www/html/wp-content/object-cache.php
-rw-r--r-- 1 www-data www-data 14523 Dec 27 09:42 /var/www/html/wp-content/object-cache.php

Що це означає: Drop-in існує. Це означає, що WordPress завантажить його рано. Якщо він зламаний або вказує на недоступний Redis-хост, ви отримаєте повільну адмінку, проблеми з логіном або fatal-ошибку.

Рішення: Якщо підозрюєте проблеми з кешем — тимчасово перемістіть файл (перейменуйте) під час maintenance і перевірте повторно.

Завдання 14: Перевірити підключення до Redis (якщо він налаштований у wp-config.php)

cr0x@server:~$ redis-cli -h 127.0.0.1 ping
PONG

Що це означає: Redis досяжний і відповідає. Якщо timeout — він вимкнений, слухає на іншому інтерфейсі, захищений ACL або заблокований фаєрволом.

Рішення: Якщо Redis недоступний — вимкніть інтеграцію об’єктного кешу до вирішення. Зламані кеші гірші за відсутність кешу.

Завдання 15: Підтвердити ліміт пам’яті PHP і чи WordPress його перевизначає

cr0x@server:~$ php -i | grep -i "^memory_limit"
memory_limit => 256M => 256M

Що це означає: Базовий memory_limit PHP — 256M. WordPress може запросити більше через константи як WP_MEMORY_LIMIT, але не перевищить жорсткий ліміт PHP, якщо він налаштований.

Рішення: Якщо бачите «Allowed memory size exhausted», підніміть ліміт у PHP-FPM (і потім знайдіть, що їсть пам’ять; не підвищуйте нескінченно).

Завдання 16: Перевірити канонічні URL WordPress у базі, коли конфіг їх не визначає

cr0x@server:~$ mysql -h db01.internal -u wp_user -p -D wordpress_prod -e "SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');"
Enter password:
option_name	option_value
home	https://example.com
siteurl	https://example.com

Що це означає: Значення в БД узгоджені. Якщо вони не збігаються (або містять неправильний хост/схему), ви отримаєте петлі редиректів, зламані URL ресурсів і проблеми в адмінці.

Рішення: Якщо неправильно — виправляйте обережно. Краще контролюваний апдейт і очистка кешу. Не «тимчасово» хардкодьте константи й забувайте про це роками.

Завдання 17: Перевірити поведінку cron, якщо встановлено DISABLE_WP_CRON

cr0x@server:~$ grep -n "DISABLE_WP_CRON" /var/www/html/wp-config.php
110:define('DISABLE_WP_CRON', true);

Що це означає: WP-Cron вимкнено. Це нормально лише за наявності реального системного cron, що викликає wp-cron.php.

Рішення: Якщо немає системного cron — знову ввімкніть WP-Cron або одразу додайте cron-job. Інакше планові пости, очищення й фонова робота зупиняться тихо.

Поширені помилки: симптом → корінь → виправлення

Цей розділ ви відкриєте о 02:00. Він спроєктований так, щоб зіставити те, що ви бачите, з тим, що насправді неправильно, і дати конкретне виправлення.

1) Білий екран / HTTP 500 одразу після редагування wp-config.php

Симптоми: Порожня сторінка, 500-ка або «There has been a critical error» одразу після зміни конфігу.

Корінь: PHP-синтаксична помилка (відсутня крапка з комою, зайва лапка), BOM на початку файлу або дублювання <?php тегів.

Виправлення: Запустіть php -l проти файлу; відкотіть до останньої робочої версії. Якщо копіювали з тикета — перевірте на «smart quotes».

2) «Error establishing a database connection»

Симптоми: Фронтенд і адмінка показують сторінку помилки БД; health checks падають.

Корінь: Неправильний DB_HOST, неправильні облікові дані, відсутні привілеї, проблема резолюції DNS або сервер БД вимкнений.

Виправлення: Доведіть мережеве підключення (nc) і аутентифікацію через mysql з тими ж креденшалами. Обертати паролі тільки після підтвердження доступності БД та її здоров’я.

3) Петля редиректів (особливо після додавання reverse proxy/CDN)

Симптоми: Браузер каже «too many redirects», вхід в адмінку зациклюється або постійні перемикання HTTP/HTTPS.

Корінь: WordPress вважає запити HTTP, коли їх термінує HTTPS на краю; WP_HOME/WP_SITEURL не збігаються; заголовки проксі не довірені.

Виправлення: Встановіть канонічні URL послідовно й обробляйте HTTP_X_FORWARDED_PROTO лише якщо він надходить від довірених проксі. Не довіряйте заголовкам з інтернету без фільтрації.

4) Попередження про змішаний контент і зламані CSS/JS

Симптоми: Сторінки завантажуються, але ресурси блокуються; адмінка без стилів; консоль показує помилки mixed content.

Корінь: siteurl/home або WP_HOME/WP_SITEURL використовують http://, тоді як сайт віддається через https://.

Виправлення: Стандартизувати HTTPS у конфігурації й у БД. Якщо за проксі — виправте визначення схеми, щоб WordPress генерував HTTPS URL.

5) Інформація про відладку витікає на сторінки

Симптоми: Відвідувачі бачать warnings/notices; HTML сторінки містить шляхи файлів і деталі запитів.

Корінь: WP_DEBUG увімкнено з WP_DEBUG_DISPLAY on, або PHP display_errors увімкнено на рівні FPM.

Виправлення: У продакшні: WP_DEBUG false, WP_DEBUG_DISPLAY false. Логувати помилки в інфраструктурне місце з ротацією. Якщо треба налагоджувати — робіть тимчасово і з чітким часовим лімітом.

6) Диск заповнюється несподівано

Симптоми: Сервер переходить у read-only або сервіси падають; df показує 95–100% зайнятості.

Корінь: WP_DEBUG_LOG генерує величезний wp-content/debug.log; плагін спамить notices; або неправильно налаштований кеш без контролю обсягу записів.

Виправлення: Зупиніть зростання логів (вимкніть debug log), безпечно обріжте файл, додайте ротацію й виправте «галасливий» код.

7) Cookie для входу недійсні або сесії адміністратора рандомно закінчуються

Симптоми: Ви входите, а потім відразу виходите; «Are you sure you want to do this?» — nonce помилки.

Корінь: Зміна salts/ключів (або їх надмірна ротація), невідповідний COOKIE_DOMAIN, проксі змінює хост, або кешування адміністраторських сторінок.

Виправлення: Тримайте salts стабільними, якщо не робите це навмисно для інцидент-реакції. Не кешуйте /wp-admin або сторінки авторизованих користувачів на краю. Забезпечте єдиний канонічний хост і cookie domain.

8) Об’єктний кеш увімкнено, але продуктивність гіршає

Симптоми: Зрослий TTFB, більше CPU, повільна адмінка; періодичні помилки у логах від бекенду кешу.

Корінь: Redis/Memcached недоступні/повільні, неправильний socket/host, невідповідність аутентифікації або drop-in не сумісний з версією PHP.

Виправлення: Перевірте підключення бекенду, виміряйте латентність і відключіть drop-in до стабілізації. Кеш, що блокує запити таймаутами, — самопороджений DoS.

9) Multisite поводиться дивно після міграції

Симптоми: Підсайти редиректять неправильно; завантаження відсутнє; мережевий адмін не працює.

Корінь: Невідповідність констант мультисайту (MULTISITE, SUBDOMAIN_INSTALL, DOMAIN_CURRENT_SITE, шляхи), або застарілі URL у БД.

Виправлення: Трактуйте конфіг multisite як єдине ціле. Перевірте доменні/шляхові константи проти БД і маршрутизації зворотного проксі.

10) Регресія безпеки: відкриті креденшали БД або записуваний конфіг

Симптоми: Креденшали знайдені в репозиторії, бекапах або у файлах з правами для всіх; шкідливе ПЗ редагує конфіг.

Корінь: Слабкі дозволи файлів, секрети у репо, або конфіг в корені документів з хибним серверним налаштуванням, що дозволяє завантажити код (рідко, але катастрофічно).

Виправлення: Заблокуйте дозволи, тримайте секрети поза репо, розгляньте переміщення wp-config.php на одну директорію вище і перевірте, що сервер ніколи не віддає PHP-джерело.

Жарт 2: Залишити WP_DEBUG увімкненим у продакшні — як залишити відкритий капот авто, «щоб краще охолоджувалося». Ви почуєте нові звуки.

Три виробничі міні-історії з продакшну

Міні-історія 1: Інцидент через хибне припущення

Компанія мігрувала WordPress з одної ВМ до «правильної» архітектури: керована БД, load balancer і два ап-нодa. План міграції виглядав солідно. Зміна конфігу виглядала безпечно: поставити DB_HOST на endpoint керованої БД і викатити.

Протягом кількох хвилин стався простій. Обидва ноди віддавали «Error establishing a database connection». Хтось присягнувся, що креденшали вірні, бо «вони працювали на його ноуті». Цю фразу треба приклеїти на кожен телефон on-call.

Корінь проблеми був не в паролі. Проблема була в резолюції імен всередині VPC. Endpoint керованої БД резолювався в приватну адресу, але ап-ноди використовували інший резольвер, який не знав про цю приватну зону. Endpoint резолювався непослідовно, тому PHP-процеси накопичувалися, повторюючи підключення. Health checks падали. Load balancer дренував ноди. Total outage, хоча «БД була up».

Виправлення було нудним: правильна DNS-конфігурація й тест резолюції з ап-сабнету перед будь-якою зміною конфігу. Вони додали preflight-скрипт, що виконує getent hosts і TCP-підключення з кожного нода під час деплою. Наступна міграція пройшла гладко, бо вони перестали припускати, що «DNS просто працюватиме».

Міні-історія 2: Оптимізація, що повернулась бумерангом

З’явився запит на продуктивність під акомпанемент керівництва: «Нам треба швидше». Інженерія відповіла об’єктним кешем Redis. Розумно. Додали drop-in, поставили WP_CACHE і визначили Redis-хост у конфігу. Навантажувальні тести показали покращення. Всі привітали один одного.

Потім у продакшн зайшов трафік. Замість прискорення — латентність зросла. CPU на ап-нодах піднявся. Кількість PHP-FPM воркерів зросла. Навантаження бази впало, що виглядало добре, поки не помітили, що сайт повільніший. Класична історія «ми оптимізували не те».

Справжня причина: Redis був досяжний, але за мережею з додатковим хопом, що додавав періодичні спайки латентності. Drop-in для об’єктного кешу мав generous timeout, який у людському розумінні був прийнятним, а в шляхах запиту — катастрофічним. Коли Redis гальмував, запит чекав. Ще гірше, кеш-місс призводив до більшої роботи PHP, поки воркери чекали на кеш. Ось як «кешування» стає розподіленим механізмом дроселювання.

Виправлення: трактувати Redis як виробничу інфраструктуру, а не чекбокс у плагіні. Перемістили Redis ближче (або в ту саму мережну зону), звузили таймаути і моніторили латентність кешу як базу даних. Коли Redis був хворий — вони віддавали повільніше, але швидко відмовлялися, замість чекати. Прискорення повернулися — бо кеш перестав бути найповільнішим залежним компонентом.

Міні-історія 3: Нудна, але правильна практика, що врятувала день

Інша команда вела WordPress як критичний для доходу актив. Вони не любили ризик. Вони були скрупульозні. Кожна зміна конфігу деплоїлась через pipeline, що робив три перевірки: синтаксичний lint, перевірку дозволів під веб-користувачем і DB-підключення з використанням налаштованого хоста й користувача.

Одного дня рутинна ротація облікових даних пішла не так. Менеджер секретів оновив, але один ап-нод не оновив свої змінні оточення через баг у процес-супервайзорі. Половина флоту мала нові креденшали, половина — ні. Симптом був неприємний: випадкові помилки підключення до БД залежно від того, на який нод потрапляв load balancer.

Pipeline зупинив це до перетворення у великий інцидент. DB probe падав на одному ноді і деплой зупинився. On-call отримав чітке повідомлення: «Cannot authenticate with configured credentials from node X.» Вони віддренували той нод, перезапустили сервіси, щоб підхопити нове оточення, і повернули у флот. Клієнти не помітили.

Урок не в «використовувати змінні оточення». Урок: тестуйте конфіг так, як його використовує продакшн, щоразу. Нудні перевірки запобігають яскравим інцидентам.

парафраз — John Allspaw: надійність народжується з проєктування під те, як системи виходять з ладу, а не з надії, що уважні люди не помиляться.

Чеклісти / поетапний план

Поетапно: безпечно редагувати wp-config.php у продакшні

  1. Зробіть копію з збереженням дозволів.
    cr0x@server:~$ sudo cp -a /var/www/html/wp-config.php /var/www/html/wp-config.php.bak
    

    Значення: -a зберігає mode/ownership/timestamps. Ваш відкат не створить нової проблеми з дозволами.

    Рішення: Якщо не можете зробити резервну копію — ви не готові редагувати.

  2. Редагуйте інструментом, що не додає BOM або «розумні» лапки. Використовуйте vim, nano або адекватний редактор через SSH.
  3. Лінтуйте перед перезавантаженням.
    cr0x@server:~$ php -l /var/www/html/wp-config.php
    No syntax errors detected in /var/www/html/wp-config.php
    

    Рішення: Якщо lint падає — відкотіть негайно і редагуйте спокійно.

  4. Перевірте під веб-користувачем.
    cr0x@server:~$ sudo -u www-data php -r 'include "/var/www/html/wp-config.php"; echo "loaded\n";'
    loaded
    

    Рішення: Якщо це падає — ви, ймовірно, внесли помилку в шляхи/includes/дозволи, яку ваш root-shell приховує.

  5. Зробіть легкий запит і спостерігайте логи. Краще один запит + tail логів, ніж шквал оновлень у браузері.

Чекліст жорсткого захисту (робіть це — не сперечайтеся)

  • Права файлів: читабельні для PHP, не загальнодоступні. Типово: 640 власник www-data або root з групою для читання.
  • Перемістіть wp-config.php на одну директорію вгору, коли ваша структура дозволяє, щоб він не лежав у document root.
  • Вимкніть показ налагодження в продакшні; логуйтесь в контрольоване місце з ротацією.
  • Ротуйте salts обдумано (інцидент-реакція), а не випадково. Ротація salts виводить усіх користувачів з сесій.
  • Не довіряйте forwarded headers за замовчуванням. Приймайте їх лише від відомих IP проксі.
  • Тримайте WP_HOME/WP_SITEURL послідовними. Якщо визначаєте їх у конфігу — задокументуйте причину і джерело істини.
  • Підтвердіть стратегію cron: або WP-Cron увімкнено, або є системний cron. «Вимкнено без заміни» — це не стратегія.

Чекліст продуктивності (версія, що не саботує вас)

  • Міряйте перед увімкненням об’єктного кешу. Якщо вузьке місце — CPU PHP або повільні плагіни, Redis не врятує.
  • Встановіть агресивні таймаути для кешів. Кеш, що гальмує запити — гірший за його відсутність.
  • Тримайте debug-логування вимкненим у гарячих шляхах. Дискові операції — не безкоштовна побічна задача.
  • Зрівняйте ліміти пам’яті з реальністю. Піднімайте ліміти лише разом із виправленням причин (плагіни, великі запити, обробка зображень).

Що варто класти в wp-config.php (а чого не варто)

Налаштування бази даних: правильно, мінімально, тестовано

Щонайменше: DB_NAME, DB_USER, DB_PASSWORD, DB_HOST. Усе інше має бути виправдане. Не розкидайте експериментальні константи, бо якась стаття в блозі так сказала. Блоги не потрапляють у пейджинг.

Salts і ключі: не імпровізуйте з криптографією

Auth keys і salts захищають cookie і nonce. Якщо вони змінюються, сесії інвалідовуються. Це може бути навмисно під час інцидент-реакції. Це не має бути частиною звичайного деплою. Зберігайте їх безпечно і тримайте стабільними.

Префікс таблиць: не панацея для безпеки

Зміна $table_prefix з wp_ — допустима, але не переоцінюйте її. Це слабкий захист від SQL injection; справжній захист — відсутність вразливостей ін’єкції. Тим не менш, унікальні префікси допомагають при хостингу кількох сайтів в одній БД і зменшують випадкові колізії під час міграцій.

Обробка reverse proxy і HTTPS: будьте явними і обережними

Багато відмов починаються з одного рядка, що змушує HTTPS неправильно, або довіряє X-Forwarded-Proto від будь-кого. Якщо потрібно переоприділити визначення схеми в wp-config.php, робіть це з allowlist IP на рівні веб-сервера/проксі, а не з надією всередині PHP.

Налаштування налагодження: обирайте «безпечне логування» або «тимчасовий хаос», а не обидва

У продакшні чистий шаблон: не показувати помилки; логувати помилки в контрольоване місце; ротація логів; алерти на спайки у логах. Якщо потрібна детальна діагностика — обмежте її в часі і майте план відкату.

Автоматичні оновлення і зміни файлів: розумійте радіус ураження

Вимикання редагування файлів і контроль оновлень може бути відповідальним у регульованих середовищах. Але це також може залишити вас з уразливими плагінами на місяці, бо «оновлення страшні». Рішення — на підставі зрілості вашого пайплайну, а не забобонів.

FAQ

1) Чи можу я зберігати креденшали БД у змінних оточення замість wp-config.php?

Так, і це часто краще з операційної точки зору. Ви зменшуєте ризик коміту секретів. Але потрібно переконатися, що сервіс PHP-FPM надійно отримує оновлене оточення при деплої/перезапуску, і мати чіткий шлях відкату.

2) Хто має бути власником wp-config.php: root чи www-data?

Обидва варіанти можуть бути коректними. Root-owned з груповим читанням для PHP-користувача — поширений патерн жорсткого захисту. Головне: PHP повинен читати файл; нападники (і випадкові користувачі) не повинні мати права запису.

3) Чи варто змінювати $table_prefix заради безпеки?

Це дрібний defense-in-depth, а не щит. Робіть це при створенні нової інсталяції або консолідації баз. Не робіть цього панічно під час активного компромісу; зосередьтеся на патчах, ротації креденшалів і судовому огляді.

4) Чому фронтенд працює, а wp-admin зламана після змін у конфігу?

Адмін-шляхи більш чутливі до налаштувань схеми/хоста/cookie. Неправильне визначення reverse proxy, проблеми з cookie domain або правила кешу, що випадково кешують авторизовані відповіді, зазвичай першими вражають wp-admin.

5) Який найбезпечніший спосіб тимчасово ввімкнути налагодження у продакшні?

Увімкніть логування, а не відображення помилок. Обмежте час і слідкуйте за зростанням файлів. Краще логувати на рівні PHP-FPM/вебсерверу з ротацією, а не писати в wp-content/debug.log.

6) Моя помилка «Error establishing a database connection» зникає при оновленні сторінки. Чому?

Інтермитентні підключення до БД зазвичай означають мережеві фліпи, нестабільність DNS, перевищення max connections, або повільну аутентифікацію. Також це може бути перевантаження PHP-FPM, що призводить до таймаутів. Розглядайте це як інфраструктурну проблему, поки не доведете протилежне.

7) Чи варто визначати WP_HOME і WP_SITEURL у wp-config.php?

Тільки якщо є вагома причина (іммутований інфраструктурний образ, контейнерні образи або часті зміни середовища). Якщо ви їх задаєте, ви робите DB-значення неактуальними — задокументуйте це, інакше наступний інженер «пофіксить» БД, а нічого не зміниться.

8) Чи впливає wp-config.php напряму на продуктивність?

Так, опосередковано. Debug-логування, конфіг об’єктного кешу, перемикачі cron і SSL-обробка можуть змінювати латентність та навантаження. Одна неправильна таймаут-настройка кешу може стати найповільнішою залежністю для кожного запиту.

9) Як уникнути виведення сайту з ладу при редагуванні wp-config.php?

Резервне копіювання, lint, тест під веб-користувачем і деплой через контрольований шлях. Якщо можливо — використовуйте canary-node за load balancer для змін конфігів.

Наступні кроки, щоб уникнути повторних інцидентів

Якщо ваші відмови WordPress мають збірку хітів, wp-config.php — ймовірно, перший трек. Виправлення не екзотичні. Вони дисципліновані.

  1. Перетворіть ваш «План швидкої діагностики» у runbook. Синтаксис, дозволи, доступність БД, коректність схеми/хоста, перемикачі debug/кешування.
  2. Додайте preflight-перевірки в деплой. Лінт конфігу, підключення під PHP-користувачем і DB connect probe з використанням налаштованого хоста та користувача.
  3. Зробіть логування безпечним за замовчуванням. Ніякого відображення debug у продакшні. Ротація логів. Алерти на зростання логів і заповнення диска.
  4. Будьте консервативні з кешуванням. Перевіряйте латентність бекенду кешу і ставте таймаути, що швидко відмовляються.
  5. Задокументуйте канонічну URL і поведінку проксі. Більшість петель редиректів — це політична невизначеність, що маскується під баг.

Зробіть це — і wp-config.php знову стане тим, чим має бути: нудним файлом, про який рідко думають. Нудьга — це добре. Нудьга масштабується.

← Попередня
Intel Tick‑Tock: стратегія, яка працювала — поки не перестала
Наступна →
Debian 13 «Address already in use»: знайдіть, хто займає порт (і виправте акуратно)

Залишити коментар