Отдельная статья: WordPress на виртуальном хостинге и на VPS

Установить WordPress

Эта страница необязательна. Курсу WordPress не нужен, и каждый урок работает с небольшим сайтом на PHP, написанным вручную. Читайте дальше, только если вы уже пользуетесь WordPress или решили это сделать и хотите увидеть шаги, которые сайт на WordPress добавляет к тем, что уже описаны в уроках.

База данных — та же, что в уроках. Создайте example_db и example_user в панели на виртуальном хостинге или через MariaDB на VPS, точно как показывают урок 4 и урок 5. Затем WordPress нужны четыре значения: имя базы данных, пользователь базы, пароль и хост, а это localhost, когда база данных работает на той же машине. Установщик хранит их в wp-config.php как DB_NAME, DB_USER, DB_PASSWORD и DB_HOST.

Установить файлы можно двумя способами. На виртуальном хостинге в панели обычно есть WordPress в разделе приложений: выберите домен, папку и базу данных, и панель скачает и настроит всё сама. Вручную скачайте архив с wordpress.org, распакуйте его и загрузите содержимое папки wordpress в папку сайта, чтобы index.php и wp-admin/ лежали прямо в веб-корне. Откройте https://example.com/wp-admin/install.php и создайте аккаунт администратора.

wp-config.php выше веб-корня

Установщик пишет wp-config.php в веб-корень. В этом файле лежит пароль базы данных, поэтому его место — на уровень выше веб-корня, рядом с html/, где веб-сервер не может его отдать. WordPress ищет его и там, и в папке установки, поэтому перенос работает без других изменений. На VPS:

sudo mv /var/www/example.com/html/wp-config.php /var/www/example.com/wp-config.php

sudo chown example:example /var/www/example.com/wp-config.php

sudo chmod 600 /var/www/example.com/wp-config.php

Владельца тоже меняют: перенесённый файл сохраняет того, кого дал установщик, часто www-data, и когда урок 8 запустит PHP под example, сайт больше не сможет его прочитать.

На виртуальном хостинге перенесите файл на папку выше по SFTP: из www/example.com/ в www/. Сайт продолжит работать, а ошибка PHP больше не сможет напечатать файл или отдать его посетителю.

HTTPS и адрес сайта

WordPress хранит свой адрес в базе данных, поэтому перевод сайта на HTTPS — это две настройки, а не одна. После того как сертификат заработает, откройте Настройки, Общие и задайте и адрес WordPress, и адрес сайта равными https://example.com. Те же значения можно исправить в wp-config.php, который имеет приоритет над базой данных и который проще исправить, когда страницы администрирования перестали загружаться:

sudo vi /var/www/example.com/wp-config.php

define('WP_HOME', 'https://example.com'); define('WP_SITEURL', 'https://example.com');

Затем откройте сайт и поищите смешанное содержимое: картинку или таблицу стилей, которые всё ещё загружаются по http:// — браузер блокирует их на странице HTTPS, и тема выглядит сломанной. Обновите адрес в содержимом или используйте относительный путь.

Постоянные ссылки и try_files

WordPress отправляет каждый запрос, который не ведёт к настоящему файлу, в index.php. В Nginx блок сервера из урока 5 использует try_files $uri $uri/ =404;, что правильно для небольшого сайта и возвращает 404 для красивой постоянной ссылки. Замените эту строку для WordPress:

sudo vi /etc/nginx/sites-available/example.com

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

sudo nginx -t

sudo systemctl reload nginx

Затем выберите Название записи в разделе Настройки, Постоянные ссылки. На виртуальном хостинге с Apache ту же работу делает файл .htaccess, который WordPress пишет сам.

Загрузки и PHP в загрузках

WordPress пишет каждый загруженный файл в wp-content/uploads, поэтому PHP должен уметь туда писать. Пока урок 8 не даст сайту собственный пул, PHP работает под www-data; дайте этой группе запись:

sudo -u example mkdir -p /var/www/example.com/html/wp-content/uploads

sudo chgrp -R www-data /var/www/example.com/html/wp-content/uploads

sudo chmod -R g+w /var/www/example.com/html/wp-content/uploads

Фрагменты для Nginx ниже предполагают отдельный пул PHP-FPM из урока 8. Пока этого пула нет, сокет — unix:/run/php/php8.3-fpm.sock, сокет по умолчанию из урока 5.

Папка загрузок — ещё и место, где атакующий, нашедший дыру в загрузке, пытается оставить файл PHP. Откажитесь выполнять там PHP и поставьте правило до location PHP сайта:

sudo vi /etc/nginx/sites-available/example.com

location ~* ^/wp-content/uploads/.*\.php$ { deny all; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm-example.sock; }

Страница входа

/wp-login.php — страница, которую знает каждый бот. Ограничение частоты из урока 8 замедляет подбор, не блокируя человека, который один раз ошибся паролем:

sudo vi /etc/nginx/sites-available/example.com

location = /wp-login.php { limit_req zone=perip burst=5 nodelay; limit_req_status 429; include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm-example.sock; }

Двухфакторная аутентификация на аккаунте администратора — мера сильнее; ограничение лишь убирает шум.

Плагины, темы и обновления

unattended-upgrades обновляет Ubuntu, а не код внутри папки сайта. В панели администратора откройте Плагины и Темы и включите автоматические обновления для каждого плагина и каждой темы, которые вы оставляете; тогда WordPress ставит новые версии без вас. Удаляйте плагины и темы, которыми не пользуетесь, потому что неактивный плагин — всё ещё код на диске и всё ещё путь внутрь.

На сервере с WP-CLI та же работа — две команды. Запускайте их от пользователя сайта раз в неделю, из строки cron или вручную:

sudo -u example -H wp plugin update --all --path=/var/www/example.com/html

sudo -u example -H wp theme update --all --path=/var/www/example.com/html

Читайте вывод: плагин, который не обновляется, — плагин, который надо удалить или заменить.

xmlrpc.php и проверка базы данных

xmlrpc.php — старый интерфейс, которым пользуются некоторые настольные приложения и Jetpack. Если на вашем сайте его ничто не использует, закройте его в настройке сайта:

sudo vi /etc/nginx/sites-available/example.com

location = /xmlrpc.php { deny all; }

После переноса сайта и импорта базы данных проверьте, что записи приехали. Префикс таблиц по умолчанию — wp_; если сайт использовал другой, берите его имя:

sudo mariadb -e "SELECT COUNT(*) FROM example_db.wp_posts;"

+----------+ | COUNT(*) | +----------+ | 24 | +----------+

Тест

1 Где должен лежать wp-config.php?

  1. В веб-корне, рядом с index.php
  2. На уровень выше веб-корня, где WordPress тоже его ищет
  3. В /tmp
  4. В базе данных
Ответ

b) В файле лежит пароль базы данных, поэтому его нельзя отдавать по веб. WordPress ищет его в папке установки и на уровень выше.

2 Какая строка try_files заставляет постоянные ссылки WordPress работать?

  1. try_files $uri $uri/ =404;
  2. try_files $uri $uri/ /index.php?$args;
  3. try_files $uri /wp-login.php;
  4. try_files /index.php $uri;
Ответ

b) Красивая постоянная ссылка не соответствует файлу на диске, поэтому запрос идёт во фронт-контроллер. Простая версия с =404 правильна для небольшого сайта, написанного вручную.

3 Почему в wp-content/uploads отказываются выполнять PHP?

  1. Так загрузки быстрее
  2. Загруженный файл .php выполнился бы на сервере и стал веб-оболочкой
  3. Так экономится место на диске
  4. Так тема становится лучше
Ответ

b) В папке загрузок должны лежать картинки и документы и никогда код. Правило стоит до location PHP, потому что nginx использует первое подходящее регулярное выражение location.

4 После того как сертификат заработал, административная часть всё равно перенаправляет на http://. Что ещё не так?

  1. База данных лежит
  2. Адрес WordPress и адрес сайта всё ещё говорят http://
  3. Папка загрузок доступна только на чтение
  4. Запись PTR отсутствует
Ответ

b) WordPress хранит свой базовый адрес в базе данных. Задайте оба адреса равными https://example.com — в панели администратора или в wp-config.php.

5 Что делать с xmlrpc.php, если им не пользуется ни одно приложение?

  1. Открыть его всему миру
  2. Закрыть его в блоке сервера
  3. Удалить базу данных
  4. Перенести его в загрузки
Ответ

b) Это старый интерфейс с долгой историей злоупотреблений. Если он никому не нужен, правило deny all убирает риск.

Автор статьи: Arthur Isaev