Deploying a Symfony application to Heroku doesn't require any change in its
code, but it requires some minor tweaks to its configuration.

By default, the Symfony app will log into your application's app/log/
directory. This is not ideal as Heroku uses an ephemeral file system. On
Heroku, the best way to handle logging is using Logplex. And the best way to
send log data to Logplex is by writing to STDERR or STDOUT. Luckily,
Symfony uses the excellent Monolog library for logging. So, a new log
destination is just a change to a config file away.

Open the app/config/config_prod.yml file, locate the
monolog/handlers/nested section (or create it if it doesn't exist yet) and
change the value of path from
"%kernel.logs_dir%/%kernel.environment%.log" to "php://stderr":

By default, Heroku will launch an Apache web server together with PHP to serve
applications. However, two special circumstances apply to Symfony applications:

The document root is in the web/ directory and not in the root directory
of the application;

The Composer bin-dir, where vendor binaries (and thus Heroku's own boot
scripts) are placed, is bin/ , and not the default vendor/bin.

Note

Vendor binaries are usually installed to vendor/bin by Composer, but
sometimes (e.g. when running a Symfony Standard Edition project!), the
location will be different. If in doubt, you can always run
composer config bin-dir to figure out the right location.

Create a new file called Procfile (without any extension) at the root
directory of the application and add just the following content:

1

web: bin/heroku-php-apache2 web/

Note

If you prefer to use Nginx, which is also available on Heroku, you can create
a configuration file for it and point to it from your Procfile as described
in the Heroku documentation:

1

web: bin/heroku-php-nginx -C nginx_app.conf web/

If you prefer working on the command console, execute the following commands to
create the Procfile file and to add it to the repository:

During a deployment, Heroku runs composer install --no-dev to install all the
dependencies your application requires. However, typical post-install-commands
in composer.json, e.g. to install assets or clear (or pre-warm) caches, run
using Symfony's dev environment by default.

This is clearly not what you want - the app runs in "production" (even if you
use it just for an experiment, or as a staging environment), and so any build
steps should use the same prod environment as well.

Thankfully, the solution to this problem is very simple: Symfony will pick up an
environment variable named SYMFONY_ENV and use that environment if nothing
else is explicitly set. As Heroku exposes all config vars as environment
variables, you can issue a single command to prepare your app for a deployment:

1

$ heroku config:set SYMFONY_ENV=prod

Caution

Be aware that dependencies from composer.json listed in the require-dev
section are never installed during a deploy on Heroku. This may cause problems
if your Symfony environment relies on such packages. The solution is to move these
packages from require-dev to the require section.

Next up, it's finally time to deploy your application to Heroku. If you are
doing this for the very first time, you may see a message such as the following:

1
2
3

The authenticity of host 'heroku.com (50.19.85.132)' can't be established.
RSA key fingerprint is 8b:48:5e:67:0e:c9:16:47:32:f2:87:0c:1f:c8:60:ad.
Are you sure you want to continue connecting (yes/no)?

And that's it! If you now open your browser, either by manually pointing
it to the URL heroku create gave you, or by using the Heroku Toolbelt, the
application will respond:

1
2

$ heroku open
Opening mighty-hamlet-1981... done

You should be seeing your Symfony application in your browser.

Caution

If you take your first steps on Heroku using a fresh installation of
the Symfony Standard Edition, you may run into a 404 page not found error.
This is because the route for / is defined by the AcmeDemoBundle, but the
AcmeDemoBundle is only loaded in the dev environment (check out your
AppKernel class). Try opening /app/example from the AppBundle.

If you wish to execute additional custom commands during a build, you can leverage
Heroku's custom compile steps. Imagine you want to remove the dev front controller
from your production environment on Heroku in order to avoid a potential vulnerability.
Adding a command to remove web/app_dev.php to Composer's post-install-commands would
work, but it also removes the controller in your local development environment on each
composer install or composer update respectively. Instead, you can add a
custom Composer command named compile (this key name is a Heroku convention) to the
scripts section of your composer.json. The listed commands hook into Heroku's deploy
process:

1
2
3
4
5
6
7

{"scripts":{"compile":["rm web/app_dev.php"]}}

This is also very useful to build assets on the production system, e.g. with Assetic:

1
2
3
4
5
6
7

{"scripts":{"compile":["bin/console assetic:dump"]}}

Node.js Dependencies

Building assets may depend on node packages, e.g. uglifyjs or uglifycss
for asset minification. Installing node packages during the deploy requires a node
installation. But currently, Heroku compiles your app using the PHP buildpack, which
is auto-detected by the presence of a composer.json file, and does not include a
node installation. Because the Node.js buildpack has a higher precedence than the PHP
buildpack (see Heroku buildpacks), adding a package.json listing your node
dependencies makes Heroku opt for the Node.js buildpack instead:

With the next deploy, Heroku compiles your app using the Node.js buildpack and
your npm packages become installed. On the other hand, your composer.json is
now ignored. To compile your app with both buildpacks, Node.js and PHP, you need
to use both buildpacks. To override buildpack auto-detection, you
need to explicitly set the buildpack:

1
2
3
4
5
6
7
8

$ heroku buildpacks:set heroku/nodejs
Buildpack set. Next release on your-application will use heroku/nodejs.
Run git push heroku master to create a new release using this buildpack.
$ heroku buildpacks:set heroku/php --index 2
Buildpack set. Next release on your-application will use:
1. heroku/nodejs
2. heroku/php
Run git push heroku master to create a new release using these buildpacks.

With the next deploy, you can benefit from both buildpacks. This setup also enables
your Heroku environment to make use of node based automatic build tools like
Grunt or gulp.