Ручная установка WordPress - это четыре вещи: файлы в корне веб-каталога, база данных с пользователем, который может в неё писать, файл wp-config.php с этими учётными данными и восемью случайными солями, и один заход на /wp-admin/install.php. При нормальном соединении вся работа занимает около десяти минут, и девять из них уходят на ожидание загрузки.
Почти всё, что идёт не так потом, сводится к одной из четырёх ошибок: хост базы данных не localhost, файлы принадлежат не тому пользователю, адрес сайта в базе не совпадает с тем, который вводят люди, или PHP слишком старый для темы. В этом руководстве сначала выполняется установка, а затем каждая из этих ошибок разбирается как следует, потому что сама установка - это лёгкая половина.
Что нужно перед началом#
WordPress намеренно нетребователен. Собственная рекомендация проекта - PHP 7.4 или новее и база класса MySQL 8.0 или MariaDB 10.5, с доступным HTTPS. Настоящий минимум ниже, но плагин, написанный в этом году, будет рассчитывать на PHP 8, поэтому считайте порогом 8.1, а разумным выбором - 8.2 или 8.3. Не выбирайте версию PHP новее той, на которой протестированы ваша тема и платёжные плагины: именно это обновление стабильно ломает магазин.
| Требование | Что проверить | Примечания |
|---|---|---|
| PHP | 8.1-8.3 | 7.4 ещё работает, но на нём ничего нового не тестируется |
| База данных | семейство MySQL 8 / MariaDB 10.5 | Одна пустая база, один пользователь с полными правами на неё |
| Расширения PHP | json, mysqli, curl, mbstring, zip, dom, openssl, а также gd или imagick | json и mysqli обязательны, без остальных функции ломаются тихо |
| Диск | 1 ГБ для начала | Ядро занимает около 60 МБ; растёт медиатека |
| Память | 512 МБ-1 ГБ для небольшого сайта | См. сколько RAM нужно WordPress |
| HTTPS | Сертификат на итоговое имя хоста | Настройте до установки, а не после |
Перед тем как что-либо набирать, нужно знать о хостинге ещё две вещи: от какого пользователя работает PHP и есть ли у вас shell-доступ. Первое определяет права на файлы. Второе решает, можно ли использовать WP-CLI или всю работу придётся делать через файловый менеджер и phpMyAdmin. На хостинге с панелью обычно доступен только второй путь - консоль там показывает вывод самого веб-сервера, а не даёт shell для входа, - и этого вполне достаточно.
Разместите файлы на сервере#
Официальная загрузка - https://wordpress.org/latest.zip (или latest.tar.gz). Никогда не устанавливайте из копии, которую вам прислали, из «nulled»-сборки или из архива, найденного в поисковой выдаче: внедрённый код в каталоге тем - самый частый способ, которым сайт начинает жизнь уже взломанным.
Если есть shell-доступ:
$ cd /var/www/example.com$ wget https://wordpress.org/latest.tar.gz$ tar -xzf latest.tar.gz --strip-components=1$ rm latest.tar.gz--strip-components=1 - то, что чаще всего упускают. Внутри архива лежит папка верхнего уровня wordpress/, и без этого флага вы получите /var/www/example.com/wordpress/index.php и сайт, который отвечает только по адресу example.com/wordpress. Такая структура допустима, если она вам нужна, но выбирайте её осознанно.
Без shell-доступа загрузите latest.zip через файловый менеджер и распакуйте на месте: файловый менеджер, распаковывающий архивы на стороне сервера, превращает загрузку 2000 мелких файлов общим объёмом 60 МБ в загрузку одного файла, а это примерно в двадцать раз быстрее, чем через SFTP. Затем перенесите содержимое wordpress/ на уровень выше и удалите пустую папку.
Файлы должны оказаться в каталоге, который раздаёт веб-сервер. Обычно он называется public_html, www, htdocs или public. Если загрузить в другой, вы получите листинг каталога или страницу по умолчанию, и ничего, что вы сделаете с wp-config.php, этого не изменит. О том, как получить учётные данные и найти корень, рассказано в статье SFTP и файловый менеджер.
Создайте базу данных и пользователя#
WordPress сам базу не создаст. Ему нужна уже существующая база и пользователь с полными правами на неё, и только на неё. Если у вас есть панель управления с разделом баз данных, пользуйтесь ей: сгенерированные ею учётные данные лучше тех, что придумали бы вы. Если у вас есть SQL-доступ:
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;CREATE USER 'wp_site'@'%' IDENTIFIED BY 'a-long-random-password';GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_site'@'%';FLUSH PRIVILEGES;Три детали стоят лишних секунд:
- `utf8mb4`, а не `utf8`. Старая кодировка
utf8в этом семействе хранит по три байта на символ и не вмещает emoji и ряд письменностей. Запись, обрывающаяся на полуслове там, где стоял emoji, - это как раз оно, а исправление задним числом означает конвертацию collation в каждой таблице. - Один пользователь на сайт.
GRANT ALL ON wordpress.*не даёт этому пользователю ничего за пределами его базы. Общий пользователь на три сайта означает, что один взломанный плагин добирается до всех трёх. - `ALL PRIVILEGES` - не роскошь. WordPress нужны
ALTERиCREATEпри установке и при каждом обновлении, добавляющем таблицу. Права только на чтение и запись позволят установить сайт, а затем сломаются на первом же плагине со своей схемой.
Прежде чем идти дальше, запишите четыре значения: имя базы, пользователь, пароль и хост. Хост - то, в чём чаще всего ошибаются. Это localhost только тогда, когда база работает на той же машине, что и PHP. В остальных случаях это имя хоста, и если порт нестандартный, он дописывается в конец: DB_HOST принимает db.internal.example:3307.
В RE:NODE тарифы для сайтов включают два слота баз данных, создаваемых из панели. Панель сама генерирует хост, пользователя, имя базы и пароль, а кнопка Open in phpMyAdmin входит по одноразовому токену, который истекает через шестьдесят секунд, так что пароль никогда не набирается в форме браузера. Скопируйте эти четыре значения прямо в wp-config.php. Та же панель разобрана с другой стороны в руководстве по импорту и экспорту в phpMyAdmin - оно пригодится, когда вы переносите уже существующий сайт.
wp-config.php строка за строкой#
Переименуйте wp-config-sample.php в wp-config.php и отредактируйте. Оставляйте файл в корне сайта, если не знаете, зачем его переносить, и никогда не держите рядом копию с именем wp-config.php.bak или wp-config.old: такие файлы отдаются как обычный текст и выдают пароль от базы.
define( 'DB_NAME', 'wordpress' );define( 'DB_USER', 'wp_site' );define( 'DB_PASSWORD', 'a-long-random-password' );define( 'DB_HOST', 'localhost' );define( 'DB_CHARSET', 'utf8mb4' );define( 'DB_COLLATE', '' );$table_prefix = 'wp_';define( 'WP_DEBUG', false );define( 'WP_DEBUG_LOG', false );define( 'WP_DEBUG_DISPLAY', false );define( 'FS_METHOD', 'direct' );define( 'DISALLOW_FILE_EDIT', true );define( 'WP_MEMORY_LIMIT', '256M' );define( 'WP_ENVIRONMENT_TYPE', 'production' );Что на самом деле делает каждая из этих строк:
- `DB_COLLATE` должен оставаться пустым. WordPress сам выбирает правильную collation для кодировки; если задать её вручную, сайты в итоге получают смешанные collation, которые ломают join после миграции.
- `$table_prefix` по умолчанию равен
wp_. Его смену часто выдают за меру безопасности, но это не так: всё, что может читать ваши таблицы, за секунды прочтёт префикс из аналоговwp_options. По-настоящему он полезен для размещения двух сайтов в одной базе, и это единственная причина его менять. - `WP_DEBUG` в production всегда выключен. Когда он понадобится, установите
WP_DEBUGиWP_DEBUG_LOGвtrue, аWP_DEBUG_DISPLAYвfalse: тогда ошибки пишутся вwp-content/debug.log, а не показываются посетителям, которым ваши пути к файлам ни к чему. - `FS_METHOD` со значением `direct` избавляет от запроса FTP-учётных данных при каждой установке плагина. Работает только если пользователь PHP может писать в
wp-content, о чём говорится в разделе о правах ниже. - `WP_MEMORY_LIMIT` по умолчанию равен
40Mдля публичной части, аWP_MAX_MEMORY_LIMIT-256Mдля страниц администрирования.40Mдля современной темы мало. Эта константа может только понижать или повышать значение в пределах того, что разрешает сам PHP, так что это лишь половина дела; вторая половина - настройки php.ini, которые важны. - `WP_ENVIRONMENT_TYPE` сообщает плагинам, где они работают: в production, staging, разработке или локально. Выставьте его правильно на каждой копии сайта, и плагины backup и платежей, которые его учитывают, перестанут рассылать письма клиентам с вашего staging-клона.
Ещё две настройки понадобятся со временем, но не во время установки:
define( 'WP_HOME', 'https://example.com' );define( 'WP_SITEURL', 'https://example.com' );Они переопределяют то, что хранится в базе. Это самое быстрое лекарство для сайта, который перенаправляет на неверное имя хоста, и причина того, что клонированный staging-сайт отправляет посетителей обратно на production. Кроме того, они делают поля на экране Settings доступными только для чтения, и это скорее достоинство.
Соли и то, что они на самом деле защищают#
В образце файла есть восемь констант-заглушек: AUTH_KEY, SECURE_AUTH_KEY, LOGGED_IN_KEY, NONCE_KEY и парные AUTH_SALT, SECURE_AUTH_SALT, LOGGED_IN_SALT и NONCE_SALT. Это не пароли, и вы нигде не набираете их вручную. WordPress использует их для подписи cookie входа и nonce в формах администрирования.
Если оставить put your unique phrase here, любую cookie сессии, выданную вашим сайтом, может подделать каждый, кто читал файл-образец, а это все. Сгенерируйте настоящие:
$ curl https://api.wordpress.org/secret-key/1.1/salt/Этот адрес возвращает восемь готовых строк define(). Вставьте их поверх заглушек. Если у машины нет исходящего доступа, подойдут любые восемь строк из 64 случайных символов: им нужно быть лишь длинными, случайными и секретными.
Владелец файлов и права доступа#
Здесь ручные установки чаще всего застревают, а верный ответ зависит от одного: от какого пользователя работает PHP. Здесь назовём его www-data; на вашем хосте это может быть nginx, apache или отдельный пользователь сайта.
| Что | Режим | Зачем |
|---|---|---|
| Каталоги | 755 | Веб-сервер должен иметь возможность их обходить |
| Файлы | 644 | Читаются сервером, записываются владельцем |
wp-config.php | 640 или 600 | Никому больше на машине не нужен ваш пароль от базы |
wp-content/uploads | 755, владелец - пользователь PHP | Иначе загрузка медиафайлов не работает |
$ cd /var/www/example.com$ chown -R www-data:www-data .$ find . -type d -exec chmod 755 {} \;$ find . -type f -exec chmod 644 {} \;$ chmod 640 wp-config.phpНикогда не используйте 777. Этот совет есть на сотне форумных веток, и он означает «любой на этой машине может переписать этот файл», а на общем оборудовании к «любым» относится и соседний сайт. Если загрузка не работает при 755, проблема в владельце, а не в режиме: каталог принадлежит не тому пользователю, обычно потому, что файлы были загружены по SFTP от вашей личной учётной записи, а не от пользователя PHP.
На панели с контейнерами внутри контейнера один пользователь, поэтому вопрос владельца перед вами не стоит: что бы ни записал файловый менеджер, PHP сможет прочитать и обновить. Это одно из немногих настоящих упрощений панели по сравнению с голым виртуальным сервером, и поэтому FS_METHOD со значением direct работает там без лишних раздумий.
Запустите установщик#
Откройте https://example.com/wp-admin/install.php. Если WordPress достаёт до базы, он спросит четыре вещи.
- Название сайта. Можно изменить позже, без последствий.
- Имя пользователя. Не
admin, не название сайта и не ваше имя, если оно же указано как имя автора. Автоматические попытки входа перебирают ровно эти три варианта. - Пароль. Используйте сгенерированный и положите его в менеджер паролей.
- Email. Настоящий почтовый ящик, который вы читаете. Сюда приходят сбросы паролей и уведомления о критических ошибках, а у сайта, на чей адрес администратора письма возвращаются, нет пути к восстановлению.
Есть ещё флажок Discourage search engines. Он выставляет одну опцию и добавляет заголовок noindex; для сайта, который вы ещё делаете, это правильно, а если он остался включённым после запуска, - катастрофа. Проверьте Settings, затем Reading, в день запуска. Сайт, который «не ранжируется» через месяц после запуска, в трети случаев имеет этот флажок включённым.
Установщик создаёт таблицы, записывает первого пользователя и оставляет вас в /wp-admin. Потом ничего не нужно убирать: install.php остаётся, а повторный запуск на установленном сайте просто показывает сообщение.
Если у вас есть shell-доступ, WP-CLI делает ту же работу двумя командами, и такой вариант намного удобнее для сценариев:
$ wp core config --dbname=wordpress --dbuser=wp_site --dbpass='...' --dbhost=localhost$ wp core install --url=https://example.com --title="Example" \ --admin_user=owner --admin_email=you@example.com --prompt=admin_passwordПостоянные ссылки, HTTPS и адрес сайта#
Три настройки определяют, будет ли сайт вести себя как надо. Делайте их в таком порядке.
Постоянные ссылки. Settings, затем Permalinks, затем Post name, затем Save: именно сохранение перегенерирует правила. В Apache это записывает блок в .htaccess, а если файл недоступен для записи, WordPress выводит правила, чтобы вы вставили их сами. В nginx нет .htaccess; переписывание живёт в конфигурации сервера и выглядит так:
location / { try_files $uri $uri/ /index.php?$args;}Если все URL, кроме главной страницы, возвращают 404, причина в этом: правила нет, либо вы на nginx и ждёте, что .htaccess что-то сделает. На управляемом хостинге правило обычно уже стоит, и вы его никогда не видите.
HTTPS. Добейтесь работы сертификата до установки, чтобы адрес сайта был https:// с первой строки, записанной в базу. Смена позже означает поиск с заменой по всей базе, а это уже глава из статьи перенос WordPress на новый хостинг, а не настройка.
Заголовок прокси. Когда TLS завершается перед PHP - на любом обратном прокси, на любом CDN, - PHP не видит зашифрованный запрос, поэтому WordPress строит URL с http://, перенаправляет на них, его возвращают обратно, и браузер сообщает о цикле перенаправлений. Исправление вносится в wp-config.php выше строки require_once ABSPATH . 'wp-settings.php'; в конце файла:
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) { $_SERVER['HTTPS'] = 'on';}Добавляйте его, только если прокси, который вы контролируете, действительно выставляет этот заголовок, иначе вы позволите тривиально подделывать HTTPS. Тарифы для сайтов RE:NODE включают слот прокси: направьте запись A на адрес, показанный на этой вкладке, и сертификат будет выпущен и продлён автоматически, а настоящий адрес посетителя придёт в X-Forwarded-For. Остальные заголовки разобраны в статье что делает обратный прокси, а DNS-часть - в статье ваш домен и его сертификат.
Когда не работает#
Error establishing a database connection. Одно из четырёх значений неверно либо сервер базы данных недоступен из PHP. Сначала проверьте учётные данные в phpMyAdmin: если там они работают, а в WordPress нет, разница почти всегда в DB_HOST, и почти всегда это localhost там, где нужно настоящее имя хоста.
Белый экран. Фатальная ошибка PHP при выключенном выводе. Установите WP_DEBUG и WP_DEBUG_LOG в true, перезагрузите страницу, прочтите последние строки wp-content/debug.log. В девяти случаях из десяти там названы плагин или функция, а причина - несовпадение версии PHP или исчерпанный лимит памяти.
Allowed memory size exhausted. PHP упёрся в memory_limit. Повысьте WP_MEMORY_LIMIT, а если ничего не изменилось, значит собственный лимит PHP ниже, и поднимать нужно сначала его.
The upload failed to write to disk, или папка загрузок недоступна для записи. Владелец wp-content/uploads или заполненный диск. Прежде чем менять права, проверьте свободное место.
A file exceeds the upload_max_filesize directive. Это лимит PHP, а не WordPress. Нужно поднять upload_max_filesize и post_max_size вместе, а возможно, и лимит размера тела запроса на прокси перед сайтом.
Предупреждения о смешанном содержимом. Страница пришла по HTTPS и запросила изображение по HTTP. URL хранятся в базе со старой схемой; исправьте их инструментом поиска с заменой, который понимает сериализованные данные, и никогда не обычным SQL REPLACE.
Цикл перенаправлений сразу после установки. Случай с заголовком прокси, описанный выше, либо WP_HOME и WP_SITEURL расходятся с именем хоста в адресной строке, в том числе когда версии с www и без www считаются разными сайтами.
FAQ#
Нужен ли установщик в один клик?
Нет, и есть довод в пользу того, чтобы его не использовать. Ручная установка занимает десять минут, кладёт на диск именно ту версию, которую вы выбрали, и не оставляет ничего, чего не положили вы сами. Установщики часто закрепляют версию, добавляют свои обязательные плагины или создают пользователя базы с более широкими правами, чем нужно сайту.
Можно ли установить WordPress в подпапку, а отдавать из корня?
Да. Положите файлы в /wordpress, задайте WP_SITEURL как https://example.com/wordpress, а WP_HOME как https://example.com, затем скопируйте index.php и .htaccess в корень и измените в index.php единственную строку, подключающую wp-blog-header.php, чтобы она указывала в подпапку. Это держит корень в порядке, но мерой безопасности не является.
Как заставить WordPress отправлять почту?
На практике не с веб-сервера. Почта с IP хостинга без согласованных SPF, DKIM и DMARC попадает в спам или отклоняется сразу, а многие хостеры, включая RE:NODE, почту не запускают вовсе. Установите SMTP-плагин и направьте его на провайдера транзакционной почты или на собственный ящик. Почему записи важны даже тогда, объяснено в статье SPF, DKIM и DMARC простыми словами.
Стоит ли менять префикс таблиц wp_?
Только чтобы разместить несколько сайтов в одной базе. Как мера безопасности он ничего не даёт: любой код, способный делать запросы к вашим таблицам, может и перечислить их. Смена на работающем сайте означает переименование каждой таблицы и правку двух строк в таблицах options и user-meta, а если сделать это наполовину, админка сломается.
Что сделать сразу после первого входа?
Удалите ненужную тему по умолчанию и все поставляемые плагины, которыми не будете пользоваться, настройте постоянные ссылки, снимите флажок поисковых систем, если ставили его, добавьте вторую учётную запись администратора, через которую можно восстановить доступ, и сделайте backup до установки первого же плагина. Затем прочтите укрепление безопасности WordPress.
Сколько ресурсов нужно свежему сайту на WordPress?
Тариф с 1 ГБ и 0,5 vCPU спокойно тянет небольшой сайт-визитку. Память становится ограничением, когда одновременно растут число плагинов и число рабочих процессов PHP, а не когда растёт трафик, и поэтому сайт, перегруженный плагинами, с пятьюдесятью посетителями в день может требовать больше памяти, чем лёгкий сайт с пятью тысячами.




Комментарии
Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.