# Symfony на VPS: деплой, конфиг Nginx и права на каталоги

> Symfony на VPS: структура каталогов, конфиг Nginx для public/index.php, права на var/cache и типовые ошибки 502.

Symfony по умолчанию рассчитан на структуру, где точка входа лежит в каталоге `public/`, а всё остальное — исходники, кэш, логи — недоступно веб-серверу напрямую. Ошибки в конфиге Nginx или в правах на каталоги — самая частая причина белого экрана и 502 после первого деплоя.

## Структура каталогов проекта

Веб-сервер должен смотреть строго в `public/`, а не в корень проекта — иначе через браузер будут доступны `.env`, `composer.json` и содержимое `var/`. Каталог `var/cache` и `var/log` должен быть доступен на запись пользователю PHP-FPM, а `vendor/` собирается через Composer уже на сервере или заливается вместе с релизом. Про сам менеджер зависимостей — в статье [про установку и настройку Composer](https://www.zevshost.net/ru/kb/composer-ustanovka-nastroika/).

## Конфиг Nginx для Symfony

Ключевая часть — правило `try_files`, которое отдаёт все запросы, кроме реальных файлов, через `index.php`:

```
server {
    listen 80;
    server_name example.com;
    root /var/www/example/public;

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

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        internal;
    }

    location ~ \.php$ {
        return 404;
    }
}
```

Строка `internal;` запрещает открывать `/index.php` напрямую по URL — только через try\_files. Настройки самого пула PHP-FPM, включая лимиты воркеров, разобраны в статье [про пулы и оптимизацию PHP-FPM](https://www.zevshost.net/ru/kb/php-fpm-nastroika-optimizatsiya/).

## Права на каталоги var/cache и var/log

Symfony пишет кэш контейнера сервисов, скомпилированные шаблоны и логи в `var/`. Если пользователь PHP-FPM не может писать в эти папки, приложение падает с ошибкой доступа при первом же запросе после деплоя.

| Каталог | Владелец | Права | Назначение |
| --- | --- | --- | --- |
| var/cache | www-data | 775 | кэш контейнера и шаблонов |
| var/log | www-data | 775 | логи приложения |
| public/uploads | www-data | 775 | файлы, загруженные пользователями |
| config, src | деплой-пользователь | 755 | исходники, только чтение для веба |

## Порядок деплоя релиза

Обновление кода без прогрева кэша ведёт к тому, что первый посетитель после релиза ждёт компиляцию контейнера сервисов несколько секунд. Порядок команд на сервере такой:

- `composer install --no-dev --optimize-autoloader` — ставит зависимости без dev-пакетов и строит оптимизированный автозагрузчик.
- `php bin/console cache:clear --env=prod` — очищает старый кэш перед пересборкой.
- `php bin/console cache:warmup --env=prod` — прогревает кэш заранее, до прихода первого запроса.
- `php bin/console doctrine:migrations:migrate --no-interaction` — применяет миграции базы данных, если они есть в релизе.

```
composer install --no-dev --optimize-autoloader
php bin/console cache:clear --env=prod
php bin/console cache:warmup --env=prod
php bin/console doctrine:migrations:migrate --no-interaction
```

## Типовые ошибки 502 и белый экран

После первого деплоя чаще всего встречаются такие проблемы:

502 Bad Gateway обычно означает, что Nginx не может достучаться до сокета PHP-FPM — либо путь в `fastcgi_pass` не совпадает с реальным сокетом, либо сам пул упал из-за нехватки памяти. Белый экран без текста ошибки означает, что `APP_DEBUG=0` и Symfony скрывает подробности — временно включите отображение через `var/log/prod.log`, не через браузер. Автозагрузка PSR-4 связана с оптимизацией автозагрузчика Composer — детали в статье [про оптимизацию Composer autoloader](https://www.zevshost.net/ru/kb/php-composer-autoload-optimizatsiya/).

## Чек-лист перед запуском в проде

Перед тем как переключить домен на новый релиз, пройдитесь по списку:

1. Проверьте, что `APP_ENV=prod` и `APP_DEBUG=0` в файле `.env.local` на сервере, а не только локально.
2. Убедитесь, что OPcache включён и настроен на инвалидацию по времени, а не на каждый запрос — конфигурация описана в статье [про настройку OPcache](https://www.zevshost.net/ru/kb/php-opcache-nastroika-linux/).
3. Прогоните smoke-тест ключевых страниц сразу после деплоя, до того как на сайт зайдут реальные посетители.

---

Источник: https://www.zevshost.net/ru/kb/symfony-nastroika-vps/
