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.