Configuring a Web Server

Configuring a Web Server

The preferred way to develop your Symfony application is to use Symfony Local Web Server.

However, when running the application in the production environment, you’ll need to use a fully-featured web server. This article describes several ways to use Symfony with Apache or Nginx.

When using Apache, you can configure PHP as an Apache module or with FastCGI using PHP FPM. FastCGI also is the preferred way to use PHP with Nginx.

The public directory

The public directory is the home of all of your application’s public and static files, including images, stylesheets and JavaScript files. It is also where the front controller (index.php) lives.

The public directory serves as the document root when configuring your web server. In the examples below, the public/ directory will be the document root. This directory is /var/www/project/public/.

If your hosting provider requires you to change the public/ directory to another location (e.g. public_html/) make sure you override the location of the public/ directory.

Adding Rewrite Rules

The easiest way is to install the apache Symfony pack by executing the following command:

  1. $ composer require symfony/apache-pack

This pack installs a .htaccess file in the public/ directory that contains the rewrite rules needed to serve the Symfony application.

In production servers, you should move the .htaccess rules into the main Apache configuration file to improve performance. To do so, copy the .htaccess contents inside the <Directory> configuration associated to the Symfony application public/ directory (and replace AllowOverride All by AllowOverride None):

  1. <VirtualHost *:80>
  2. # ...
  3. DocumentRoot /var/www/project/public
  4. <Directory /var/www/project/public>
  5. AllowOverride None
  6. # Copy .htaccess contents here
  7. </Directory>
  8. </VirtualHost>

Apache with mod_php/PHP-CGI

The minimum configuration to get your application running under Apache is:

  1. <VirtualHost *:80>
  2. ServerName domain.tld
  3. ServerAlias www.domain.tld
  4. DocumentRoot /var/www/project/public
  5. <Directory /var/www/project/public>
  6. AllowOverride All
  7. Order Allow,Deny
  8. Allow from All
  9. </Directory>
  10. # uncomment the following lines if you install assets as symlinks
  11. # or run into problems when compiling LESS/Sass/CoffeeScript assets
  12. # <Directory /var/www/project>
  13. # Options FollowSymlinks
  14. # </Directory>
  15. ErrorLog /var/log/apache2/project_error.log
  16. CustomLog /var/log/apache2/project_access.log combined
  17. </VirtualHost>

Tip

If your system supports the APACHE_LOG_DIR variable, you may want to use ${APACHE_LOG_DIR}/ instead of hardcoding /var/log/apache2/.

Use the following optimized configuration to disable .htaccess support and increase web server performance:

  1. <VirtualHost *:80>
  2. ServerName domain.tld
  3. ServerAlias www.domain.tld
  4. DocumentRoot /var/www/project/public
  5. DirectoryIndex /index.php
  6. <Directory /var/www/project/public>
  7. AllowOverride None
  8. Order Allow,Deny
  9. Allow from All
  10. FallbackResource /index.php
  11. </Directory>
  12. # uncomment the following lines if you install assets as symlinks
  13. # or run into problems when compiling LESS/Sass/CoffeeScript assets
  14. # <Directory /var/www/project>
  15. # Options FollowSymlinks
  16. # </Directory>
  17. # optionally disable the fallback resource for the asset directories
  18. # which will allow Apache to return a 404 error when files are
  19. # not found instead of passing the request to Symfony
  20. <Directory /var/www/project/public/bundles>
  21. DirectoryIndex disabled
  22. FallbackResource disabled
  23. </Directory>
  24. ErrorLog /var/log/apache2/project_error.log
  25. CustomLog /var/log/apache2/project_access.log combined
  26. # optionally set the value of the environment variables used in the application
  27. #SetEnv APP_ENV prod
  28. #SetEnv APP_SECRET <app-secret-id>
  29. #SetEnv DATABASE_URL "mysql://db_user:[email protected]:3306/db_name"
  30. </VirtualHost>

Caution

Use FallbackResource on Apache 2.4.25 or higher, due to a bug which was fixed on that release causing the root / to hang.

Tip

If you are using php-cgi, Apache does not pass HTTP basic username and password to PHP by default. To work around this limitation, you should use the following configuration snippet:

  1. RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Using mod_php/PHP-CGI with Apache 2.4

In Apache 2.4, Order Allow,Deny has been replaced by Require all granted. Hence, you need to modify your Directory permission settings as follows:

  1. <Directory /var/www/project/public>
  2. Require all granted
  3. # ...
  4. </Directory>

For advanced Apache configuration options, read the official Apache documentation.

Apache with PHP-FPM

To make use of PHP-FPM with Apache, you first have to ensure that you have the FastCGI process manager php-fpm binary and Apache’s FastCGI module installed (for example, on a Debian based system you have to install the libapache2-mod-fastcgi and php7.4-fpm packages).

PHP-FPM uses so-called pools to handle incoming FastCGI requests. You can configure an arbitrary number of pools in the FPM configuration. In a pool you configure either a TCP socket (IP and port) or a Unix domain socket to listen on. Each pool can also be run under a different UID and GID:

  1. ; a pool called www
  2. [www]
  3. user = www-data
  4. group = www-data
  5. ; use a unix domain socket
  6. listen = /var/run/php/php7.4-fpm.sock
  7. ; or listen on a TCP socket
  8. listen = 127.0.0.1:9000

Using mod_proxy_fcgi with Apache 2.4

If you are running Apache 2.4, you can use mod_proxy_fcgi to pass incoming requests to PHP-FPM. Configure PHP-FPM to listen on a TCP or Unix socket, enable mod_proxy and mod_proxy_fcgi in your Apache configuration, and use the SetHandler directive to pass requests for PHP files to PHP FPM:

  1. <VirtualHost *:80>
  2. ServerName domain.tld
  3. ServerAlias www.domain.tld
  4. # Uncomment the following line to force Apache to pass the Authorization
  5. # header to PHP: required for "basic_auth" under PHP-FPM and FastCGI
  6. #
  7. # SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
  8. # For Apache 2.4.9 or higher
  9. # Using SetHandler avoids issues with using ProxyPassMatch in combination
  10. # with mod_rewrite or mod_autoindex
  11. <FilesMatch \.php$>
  12. SetHandler proxy:fcgi://127.0.0.1:9000
  13. # for Unix sockets, Apache 2.4.10 or higher
  14. # SetHandler proxy:unix:/path/to/fpm.sock|fcgi://dummy
  15. </FilesMatch>
  16. # If you use Apache version below 2.4.9 you must consider update or use this instead
  17. # ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/public/$1
  18. # If you run your Symfony application on a subpath of your document root, the
  19. # regular expression must be changed accordingly:
  20. # ProxyPassMatch ^/path-to-app/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/project/public/$1
  21. DocumentRoot /var/www/project/public
  22. <Directory /var/www/project/public>
  23. # enable the .htaccess rewrites
  24. AllowOverride All
  25. Require all granted
  26. </Directory>
  27. # uncomment the following lines if you install assets as symlinks
  28. # or run into problems when compiling LESS/Sass/CoffeeScript assets
  29. # <Directory /var/www/project>
  30. # Options FollowSymlinks
  31. # </Directory>
  32. ErrorLog /var/log/apache2/project_error.log
  33. CustomLog /var/log/apache2/project_access.log combined
  34. </VirtualHost>

PHP-FPM with Apache 2.2

On Apache 2.2 or lower, you cannot use mod_proxy_fcgi. You have to use the FastCgiExternalServer directive instead. Therefore, your Apache configuration should look something like this:

  1. <VirtualHost *:80>
  2. ServerName domain.tld
  3. ServerAlias www.domain.tld
  4. AddHandler php7-fcgi .php
  5. Action php7-fcgi /php7-fcgi
  6. Alias /php7-fcgi /usr/lib/cgi-bin/php7-fcgi
  7. FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi -host 127.0.0.1:9000 -pass-header Authorization
  8. DocumentRoot /var/www/project/public
  9. <Directory /var/www/project/public>
  10. # enable the .htaccess rewrites
  11. AllowOverride All
  12. Order Allow,Deny
  13. Allow from all
  14. </Directory>
  15. # uncomment the following lines if you install assets as symlinks
  16. # or run into problems when compiling LESS/Sass/CoffeeScript assets
  17. # <Directory /var/www/project>
  18. # Options FollowSymlinks
  19. # </Directory>
  20. ErrorLog /var/log/apache2/project_error.log
  21. CustomLog /var/log/apache2/project_access.log combined
  22. </VirtualHost>

If you prefer to use a Unix socket, you have to use the -socket option instead:

  1. FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi -socket /var/run/php/php7.4-fpm.sock -pass-header Authorization

Nginx

The minimum configuration to get your application running under Nginx is:

  1. server {
  2. server_name domain.tld www.domain.tld;
  3. root /var/www/project/public;
  4. location / {
  5. # try to serve file directly, fallback to index.php
  6. try_files $uri /index.php$is_args$args;
  7. }
  8. # optionally disable falling back to PHP script for the asset directories;
  9. # nginx will return a 404 error when files are not found instead of passing the
  10. # request to Symfony (improves performance but Symfony's 404 page is not displayed)
  11. # location /bundles {
  12. # try_files $uri =404;
  13. # }
  14. location ~ ^/index\.php(/|$) {
  15. fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
  16. fastcgi_split_path_info ^(.+\.php)(/.*)$;
  17. include fastcgi_params;
  18. # optionally set the value of the environment variables used in the application
  19. # fastcgi_param APP_ENV prod;
  20. # fastcgi_param APP_SECRET <app-secret-id>;
  21. # fastcgi_param DATABASE_URL "mysql://db_user:[email protected]:3306/db_name";
  22. # When you are using symlinks to link the document root to the
  23. # current version of your application, you should pass the real
  24. # application path instead of the path to the symlink to PHP
  25. # FPM.
  26. # Otherwise, PHP's OPcache may not properly detect changes to
  27. # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
  28. # for more information).
  29. # Caveat: When PHP-FPM is hosted on a different machine from nginx
  30. # $realpath_root may not resolve as you expect! In this case try using
  31. # $document_root instead.
  32. fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
  33. fastcgi_param DOCUMENT_ROOT $realpath_root;
  34. # Prevents URIs that include the front controller. This will 404:
  35. # http://domain.tld/index.php/some-path
  36. # Remove the internal directive to allow URIs like this
  37. internal;
  38. }
  39. # return 404 for all other php files not matching the front controller
  40. # this prevents access to other php files you don't want to be accessible.
  41. location ~ \.php$ {
  42. return 404;
  43. }
  44. error_log /var/log/nginx/project_error.log;
  45. access_log /var/log/nginx/project_access.log;
  46. }

Tip

If you use NGINX Unit, check out the official article about How to run Symfony applications using NGINX Unit.

Note

Depending on your PHP-FPM config, the fastcgi_pass can also be fastcgi_pass 127.0.0.1:9000.

Tip

This executes only index.php in the public directory. All other files ending in “.php” will be denied.

If you have other PHP files in your public directory that need to be executed, be sure to include them in the location block above.

Caution

After you deploy to production, make sure that you cannot access the index.php script (i.e. http://example.com/index.php).

For advanced Nginx configuration options, read the official Nginx documentation.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.