NGINX
#nginx#wordpress#php-fpm#cms#fastcgi#permalinks

Nginx: конфигурация для WordPress с PHP-FPM

Официальная конфигурация Nginx для WordPress с PHP-FPM, поддержкой pretty permalinks, кеширования и безопасности. Основано на документации WordPress.org.

Как использовать

  1. Скопируйте блок server, замените server_name, root и пути к логам и SSL-сертификатам.
  2. Убедитесь, что try_files для location / содержит /index.php?$args для pretty permalinks.
  3. Запретите выполнение PHP в uploads: location ~* /(?:uploads|files)/.*\.php$ { deny all; }. Проверка: nginx -t; systemctl reload nginx.

Под WordPress на Nginx запросы к PHP отдаёт PHP-FPM через fastcgi; для «человекопонятных» URL (pretty permalinks) все запросы должны уходить в index.php с query string. Без правильного try_files страницы постов и рубрик отдают 404; без запрета выполнения PHP в uploads загруженный вредоносный .php может выполниться. Проблема: типовой конфиг под Apache не подходит — Nginx не читает .htaccess. Симптомы: 404 на страницах с permalinks, выполнение PHP в wp-content/uploads, потеря GET-параметров. Ниже — базовая конфигурация и вариант с HTTPS по документации WordPress.org и Nginx WordPress Recipe; проверка и типичные ошибки.

Решение

Конфигурация Nginx для WordPress с PHP-FPM: pretty permalinks, защита скрытых файлов и uploads, кеш статики.

Базовая конфигурация (HTTP)

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/wordpress;
    index index.php index.html;

    access_log /var/log/nginx/wordpress-access.log;
    error_log  /var/log/nginx/wordpress-error.log;

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~ /\. {
        deny all;
    }

    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires max;
        log_not_found off;
    }
}

С поддержкой HTTPS

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    root /var/www/wordpress;
    index index.php index.html;

    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    access_log /var/log/nginx/wordpress-access.log;
    error_log  /var/log/nginx/wordpress-error.log;

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { allow all; log_not_found off; access_log off; }
    location ~ /\. { deny all; }
    location ~* /(?:uploads|files)/.*\.php$ { deny all; }

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        fastcgi_intercept_errors on;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires max;
        log_not_found off;
    }
}

Важно: для pretty permalinks обязателен try_files ... /index.php?$args?$args). В php.ini должно быть cgi.fix_pathinfo = 0. Nginx не использует .htaccess — всё в конфиге сервера.

Проверка

  1. Синтаксис и перезагрузка:
sudo nginx -t
sudo systemctl reload nginx
  1. Главная и страница с permalink — откройте главную и любую страницу/запись с «человекопонятным» URL. Не должно быть 404. Если 404 — проверьте, что в location / стоит именно /index.php?$args.

  2. Запрет PHP в uploads — положите в wp-content/uploads тестовый файл test.php с содержимым <?php echo 'exec'; ?>. Запрос к https://example.com/wp-content/uploads/2026/02/test.php должен вернуть 403 (deny all), а не выполнить код.

  3. Путь к PHP-FPM — сокет в fastcgi_pass должен совпадать с настройками PHP-FPM (часто /run/php/php8.2-fpm.sock или 127.0.0.1:9000). При неверном пути nginx отдаёт 502.

Типичные ошибки

  • Нет ?$args в try_files — без него query string теряется, WordPress не получает REQUEST_URI и отдаёт 404 на страницах с permalinks. Всегда используйте /index.php?$args.
  • cgi.fix_pathinfo = 1 в php.ini — при этом PHP может выполнить другой файл по пути; рекомендуется 0. Проверьте: php -i | grep fix_pathinfo.
  • Выполнение PHP в uploads — без location с deny all для .*\.php$ в uploads загруженный скрипт выполнится. Обязательно запрещайте выполнение в каталогах загрузок.
  • root указывает не на каталог WordPress — root должен быть каталог, в котором лежат index.php, wp-config.php и т.д. (при структуре с public — корень сайта, где доступен index.php).

Где применять

  • Prod / dev: сервер с Nginx и PHP-FPM под один или несколько сайтов WordPress. Логи можно вынести в каталог сайта (структура каталогов).
  • SSL: подставьте пути к сертификатам (или используйте Let’s Encrypt по аналогии для своего пути).

Связанные сниппеты: Структура каталогов для сайтов, Nginx и SSL Let’s Encrypt (BitrixVM), Анализ логов nginx.