Skip to main content

Symfony on a VPS: Deploy, Nginx Config, and Folder Rights

PHP · 29.09.2026

Symfony by default assumes a layout where the entry point lives in the public/ directory, and everything else — source code, cache, logs — is not reachable by the web server directly. Mistakes in the Nginx config or in directory permissions are the most common cause of a white screen and 502 errors after the first deployment.

Project directory layout

The web server must point strictly at public/, not the project root — otherwise .env, composer.json, and the contents of var/ become reachable through the browser. The var/cache and var/log directories must be writable by the PHP-FPM user, while vendor/ is built with Composer on the server itself or shipped together with the release. For the dependency manager itself, see the article on installing and configuring Composer.

Nginx config for Symfony

The key part is the try_files rule, which routes every request except real files through 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;
    }
}

The internal; line forbids opening /index.php directly by URL — only through try_files. The PHP-FPM pool settings themselves, including worker limits, are covered in the article on PHP-FPM pools and optimization.

Rights on var/cache and var/log

Symfony writes the service container cache, compiled templates, and logs into var/. If the PHP-FPM user cannot write to these folders, the application fails with a permission error on the very first request after deployment.

DirectoryOwnerRightsPurpose
var/cachewww-data775container and template cache
var/logwww-data775application logs
public/uploadswww-data775files uploaded by visitors
config, srcdeploy user755source code, read-only for the web

Release deployment order

Updating the code without warming up the cache means the first visitor after a release waits several seconds for the service container to compile. The command order on the server is:

  • composer install --no-dev --optimize-autoloader — installs dependencies without dev packages and builds an optimized autoloader.
  • php bin/console cache:clear --env=prod — clears the old cache before the rebuild.
  • php bin/console cache:warmup --env=prod — warms up the cache ahead of time, before the first request arrives.
  • php bin/console doctrine:migrations:migrate --no-interaction — applies database migrations if the release includes any.
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

Common 502 errors and white screens

After the first deployment, the most common problems are these.

A 502 Bad Gateway usually means Nginx cannot reach the PHP-FPM socket — either the path in fastcgi_pass does not match the real socket, or the pool itself crashed from running out of memory. A white screen with no error text means APP_DEBUG=0 and Symfony is hiding the details — temporarily check var/log/prod.log instead of the browser. PSR-4 autoloading is tied to Composer autoloader optimization — details are in the article on optimizing the Composer autoloader.

Checklist before going live

Before switching the domain to the new release, go through this list:

  1. Confirm APP_ENV=prod and APP_DEBUG=0 in the .env.local file on the server, not only locally.
  2. Make sure OPcache is enabled and configured to invalidate on a timer, not on every request — the configuration is described in the article on configuring OPcache.
  3. Run a smoke test of the key pages right after deployment, before real visitors reach the site.
← Back to Knowledge Base Ask Support