Laravel on Heroku - with Nginx & gzip
This blog post was originally published a little while ago. Please consider that it may no longer be relevant or even accurate.
When setting up a PHP app on Heroku the default configuration is to use Apache. It's simple to get going and customise through the .htaccess
file. However out of the box this falls short of what you probably want in a production site.
First you're going to want to switch to using Nginx - as it's generally faster than Apache. Nginx still has first-party support from Heroku, so it's easy to do. Second, you'll want to enable gzip (which is not enabled by default for either Apache or Nginx on Heroku) as that will reduce the time your dyno spends serving requests.
Switching to Nginx
To switch to Nginx we'll need to do two things; first update the Procfile
to tell Heroku to use a different server and second provide a configuration for it that works with Laravel. For reference, take a look at the Nginx configuration provided by Laravel's documentation - we need to adjust it a tad to be compatible with Heroku. We'll effectively be merging it up with the default Nginx configuration file that Heroku uses.
In your Procfile
update the web:
line to use heroku-php-nginx
instead of Apache. As usual you'll provide public/
as the public directory but we also provide a custom configuration file - nginx.conf
- which will instruct Nginx how to work with Laravel.
Next we'll create the nginx.conf
file in the root of the app (but you could pop it wherever you want). This adjusts the default Laravel configuration to work with Heroku. Not a lot has changed, you can easily reference both to see the differences.
There's only a one major difference from Laravel's example - we don't use the listen
, server_name
or root
options as that is all handled upstream by Heroku.
Easy enough - once you ship these changes you'll be running Laravel on Heroku with Nginx, be sure to check the performance of your app before and after the change to get a feel for the improvement.
Enabling nginx
For whatever reason, gzip is disabled by default for Heroku's PHP buildpack. It's unfortunate as gzip can provide a performance improvement as your dyno will spend less time serving request.
Luckily, the HTML5 boilerplate provides example optimised server configuration files. Taking a look at the default setup we can see the gzip configuration. Let's apply this to our configuration (stripping the comments).
With this configuration deployed your Laravel app will now be served through Nginx with everything gzipped. Run another speed test and you should see another speed bump.
I've tried to keep this configuration fairly conventional and unopinionated - using the suggested configuration from Laravel and doing the bare minimum to make it compatible on Heroku and then adding the HTML5 boilerplate's gzip options.