Установка WordPress на VPS: Nginx + PHP-FPM + Redis на Ubuntu 24.04 Печать

  • 0

Если вам нужно быстро поднять WordPress в продакшн, где страницы отдаются шустро, админка не тормозит, а нагрузка держится предсказуемо, связка Nginx + PHP-FPM + Redis это базовый “правильный” стек. В этой инструкции вы поставите WordPress на чистый сервер, настроите Nginx под PHP-FPM, подключите Redis под object cache, включите HTTPS, проверите производительность и сразу закроете типовые ошибки. Дальше покажу, как без боли масштабироваться с одного VPS до multi-node и когда пора переезжать на выделенный сервер или брать подсеть IPv4.

Что получите на выходе и почему стек именно такой

Nginx отвечает за быстрый веб и статик, PHP-FPM изолирует PHP-процессы и даёт нормальную настройку пулов, Redis снимает часть нагрузки с базы и ускоряет админку за счёт object cache. В итоге WordPress становится заметно живее уже на старте, а под нагрузкой деградирует медленнее, чем “как получилось по умолчанию”.

Практический минимум по серверу для нормальной работы одного сайта: 2 vCPU, 2–4 GB RAM, NVMe. Если у вас коммерческий сайт или несколько проектов, это тот случай, когда выгоднее сразу заказать VPS с честными vCPU/NVMe и не экономить на диске. На HSTQ обычно берут VPS в Европе (NL/DE/UK) под минимальную задержку и быстрые апгрейды, а перенос и первичную настройку можно закрыть “под ключ”, чтобы вы не тратили день на рутину.

Важные вводные перед установкой

Чтобы дальше не ловить “почему SSL не ставится” и “почему редирект крутится по кругу”, сделайте базу правильно:

  • У домена должна быть A-запись на IP сервера

  • На сервере должен быть корректный hostname

  • Порты 80 и 443 открыты наружу, SSH доступен вам

  • Система чистая, без старых Apache/Nginx и “случайных” стеков

Дальше я дам рабочий bash-скрипт, который ставит весь стек на Ubuntu 24.04. Для Debian 12 и AlmaLinux 9 ниже будут короткие отличия, но в продакшне я рекомендую именно Ubuntu 24.04 под WordPress, потому что с PHP 8.3 и пакетами всё проще и быстрее.

Быстрая установка одним скриптом Ubuntu 24.04

Скрипт сделан так, чтобы вы не ковыряли конфиги руками. Он спросит домен и email для сертификата, сам поставит пакеты, создаст базу, поставит WordPress через WP-CLI, настроит Nginx + PHP-FPM, включит Redis и активирует object cache. Показ прогресса идёт шагами, после установки выводит проверки.

Запускайте от root на чистом Ubuntu 24.04:

cat > /root/wp-nginx-phpfpm-redis.sh <<'BASH'
#!/usr/bin/env bash
set -euo pipefail

log(){ printf "\n[%s] %s\n" "$(date '+%H:%M:%S')" "$*"; }
step(){ printf "\n[%s/%s] %s\n" "$1" "$2" "$3"; }

need_root(){
  if [[ "$(id -u)" -ne 0 ]]; then
    echo "Run as root"; exit 1
  fi
}

ask(){
  read -r -p "Domain (example.com): " DOMAIN
  read -r -p "Email for Let's Encrypt: " EMAIL
  read -r -s -p "MySQL root password: " DB_ROOT_PASS; echo
  read -r -s -p "WP admin password: " WP_ADMIN_PASS; echo
  if [[ -z "${DOMAIN:-}" || -z "${EMAIL:-}" || -z "${DB_ROOT_PASS:-}" || -z "${WP_ADMIN_PASS:-}" ]]; then
    echo "Empty values are not allowed"; exit 1
  fi
  DB_NAME="wp_${DOMAIN//./_}"
  DB_USER="wp_${DOMAIN//./_}"
  DB_PASS="$(openssl rand -base64 24 | tr -d '=+/')"
  WP_ADMIN_USER="admin"
  WP_ADMIN_EMAIL="$EMAIL"
  WEBROOT="/var/www/${DOMAIN}"
}

sys_prep(){
  step 1 10 "System update and base packages"
  export DEBIAN_FRONTEND=noninteractive
  apt-get update -y
  apt-get upgrade -y
  apt-get install -y ca-certificates curl unzip gnupg lsb-release ufw fail2ban openssl

  step 2 10 "Firewall (UFW): allow SSH/HTTP/HTTPS"
  ufw --force reset
  ufw default deny incoming
  ufw default allow outgoing
  ufw allow 22/tcp
  ufw allow 80/tcp
  ufw allow 443/tcp
  ufw --force enable
}

install_stack(){
  step 3 10 "Install Nginx, MariaDB, PHP-FPM 8.3, Redis, WP-CLI"
  apt-get install -y nginx mariadb-server redis-server \
    php8.3-fpm php8.3-cli php8.3-common php8.3-mysql php8.3-xml php8.3-gd php8.3-curl \
    php8.3-mbstring php8.3-zip php8.3-intl php8.3-bcmath php8.3-imagick php-redis \
    wp-cli certbot python3-certbot-nginx

  systemctl enable --now nginx mariadb redis-server php8.3-fpm
}

secure_mariadb(){
  step 4 10 "Secure MariaDB and create database"
  mysql --protocol=socket -uroot <<SQL
ALTER USER 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASS}';
DELETE FROM mysql.user WHERE User='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;
SQL

  mysql -uroot -p"${DB_ROOT_PASS}" <<SQL
CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';
GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL
}

tune_php(){
  step 5 10 "Tune PHP-FPM (basic safe defaults)"
  sed -i 's/^;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/' /etc/php/8.3/fpm/php.ini
  sed -i 's/^memory_limit = .*/memory_limit = 256M/' /etc/php/8.3/fpm/php.ini
  sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 64M/' /etc/php/8.3/fpm/php.ini
  sed -i 's/^post_max_size = .*/post_max_size = 64M/' /etc/php/8.3/fpm/php.ini
  sed -i 's/^max_execution_time = .*/max_execution_time = 120/' /etc/php/8.3/fpm/php.ini

  systemctl restart php8.3-fpm
}

setup_redis(){
  step 6 10 "Redis: unix socket + permissions (secure and fast)"
  sed -i 's/^# unixsocket .*/unixsocket \/run\/redis\/redis-server.sock/' /etc/redis/redis.conf
  sed -i 's/^# unixsocketperm .*/unixsocketperm 770/' /etc/redis/redis.conf
  sed -i 's/^supervised .*/supervised systemd/' /etc/redis/redis.conf
  systemctl restart redis-server

  usermod -aG redis www-data
}

setup_nginx(){
  step 7 10 "Nginx vhost for WordPress"
  mkdir -p "${WEBROOT}/public"
  chown -R www-data:www-data "${WEBROOT}"
  chmod 0755 "${WEBROOT}"

  cat > /etc/nginx/snippets/wordpress-common.conf <<'NG'
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt  { allow all; log_not_found off; access_log off; }
location ~* \.(css|gif|ico|jpeg|jpg|js|png|svg|webp|woff2?)$ {
  expires 30d;
  add_header Cache-Control "public, max-age=2592000";
  access_log off;
}
location ~* \.(zip|gz|tgz|rar|bz2|7z)$ { deny all; }
location ~* /(wp-config\.php|readme\.html|license\.txt) { deny all; }
NG

  cat > /etc/nginx/sites-available/"${DOMAIN}".conf <<NG
server {
  listen 80;
  server_name ${DOMAIN} www.${DOMAIN};

  root ${WEBROOT}/public;
  index index.php index.html;

  access_log /var/log/nginx/${DOMAIN}.access.log;
  error_log  /var/log/nginx/${DOMAIN}.error.log warn;

  include /etc/nginx/snippets/wordpress-common.conf;

  location / {
    try_files \$uri \$uri/ /index.php?\$args;
  }

  location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_read_timeout 120;
  }
}
NG

  ln -sf /etc/nginx/sites-available/"${DOMAIN}".conf /etc/nginx/sites-enabled/"${DOMAIN}".conf
  rm -f /etc/nginx/sites-enabled/default || true
  nginx -t
  systemctl reload nginx
}

install_wp(){
  step 8 10 "Install WordPress via WP-CLI"
  sudo -u www-data wp core download --path="${WEBROOT}/public" --locale=ru_RU
  sudo -u www-data wp config create --path="${WEBROOT}/public" \
    --dbname="${DB_NAME}" --dbuser="${DB_USER}" --dbpass="${DB_PASS}" --dbhost=localhost \
    --dbcharset=utf8mb4 --dbcollate=utf8mb4_unicode_ci

  sudo -u www-data wp core install --path="${WEBROOT}/public" \
    --url="https://${DOMAIN}" --title="${DOMAIN}" \
    --admin_user="${WP_ADMIN_USER}" --admin_password="${WP_ADMIN_PASS}" --admin_email="${WP_ADMIN_EMAIL}"

  chmod 640 "${WEBROOT}/public/wp-config.php"
}

enable_redis_wp(){
  step 9 10 "Enable Redis object cache in WordPress"
  sudo -u www-data wp plugin install redis-cache --activate --path="${WEBROOT}/public"

  cat >> "${WEBROOT}/public/wp-config.php" <<'PHP'

define('WP_REDIS_PATH', '/run/redis/redis-server.sock');
define('WP_REDIS_SCHEME', 'unix');
define('WP_REDIS_DATABASE', 0);
define('WP_CACHE', true);
PHP

  sudo -u www-data wp redis enable --path="${WEBROOT}/public" || true
}

ssl(){
  step 10 10 "Issue Let's Encrypt certificate and enable HTTPS"
  certbot --nginx -d "${DOMAIN}" -d "www.${DOMAIN}" --non-interactive --agree-tos -m "${EMAIL}" --redirect
  systemctl reload nginx
}

checks(){
  log "Checks"
  echo "Domain: ${DOMAIN}"
  echo "Webroot: ${WEBROOT}/public"
  echo "DB: ${DB_NAME}"
  echo "DB user: ${DB_USER}"
  echo "DB pass: ${DB_PASS}"

  echo
  echo "Ports:"
  ss -lntp | egrep ':80|:443|:3306|:6379' || true

  echo
  echo "Nginx:"
  nginx -t

  echo
  echo "PHP-FPM:"
  systemctl is-active php8.3-fpm && php -v | head -n 1

  echo
  echo "Redis:"
  systemctl is-active redis-server && redis-cli ping

  echo
  echo "HTTP check:"
  curl -I "http://127.0.0.1" 2>/dev/null | head -n 1 || true

  echo
  echo "HTTPS check:"
  curl -kI "https://${DOMAIN}" 2>/dev/null | head -n 1 || true
}

need_root
ask
sys_prep
install_stack
secure_mariadb
tune_php
setup_redis
setup_nginx
install_wp
enable_redis_wp
ssl
checks

log "Done. Open https://${DOMAIN}/wp-admin"
BASH

chmod +x /root/wp-nginx-phpfpm-redis.sh
/root/wp-nginx-phpfpm-redis.sh

После выполнения вы получаете готовый WordPress на HTTPS, Redis object cache активирован, базовый firewall включён, и всё проверено командами в конце. Если хотите быстрее и без риска “что-то упустил”, проще заказать VPS с преднастройкой WordPress + Nginx + PHP-FPM + Redis, а миграцию и перенос домена мы закроем бесплатно, вы просто дадите доступы и получите готовый сайт.

Как проверить, что Redis реально работает, а не “просто установлен”

Самая частая самообманка: Redis стоит, но WordPress в него не пишет. Проверка должна быть фактической.

Зайдите в админку WordPress, откройте инструменты Redis (плагин redis-cache добавит раздел) и проверьте статус “Connected”. С сервера проверьте сокет и запросы:

ls -l /run/redis/redis-server.sock
redis-cli ping
redis-cli info stats | egrep 'keyspace_hits|keyspace_misses'

Если hits растут при навигации по админке и фронту, объектный кеш работает.

Типовые ошибки и мгновенная правка

Если при установке SSL certbot ругается, что домен не резолвится, это не “проблема сертификата”, это DNS. Сначала проверьте:

dig +short A yourdomain.com

IP должен совпадать с сервером. Пока не совпадает, HTTPS не получите.

Если Nginx отдаёт 502 Bad Gateway, это почти всегда PHP-FPM socket или не тот путь. Быстрая проверка:

systemctl status php8.3-fpm --no-pager
ls -l /run/php/php8.3-fpm.sock
nginx -t

Если сокета нет, перезапустите php-fpm и проверьте, не забилась память.

Если WordPress просит права на запись и не ставит плагины, проверьте владельца webroot:

chown -R www-data:www-data /var/www/yourdomain.com
find /var/www/yourdomain.com -type d -exec chmod 755 {} \;
find /var/www/yourdomain.com -type f -exec chmod 644 {} \;

Если Redis не подключается, причина обычно в правах на сокет. Проверьте, что www-data в группе redis:

id www-data
getfacl /run/redis/redis-server.sock 2>/dev/null || true

И убедитесь, что в redis.conf включён unixsocket и unixsocketperm 770, после чего перезапустите redis-server.

Debian 12 и AlmaLinux 9: что меняется по шагам

На Debian 12 стек такой же, но PHP по умолчанию 8.2. Логика установки и конфиги идентичны, меняются пакеты и путь сокета php-fpm. Если вы не хотите сторонние репозитории, оставляйте PHP 8.2, для WordPress это нормально.

На AlmaLinux 9 чаще всего ставят Nginx из официальных репозиториев и PHP через Remi, чтобы получить актуальную 8.3. Если вы делаете продакшн на AlmaLinux и хотите тот же результат, лучше делать установку как управляемую услугу, потому что сочетание SELinux, firewalld и репозиториев обычно съедает время. В таких случаях проще арендовать VPS под Linux-стек там, где всё ставится быстро и предсказуемо, а AlmaLinux оставить для тех задач, где он реально нужен.

Апгрейд-траектория: от одного VPS до multi-node и HA

Когда у вас один сайт, этот стек работает на одном VPS отлично. Дальше рост почти всегда идёт по этапам.

Первый этап: вынос бэкапов на отдельный сервер. Бэкап на том же диске это самоуспокоение. Поставьте второй маленький VPS в другой локации и делайте ежедневные снапшоты и дампы туда.

Второй этап: вынос базы. Когда MariaDB начинает быть узким местом, перенос базы на отдельный сервер даёт максимальный эффект без переписывания приложения. Nginx+PHP остаются на веб-узле, Redis можно держать рядом с PHP, чтобы не ловить сетевую задержку.

Третий этап: два веб-узла за балансировщиком. Для этого вам нужен общий storage для uploads (объектное хранилище или shared FS), общий Redis, отдельная база и нормальная схема деплоя. Тут уже появляется смысл в multi-node и продуманной сети.

Когда пора переходить на выделенный сервер: когда вы упираетесь в IOPS и CPU, а не в “настройки”. Если нагрузка стабильная и высокая, dedicated часто выгоднее по цене владения и нервам, чем бесконечные апгрейды VPS.

Когда нужна подсеть IPv4 и ASN: если вы строите вокруг проектов инфраструктуру с большим количеством IP (прокси-сервисы, отдельные витрины, сегментация по клиентам, почтовые узлы), тогда отдельная адресация начинает быть инструментом управления риском и репутацией. В этот момент полезно, когда провайдер умеет сдавать IPv4, делать PTR/WHOIS и при необходимости помогать с LIR/ASN, чтобы вы не упирались в сетевые “не можем”.

Мини-FAQ

Redis обязателен или можно без него?

Без Redis WordPress тоже работает, но под нагрузкой и в админке вы быстрее упираетесь в базу. Redis это простой способ ускорить сайт без архитектурного рефакторинга.

Что важнее для скорости: Redis или кеш страниц?

Если трафик высокий, кеш страниц может дать больше, но Redis улучшает именно внутреннюю работу WordPress и снижает нагрузку на БД. В идеале используют оба, но начинают обычно с Redis и нормальной настройки PHP-FPM.

Можно ли ставить это на Windows Server?

Этот стек под Linux. На Windows имеет смысл только заходить в админку и управлять сайтом, а сам прод держать на Linux VPS.

Почему после включения Redis ничего не ускорилось?

Потому что Redis может не быть реально активирован в WordPress. Смотрите stats hits/misses и статус Connected, а не факт установки пакета.

Что самое частое, что ломает установку?

DNS и порты. Пока домен не указывает на сервер и 80/443 не доступны, SSL и нормальные редиректы не заработают.


Помог ли вам данный ответ?

« Назад

База знаний