↓ До тексту
  1. Статті/

WordPress по-дорослому: Apache + PHP-FPM + MariaDB + Redis

·5 хвилин
cat /etc/passwd
Автор
cat /etc/passwd
Технічний блог про Linux, DevOps та Open Source технології.
Зміст
WordPress по-дорослому - частина серії статей.
Частина 1: ця стаття (ти тут)

«Поставити WordPress» вміє й хостинг у два кліки. Але коли хочеться розуміти, що там під капотом, і зробити по-дорослому - то це Apache, який віддає PHP у PHP-FPM (а не старий mod_php), окрема база на MariaDB, і Redis як object cache, щоб сторінки не збирались щоразу з нуля. Зберемо все це руками, крок за кроком - так, щоб потім ти міг це повторити з заплющеними очима.

А як цей самий стек запакувати в Docker або перенести з Apache на nginx - показую окремими нотатками (посилання в кінці). Спочатку варто розуміти, що з чого складається.

Що потрібно зробити?
#

Підняти повноцінний WordPress-стек на свіжому Debian: вебсервер Apache з PHP-FPM, базу MariaDB з окремим користувачем, Redis для кешу об’єктів, і сам WordPress - з правильними конфігами й правами.

З чим працюю?
#

1
2
3
root@wp:~# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
VERSION_CODENAME=trixie

Debian 13 (PHP тут - версії 8.4). Усе роблю від root; де в тебе інша версія PHP - підстав свою (подивитись: ls /etc/php/).

WordPress stack · Debian 13 linuxway.com.ua

Далі ті самі кроки по порядку, з готовими конфігами - копіюй і став у себе.

Крок 1. Apache і PHP-FPM
#

Ставимо вебсервер, PHP-FPM і набір розширень, які WordPress реально використовує (робота з БД, картинками, текстом, архівами):

1
2
3
apt update
apt install -y apache2 php-fpm php-mysql php-redis php-gd php-curl \
  php-xml php-mbstring php-zip php-intl php-bcmath mariadb-server redis-server
Чому PHP-FPM, а не mod_php? PHP-FPM - це окремий пул процесів, який не прив’язаний до Apache. Він ефективніший під навантаженням, працює з продуктивним MPM event, і його можна тюнити окремо від вебсервера. Це стандарт де-факто.

Вмикаємо модулі Apache, через які він віддаватиме PHP у FPM, і підключаємо конфіг FPM:

1
2
a2enmod proxy_fcgi setenvif rewrite headers
a2enconf php8.4-fpm

Крок 2. Віртуальний хост
#

Тепер опишемо сам сайт. Відкриваємо новий конфіг у редакторі:

1
nano /etc/apache2/sites-available/wordpress.conf

І вклеюємо:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<VirtualHost *:80>
    ServerName wordpress.example.com
    DocumentRoot /var/www/wordpress
    DirectoryIndex index.php index.html

    <Directory /var/www/wordpress>
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # PHP віддаємо у php-fpm через сокет (не mod_php)
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost"
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/wordpress_error.log
    CustomLog ${APACHE_LOG_DIR}/wordpress_access.log combined
</VirtualHost>

Ключовий рядок тут - SetHandler "proxy:unix:/run/php/php8.4-fpm.sock|fcgi://localhost": саме він відправляє всі .php у сокет PHP-FPM. AllowOverride All потрібен, щоб працювали «гарні посилання» WordPress через .htaccess.

Вимикаємо дефолтний сайт, вмикаємо наш:

1
a2dissite 000-default && a2ensite wordpress

Крок 3. PHP під WordPress
#

Дефолтні ліміти PHP для WordPress замалі - картинку не завантажиш. Кладемо свій drop-in, щоб не чіпати основний php.ini:

1
nano /etc/php/8.4/fpm/conf.d/99-wordpress.ini
1
2
3
4
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 120

Перевіряємо конфіг Apache і перечитуємо обидва сервіси:

1
2
apachectl configtest
systemctl reload apache2 && systemctl restart php8.4-fpm

Крок 4. База даних MariaDB
#

WordPress-у потрібна база і окремий користувач - не root. Кодування - utf8mb4 (повноцінний Unicode, разом з емодзі):

1
2
3
mysql -e "CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -e "CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'ВАШ_СКЛАДНИЙ_ПАРОЛЬ';"
mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost'; FLUSH PRIVILEGES;"
Пароль постав свій і складний, і давай права wpuser лише на базу wordpress.*, а не на все (*.*). Якщо колись зламають сайт - зловмисник не дотягнеться до інших баз.

Крок 5. Redis
#

Redis уже встановлено разом з усіма пакетами - лишається переконатись, що він запущений і в автозапуску:

1
2
systemctl enable --now redis-server
redis-cli ping     # -> PONG

Розширення php-redis ми теж поставили на першому кроці - саме воно дасть WordPress говорити з Redis.

Крок 6. WordPress
#

Качати архів і колупати wp-config руками - вчорашній день. Беремо WP-CLI:

1
2
curl -fsSL -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x /usr/local/bin/wp

Качаємо ядро, створюємо конфіг і ставимо сайт - однією серією команд:

1
2
3
4
5
6
7
8
mkdir -p /var/www/wordpress && cd /var/www/wordpress

wp core download --allow-root
wp config create --dbname=wordpress --dbuser=wpuser \
  --dbpass='ВАШ_СКЛАДНИЙ_ПАРОЛЬ' --dbhost=localhost --allow-root
wp core install --url=http://ВАШ_ДОМЕН --title="Мій блог" \
  --admin_user=admin --admin_password='СКЛАДНИЙ_ПАРОЛЬ_АДМІНА' \
  --admin_email=admin@example.com --allow-root

Крок 7. Вмикаємо Redis object cache
#

Тепер найсмачніше - підключаємо Redis як кеш об’єктів. Два рядки в конфіг (WP-CLI допише їх сам), плагін-дропін, і вмикаємо:

1
2
3
4
5
wp config set WP_REDIS_HOST 127.0.0.1 --allow-root
wp config set WP_CACHE true --raw --allow-root

wp plugin install redis-cache --activate --allow-root
wp redis enable --allow-root        # -> Object cache enabled

Нарешті віддаємо файли вебсерверу - усе має належати www-data:

1
chown -R www-data:www-data /var/www/wordpress

Перевірка
#

Переконуємось, що кеш реально підключився:

1
wp redis status --allow-root
1
2
3
Status: Connected
Client: PhpRedis (v6.2.0)
Drop-in: Valid

Connected + Drop-in: Valid - Redis працює, і WordPress складає сторінки з кешу, а не ганяє базу щоразу. А ось і сам сайт у браузері - живий, з нашого стенду:

WordPress, зібраний вручну, у браузері

А як це в Docker?
#

Той самий стек - Apache, PHP, MariaDB, Redis - можна підняти кількома рядками docker compose, не торкаючись системи. Як саме - у окремому пості: WordPress у Docker. Коли розумієш, що з чого складається вручну, контейнери стають не магією, а просто зручною упаковкою.

А якщо замість Apache - nginx?
#

Вебсервер тут - змінна деталь. Той самий WordPress можна віддавати не Apache, а nginx: база, PHP-FPM і Redis лишаються ті самі, міняється один server-блок замість віртуального хоста. Що саме відрізняється - try_files замість .htaccess і fastcgi_pass замість SetHandler - коротко розібрав окремо: WordPress на nginx.

Весь стек - це Apache з PHP-FPM, окрема база на MariaDB і Redis для кешу. Виглядає як багато кроків, та кожен - одна-дві команди. А на виході - WordPress, зібраний по-дорослому, який не соромно й у прод.

WordPress по-дорослому - частина серії статей.
Частина 1: ця стаття (ти тут)

Related