Урок 05

Reverse proxy для Laravel

Что такое reverse proxy

Reverse proxy — Nginx принимает запросы и передаёт их другому сервису (PHP-FPM, Node.js, другому Nginx). Клиент видит только Nginx.

Для Laravel Nginx работает как reverse proxy к PHP-FPM через сокет или порт.

Схема

Клиент → Nginx:80 → PHP-FPM через сокет → Laravel → ответ

Что делает Nginx:

  • Отдаёт статику (картинки, CSS, JS) сам, быстро
  • Для PHP проксирует на PHP-FPM
  • Не парсит PHP сам

Почему PHP-FPM

PHP-FPM (FastCGI Process Manager) — пул PHP-процессов, готовых обрабатывать запросы.

Плюс: PHP не запускается на каждый запрос — процессы живут постоянно.

Минус: нужно настраивать пулы и перезагружать после деплоя.

Полный конфиг Laravel

server {
    listen 80;
    listen [::]:80;
    server_name api.example.com;

    root /var/www/skills/api/public;
    index index.php;

    charset utf-8;

    # Основной роутинг — в index.php
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Статика — отдаём напрямую
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot|webp)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
        try_files $uri =404;
    }

    # PHP через PHP-FPM
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php8.5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;

        # Буферы
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;

        # Таймауты
        fastcgi_read_timeout 300;
    }

    # Favicon и robots без логов
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    # Запрет скрытых файлов
    location ~ /\.(?!well-known).* {
        deny all;
    }

    # Размер загрузки
    client_max_body_size 20M;
}

Разбор fastcgi-параметров

fastcgi_split_path_info ^(.+\.php)(/.+)$; — разделяет /index.php/foo/bar на скрипт и path info.

fastcgi_pass unix:/var/run/php/php8.5-fpm.sock; — куда отправлять. Сокет быстрее, чем TCP порт.

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; — путь к PHP. $realpath_root — реальный путь, а не симлинк. Защита от path traversal.

fastcgi_buffer_size 128k; — размер буфера для заголовков ответа.

fastcgi_buffers 4 256k; — 4 буфера по 256 КБ для тела ответа. Увеличение — если ответы большие.

fastcgi_read_timeout 300; — 5 минут на ответ. Увеличивай, если есть долгие запросы (тяжёлые отчёты, экспорт).

Проверка сокета PHP-FPM

ls /var/run/php/
# php8.5-fpm.sock

Если сокет не там — проверь /etc/php/8.5/fpm/pool.d/www.conf:

listen = /var/run/php/php8.5-fpm.sock

После изменений:

sudo systemctl restart php8.5-fpm

Проксирование на TCP

Если по каким-то причинам не сокет, а порт:

fastcgi_pass 127.0.0.1:9000;

Проверь в www.conf:

listen = 127.0.0.1:9000

Сокет быстрее, но порт проще для отладки.

Отдача статики

Nginx отдаёт статику сам — не идёт в PHP. Это быстрее в 10-100 раз.

location ~* \.(jpg|png|css|js|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
    try_files $uri =404;
}

expires 30d; — кеш в браузере на 30 дней.

immutable — файл не изменится. Браузер не будет перепроверять его — экономия запросов.

try_files $uri =404; — если файла нет — вернуть 404 (не идти в PHP).

Проверка

1. Конфиг:

sudo nginx -t

2. Перезагрузка:

sudo systemctl reload nginx

3. Тест:

curl -I http://api.example.com
# HTTP/1.1 200 OK
# X-Powered-By: PHP/8.5.10

Если видишь X-Powered-By — PHP работает.

Частые ошибки

1. 502 Bad Gateway — PHP-FPM не работает или сокет неверный. Проверь:

sudo systemctl status php8.5-fpm
ls /var/run/php/

2. 403 Forbidden — права на файлы. Laravel storage/ и bootstrap/cache/ должны быть доступны www-data:

sudo chown -R www-data:www-data /var/www/skills/api/storage
sudo chmod -R 775 /var/www/skills/api/storage

3. 404 Not Found для всех роутов — try_files неверный или root не public/.

4. File not found — неверный SCRIPT_FILENAME. Проверь php-fpm.sock и путь.

Итог

Для Laravel:

  • root .../public;
  • try_files $uri $uri/ /index.php?$query_string;
  • fastcgi_pass unix:/var/run/php/php8.5-fpm.sock;
  • fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

Дальше — reverse proxy для Next.js.