Большинство людей устанавливают WordPress легкий Мы собираемся установить его. верно способом. безопасным, повторяемым и, что самое главное, простым.
WordPress взламывают не потому, что он плохой. Его взламывают, потому что люди экономят на удобстве.
WordPress поддерживает более трети интернета, и хотя он славится своей пятиминутной установкой, правда в том, что большинство людей настраивают его так, что в будущем остаются уязвимые места для злоумышленников и головные боли. Правильная установка — это не усложнение, а закладывание прочного фундамента для производительности, безопасности и стабильности. Спешно созданная или скопированная конфигурация часто скрывает опасные уязвимости, которыми умеют пользоваться боты и сканеры. Уделяя несколько дополнительных минут правильной настройке базы данных, защите PHP и использованию защищенной конфигурации Nginx, вы защищаете себя от проблем, которые могут привести к отключению целых сайтов. Представьте это как строительство дома: каждый может возвести четыре стены, но только тщательно построенный дом выдержит шторм. Это руководство шаг за шагом рассмотрит весь процесс, чтобы вы смогли воспользоваться всеми преимуществами WordPress, не совершая типичных ошибок.
Ладно, давайте пропустим болтовню.
Что мы будем использовать?
- Система: рекомендуется Ubuntu 22.04 или 24.04
- База данных: MariaDB для производительности и стабильности
- Веб-сервер: NGINX для производительности и стабильности
- Кэширование: Redis — высокопроизводительное хранилище данных в памяти
- SSL: CertBot
- Дополнительно: автоматическая перезагрузка Nginx, сжатие Brotli, безопасное ведение журнала, сокрытие электронной почты
Ubuntu стала моей любимой серверной операционной системой с тех пор, как Red Hat «убила» CentOS. Простота использования, подробная документация, мощная поддержка сообщества и широкий выбор актуальных пакетов программного обеспечения делают её идеальным выбором как для новичков, так и для профессионалов. Она обеспечивает идеальный баланс между стабильностью и современными функциями, что как раз то, что нужно для такой популярной платформы, как WordPress.
Подготовьте свой сервер
Давайте подготовим стек. Начнём с добавления проверенного PPA Ондрея, который поддерживает актуальные сборки PHP и Nginx для Ubuntu. Затем мы установим Nginx, MariaDB, Redis, acl и все пакеты PHP 8.4, которые вам действительно понадобятся для приложений WordPress.
sudo apt install python-software-properties
sudo add-apt-repository ppa:ondrej/nginx
sudo add-apt-repository ppa:ondrej/php
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx nginx-extras mariadb-server unzip curl redis-server imagemagick acl less file
sudo apt install -y php8.4-fpm php8.4-mysql \
php8.4-curl php8.4-xml php8.4-zip php8.4-gd php8.4-mbstring php8.4-bcmath \
php8.4-intl php8.4-soap php8.4-imagick php8.4-cli# Allow NGINX in the Firewall (For this instance UFW)
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enableКак всегда, я рекомендую отключить вход по SSH с правами root через ssh_config, а также отключить аутентификацию по паролю и использовать SSH-ключи из соображений безопасности.
Настройка базы данных
Когда вы впервые устанавливаете MariaDB, это похоже на переезд в новую квартиру: двери открыты, запасные ключи лежат на столе, а на двери лежит коврик с надписью «Добро пожаловать, хакер». mysql_secure_installation существует сценарий, закрывающий эти двери, прежде чем кто-либо войдет.
sudo mysql_secure_installationSwitch to unix_socket authentication [Y/n] N
Change the root password? [Y/n] As you wish
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] YСоздайте отдельную базу данных и пользователя для WordPress. Именно здесь будет храниться большая часть, если не все, ваши данные WordPres. Поэтому обязательно выберите надёжный пароль.
# Change the DB/User Names, Password as you wish
CREATE DATABASE wp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'VERY_STRONGPASS!';
GRANT ALL PRIVILEGES ON wp.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;Рекомендуемая настройка для повышения производительности и безопасности базы данных, Править /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
bind-address = 127.0.0.1
# Adjust as you like.
# ~50-70% of RAM on DB-only servers
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_method = O_DIRECT
max_connections = 200
query_cache_size = 0
query_cache_type = 0sudo systemctl restart mariadbОптимизация PHP для WordPress
Далее мы изменим несколько ключевых настроек PHP. Эти небольшие изменения существенно повышают стабильность и безопасность, особенно для сайтов WordPress с высокой посещаемостью.
Открыть /etc/php/8.4/fpm/php.ini или 8.4 и раскомментируйте/добавьте следующее
memory_limit = 256M
; These values are kinda low. So adjust as you like
upload_max_filesize = 64M
; Post_Max_size always needs to be the same as file max upload or higher. Never lower
post_max_size = 64M
max_execution_time = 120
; Security: prevent path-info exploits
cgi.fix_pathinfo = 0
expose_php = Off
; Enable OPcache, dramatically improves performance
zend_extension=opcache
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1# Reload PHP-fpm
sudo systemctl reload php8.4-fpm # or 8.4Загрузите WordPress через WP-CLI
Вместо того, чтобы каждый раз управлять WordPress через браузер, вы можете использовать WP-CLI, оболочка, позволяющая устанавливать, обновлять и управлять WordPress с помощью простых команд терминала. Она незаменима для разработчиков, создателей скриптов автоматизации и всех, кто управляет несколькими сайтами. Давайте установим WP-CLI.
# Login as a user other than the root, for better security
sudo -u ubuntu -i
curl -sS -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x /usr/local/bin/wp
# You shoulod see WP-Cli Version now
wp --infoЕсли возникла ошибка разрешения или версия не отображается, используйте следующую команду. В противном случае пропустите её.
curl -fsSL https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
| sudo tee /usr/local/bin/wp >/dev/null
sudo chmod +x /usr/local/bin/wpЗатем создайте каталог, в котором будут храниться файлы WordPress. Это ваш веб-корень, откуда Nginx будет раздавать контент. Вы можете дать ему любое имя и разместить его в любом месте системы, но убедитесь, что веб-сервер имеет право на запись. www-data.
mkdir -p /var/www/blog
sudo chown -R www-data:www-data /var/www/blog
cd /var/www/blogПосле завершения настройки и создания базы данных пришло время запустить WordPress. Вместо того, чтобы загружать его вручную, мы воспользуемся WP-CLI, быстрее, чище и идеально подходит для автоматизированных настроек.
Загрузка и настройка: Вы можете продолжить установку с помощью браузера после wp core download --locale=en_US или CLI (ниже).
sudo -u www-data wp core download --locale=en_US
# The DB/User/Password you created earlier
sudo -u www-data wp config create --dbname=wp --dbuser=wpuser --dbpass=VERY_STRONGPASS! --dbhost=localhost --dbprefix=wp_
# Do not use default username: admin, Choose something more secure
sudo -u www-data wp core install --url="https://example.com" --title="My Site" --admin_user="myusername" --admin_password="ANOTHERSTRONGPASS" --admin_email="me@example.com"После установки WordPress пора заблокировать его файлы. Цель проста: веб-сервер (www-data) должен быть в состоянии читать и писать только то, что действительно необходимо, и ничего больше. Это значительно снижает вероятность того, что злоумышленник внедрит или отредактирует файлы с помощью эксплойта плагина или неправильно настроенной загрузки.
find /var/www/blog -type d -exec chmod 755 {} \;
find /var/www/blog -type f -exec chmod 644 {} \;
rm /var/www/blog/wp-config-sample.php
rm /var/www/blog/readme.htmlА теперь самый конфиденциальный файл из всех: wp-config.php. Он хранит ваши учетные данные и ключи базы данных, поэтому относитесь к нему как к паролю root. Затем очистите историю сеанса, поскольку в оболочке мы использовали пароль в виде простого текста.
мы делаем wp-config.php читается только www-dataи сверка с getfacl Проверьте правильность списка контроля доступа (ACL). Это гарантирует, что веб-сервер сможет прочитать файл для загрузки WordPress, но не сможет изменить или перезаписать его.
chown ubuntu:www-data /var/www/blog/wp-config.php
chown ubuntu:www-data /var/www/blog/wp-admin
chown ubuntu:www-data /var/www/blog/wp-includes
# WP-CONFIG should always have 600 (-rw-------) or 440 (-r--r-----+) permission
chmod 440 /var/www/blog/wp-config.php
sudo setfacl -m u:www-data:r /var/www/blog/wp-config.php
# ensure mask allows read
sudo setfacl -m m::r /var/www/blog/wp-config.php
getfacl /var/www/blog/wp-config.php
# https://developer.wordpress.org/advanced-administration/security/hardening/#file-permissions
# Clear Session Command History
history -cЗащитите и оптимизируйте WordPress
WordPress использует набор криптографических ключей и солей для защиты пользовательских сеансов и файлов cookie. Они делают практически невозможным перехват логина или повторное использование токенов аутентификации.
# Set unique salts & keys
sudo -u ubuntu wp config shuffle-saltsПрежде чем закончить, давайте добавим несколько дополнительных строк wp-config.php чтобы сделать работу WordPress более предсказуемой и безопасной.
Редактироватьwp-config.php и добавьте следующее чуть выше: «Вот и все, прекратите редактировать!»
# Disable file editing inside WP-Admin
define('DISALLOW_FILE_EDIT', true);
# Limit Revisions to 5
define('WP_POST_REVISIONS', 5);
# Disable WP cron (use system cron)
define('DISABLE_WP_CRON', true);
# Save/Exit the fileПоскольку ранее мы отключили внутренний cron WordPress, теперь мы заменим его полноценным системным cron-заданием. Это гарантирует своевременное выполнение запланированных задач, таких как публикация записей, отправка электронных писем или запуск обновлений, даже при низкой посещаемости вашего сайта.
sudo -u www-data crontab -e
# Append the following at the end of the file
* * * * * /usr/local/bin/wp --path=/var/www/blog cron event run --due-now --quiet# To list upcoming scheduled events
sudo -u www-data wp cron event list
# To run all pending (due) cron events immediately
sudo -u www-data -H wp cron event run --due-nowНастройка веб-сервера NGINX
Теперь, когда WordPress установлен и защищён, давайте разместим его на подходящем веб-сервере. Мы будем использовать Nginx, высокопроизводительная и легкая альтернатива Apache, которая обслуживает трафик вашего сайта, поддерживает SSL и даже может выступать в качестве балансировщика нагрузки, если вы планируете масштабировать систему в будущем.
Для начала давайте настроим Certbot для выпуска бесплатного SSL-сертификата | API-КЛЮЧ CloudflareЕсли вы не используете Cloudflare, найдите своего провайдера здесь или используйте метод HTTP.
Иметь в виду что "блог.conf” можно переименовать как угодно. На случай, если непонятно.
sudo apt install -y certbot python3-certbot-dns-cloudflare
sudo mkdir -p /etc/letsencrypt
echo "dns_cloudflare_api_token = YOUR_API_TOKEN_HERE" > /etc/.cloudflare.ini
sudo chmod 600 /root/.cloudflare.ini# Issue a Certificate
sudo certbot certonly -d example.com -d "*.example.com" \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/.cloudflare.ini \
--key-type rsa \
--rsa-key-size 2048 \
--agree-tos \
--force-renewal\
--no-eff-email\
--email YOUR@EMAIL.COM
# The cert output should be in /etc/letsencrypt/live/example.com/Теперь настроим NGINX. Файлы конфигурации: В моем Github. Не забудь чтобы изменить «example.com» внутри файлов на ваш домен и путь к SSL-сертификату.
nano /etc/nginx/nginx.conf
# Apend/Modify the following inside http{} block
http2 on;
ssl_protocols TLSv1.2 TLSv1.3; # Drop v1, v1.1 - Keep only 1.2 & 1.3cd /etc/nginx/sites-available/
wget -O /etc/nginx/sites-available/blog.conf https://raw.githubusercontent.com/abdessalllam/cloud-setup/refs/heads/main/wordpress/blog.conf
# Disable directory browsing
echo "autoindex off;" > /etc/nginx/snippets/no-autoindex.conf
# Enable the Website and Reload NGINX
sudo ln -s /etc/nginx/sites-available/blog.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginxВключить поддержку Cloudflare
Если вы будете использовать Cloudflare с обратным прокси-сервером, нам нужно добавить Диапазоны CF чтобы убедиться, что наш сервер получает реальный IP-адрес посетителя. Последние обновления Cloudflare IPv4 – IPv6 Диапазоны
То же самое можно применить и к другим балансировщикам нагрузки. Все, что вам нужно сделать, это изменить файл ниже, включив «только» их диапазоны IP-адресов.
wget -O /etc/nginx/conf.d/realip.conf https://raw.githubusercontent.com/abdessalllam/cloud-setup/refs/heads/main/wordpress/realip.conf
sudo nginx -t && sudo systemctl reload nginxЭто важно, особенно если вы собираетесь использовать аналитику и/или плагин WAF для своего WordPress.
Все файлы .conf в conf.d будут автоматически включены по умолчанию.
(Необязательно) Создайте файл ip.php в папке /var/www/blog и проверьте, получает ли Nginx реальный IP-адрес. (Удалите его после завершения)
<?php
header('Content-Type: text/plain');
foreach (['REMOTE_ADDR','HTTP_CF_CONNECTING_IP','HTTP_X_FORWARDED_FOR'] as $h) {
echo "$h: " . ($_SERVER[$h] ?? '') . "\n";
}Теперь установите плагин Cloudflare и примените рекомендуемые настройки.
Настройка кэширования Redis
Redis — один из лучших способов ускорить WordPress (кэширование объектов, иногда кэширование страниц)
sudo systemctl enable redis-server
sudo systemctl start redis-serverЗащитите Redis, отредактировав /etc/redis/redis.conf
# Append/Uncomment/Modify the following
supervised systemd
maxmemory 256mb # adjust for your RAM
maxmemory-policy allkeys-lru # evict least-used keysУстановить необходимые плагины
sudo -u www-data wp plugin install redis-cache --activate
sudo -u www-data wp redis enable
sudo -u www-data wp plugin install nginx-helper --activateУстановка и настройка Brotli
Brotli ускоряет загрузку вашего сайта, передавая меньше байтов через интернет — как архивирование файлов перед отправкой по электронной почте, но автоматически и незаметно для пользователя. Это лучше, чем Gzip.
# Only with ppa:ondrej/nginx Repo
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-staticnano /etc/nginx/nginx.conf# Append the following to inside http{} block, above "gzip on"
brotli on;
brotli_comp_level 5;
brotli_static on; # serve precompressed .br if present (harmless if not)
brotli_types
text/plain text/css text/javascript application/javascript
application/json application/xml application/rss+xml
application/vnd.ms-fontobject application/font-sfnt
application/x-font-ttf font/ttf font/otf image/svg+xml;
# Append/Uncomment the following
gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/javascript application/json application/xml image/svg+xml;Перезагрузите NGINX и проверьте работу Brotli.
sudo nginx -t && sudo systemctl reload nginx
# Brotli client
curl -sI -H 'Accept-Encoding: br' https://yourdomain | grep -i content-encoding
# Response → Content-Encoding: br
# Gzip client
curl -sI -H 'Accept-Encoding: gzip' https://yourdomain | grep -i content-encoding
# Response → Content-Encoding: gzip (or nothing if already tiny)Автоматическая перезагрузка NGINX
Если вы начнёте использовать плагины, такие как Smush, Yoast SEO Redirects и т. д., то любой плагин, требующий включения файлов в blog.conf или nginx.conf. Каждый раз, когда плагин изменяет этот файл, нам нужно перезагружать NGINX. Давайте создадим службу, которая будет делать это автоматически.
# Create a /etc/systemd/system/nginx-auto-reload.service
[Unit]
Description=Validate and reload Nginx when watched files change
[Service]
Type=oneshot
# Validate config & Stop if there are errors
ExecStart=/usr/sbin/nginx -t
# Reload ONLY if ExecStart succeeded
ExecStartPost=/bin/systemctl reload nginx# Create /etc/systemd/system/nginx-auto-reload.path
[Unit]
Description=Watch specific Nginx-related files
[Path]
# Add one line per file you want to monitor for changes
# Add/Remove Lines as needed
PathChanged=/var/www/blog/file1.conf
PathChanged=/var/www/blog/file2.conf
PathChanged=/var/www/blog/file3.conf
[Install]
WantedBy=multi-user.targetВключить и запустить
sudo systemctl daemon-reload
sudo systemctl enable --now nginx-auto-reload.path
# (optional first run)
sudo systemctl start nginx-auto-reload.serviceТест: Отредактируйте один из отслеживаемых файлов, затем
journalctl -u nginx-auto-reload.service -n 20 --no-pager
# You should see nginx: configuration file /etc/nginx/nginx.conf test is successful followed by a reload. If the config is broken, nginx -t will fail and no reload happens.Безопасный и оптимизированный PHP
Теперь давайте улучшим PHP для повышения производительности и безопасности. Значение по умолчанию php.ini Значения предназначены для разработки, а не для эксплуатации. Они безопасны, но далеки от оптимальных. Эти настройки сделают ваш сервер быстрее, безопаснее и лучше подойдут для масштабируемого WordPress.
Измените/добавьте следующее в соответствующие файлы.
; Core
expose_php = 0
cgi.fix_pathinfo = 0 ; never guess script names
default_charset = UTF-8
max_execution_time = 120
memory_limit = 512M ; raise if you run heavy builders
post_max_size = 64M
upload_max_filesize = 64M
max_input_vars = 5000
realpath_cache_size = 4096k
realpath_cache_ttl = 600
; Errors (log, don't leak)
display_errors = Off
log_errors = On
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
zend.exception_ignore_args = On
; Sessions (secure cookies)
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_secure = 1 ; keep https-only
session.cookie_samesite = Lax
session.sid_length = 48
session.sid_bits_per_character = 6
; per-pool session.save_path is set in pool conf for isolation
; Opcache (prod profile)
opcache.enable = 1
opcache.enable_cli = 1 ; faster WP-CLI
opcache.jit = off ; JIT is useless for WP
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 64
opcache.max_accelerated_files = 130987 ; ~128k hash slots
opcache.max_wasted_percentage = 5
opcache.validate_timestamps = 0 ; immutable code in prod
opcache.revalidate_freq = 0 ; reload FPM on deploy
opcache.fast_shutdown = 1
opcache.save_comments = 1 ; plugins use reflection
; If you deploy often and don't reload, use:
; opcache.validate_timestamps=1
; opcache.revalidate_freq=60
; Optional: APCu (micro-cache inside each FPM worker)
; install: apt-get install php8.4-apcu
apc.enabled = 1
apc.enable_cli = 0
apc.shm_size = 64M
apc.entries_hint = 4096
apc.ttl = 120
apc.gc_ttl = 240Теперь давайте настроим PHP-FPM, менеджер процессов FastCGI, который фактически запускает ваш PHP-код. Именно здесь кроется большинство узких мест производительности, особенно на сайтах WordPress с высокой посещаемостью.
; PROCESS MODEL
pm = dynamic
; I use: max_children ≈ (MemAvailable - reserve_for_DB_OS) / avg_child_MB
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 20
pm.max_requests = 800 ; recycle to kill leaks
; LISTENING
listen = /run/php/php8.4-fpm.sock
listen.mode = 0660
listen.owner = www-data
listen.group = www-data
; SECURITY GUARD RAILS
clear_env = yes
security.limit_extensions = .php
; Harden only FPM SAPI; leave CLI free for wp-cli
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,proc_terminate,proc_get_status,proc_nice,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wexitstatus,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifstopped,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_async_signals,popen
; If a plugin genuinely needs one of these, remove it here, not globally.
; OBSERVABILITY
pm.status_path = /fpm-status
ping.path = /fpm-ping
ping.response = pong
request_terminate_timeout = 120
request_slowlog_timeout = 3s
; Make sure the slowlog path exists and is writable by the FPM user
; e.g. sudo mkdir -p /var/log/php8.4-fpm && sudo chown www-data:www-data /var/log/php8.4-fpm
; Otherwise, PHP Reload would fail
slowlog = /var/log/php8.4-fpm/slow.log
catch_workers_output = yes
decorate_workers_output = no# Reload PHP
sudo systemctl reload php8.4-fpm
sudo systemctl status php8.4-fpm --no-pagerБезопасный Ведение журнала
Журналы — это ваш чёрный ящик: они сообщают, что произошло, когда и почему. Они необходимы для отладки и выявления проблем с производительностью или безопасностью. Но без ротации журналы будут бесконечно разрастаться и могут заполнить весь диск. Делайте всё правильно, включайте только необходимое, храните данные в безопасности и выполняйте ротацию/сжатие по расписанию.
mkdir -p /var/log/blog
sudo chown www-data:www-data /var/log/blog
sudo chmod 750 /var/log/blog
sudo tee /etc/logrotate.d/wordpress >/dev/null <<'EOF'
/var/log/blog/debug.log {
weekly
rotate 12
compress
missingok
notifempty
create 640 www-data www-data
}
EOF# Enable file logging only in wp-config.php
if ( ! defined( 'WP_DEBUG' ) ) {
define( 'WP_DEBUG', true );
}
// Set display to false, We don't want errors displayed on our frontend
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
// Log to a file (outside web root is best)
define('WP_DEBUG_LOG', '/var/log/blog/debug.log');Дополнительно
Если вы не используете функцию «Обфускация электронной почты» от Cloudflare, я рекомендую это плагин Для защиты вашего адреса электронной почты от ботов и скрейперов. Это гарантирует, что ваш адрес электронной почты будет отображаться только при включённом JavaScript, скрывая его от исходного кода страницы и затрудняя сбор спам-ботами.
# Let's create a Must-Use folder
mkdir -p /var/www/blog/wp-content/mu-plugins
chown ubuntu:www-data //var/www/blog/wp-content/mu-plugins
wget -O /var/www/blog/wp-content/mu-plugins/protect-my-email.php https://raw.githubusercontent.com/abdessalllam/cloud-setup/refs/heads/main/wordpress/protect-my-email.phpИспользование:
Full Shortcode: [js_email label="Reach out to me via Email:" user="info" domain="example.com" display="inline" subject="Hello" msg="Please enable JS for the Email" class="optional-extra-class"]
Minimal Use: [js_email user="info" domain="example.com"]
Output: info@example.comЧто дальше?
Логи Nginx находятся по адресу /var/log/nginx/
Вот и всё, готово. Поздравляю 🎉🎉 Я бы рекомендовал установить плагин кэширования и плагин безопасности, чтобы ускорить и обезопасить вашу установку.
Это не то самый быстрый способ установки WordPress, но это правильный путь.
Есть предложения или вы заметили, что можно улучшить? Поделитесь своими мыслями в комментариях — мы будем рады их услышать.
