Deploy Laravel Project On Heroku

Getting Started with Laravel on Heroku

This guide will walk you through the configuration and deployment of a Laravel 5 application. For a general introduction to using PHP on Heroku, please refer to Getting Started with PHP on Heroku.

Prerequisites:

PHP (and ideally some Laravel) knowledge.
A Heroku user account. Signup is free and instant.
Familiarity with the Getting Started with PHP on Heroku guide, with PHP, Composer, and the Heroku CLI installed on your computer.
Creating a Laravel application
The application in this tutorial is based on the Laravel Installation guide. It’s worth a read before following the instructions in this article.

Installing a new Laravel project:


The composer create-project command is one of the ways you can bootstrap a new project based on the laravel/laravel standard application skeleton. The command below sets it up in a directory named hello_laravel using the latest version of the framework.

After downloading an extensive number of dependencies and running a few hooks, Composer will have set up a fully functional project in the directory you specified, so you can cd to it.

$ composer create-project laravel/laravel --prefer-dist hello_laravel

Created project in hello_laravel

$ cd hello_laravel
Initializing a Git repository:

It’s now time to initialize a Git repository and commit the current state:

$ git init
$ git add .
$ git commit -m "new laravel project"

Deploying to Heroku:

To deploy your application to Heroku, you must first create a Procfile, which tells Heroku what command to use to launch the web server with the correct settings. After you’ve done that, you’re going to create an application instance on Heroku, configure some Laravel environment variables, and then simply git push to deploy your code!

Creating a Procfile:

By default, Heroku will launch an Apache web server together with PHP to serve applications from the root directory of the project.

However, your application’s document root is the public/ subdirectory, so you need to create a Procfile that configures the correct document root:

$ echo web: vendor/bin/heroku-php-apache2 public/ > Procfile
$ git add .
$ git commit -m "Procfile for Heroku"

Creating a new application on Heroku:

To create a new Heroku application that you can push to, use the heroku create command:

$ heroku create


You are now almost ready to deploy the application. Follow the next section to ensure your Laravel app runs with the correct configuration.

Setting a Laravel encryption key
The application’s encryption key is used by Laravel to encrypt user sessions and other information. Its value will be read from the APP_KEY environment variable.

As it must comply with the rules of the selected cipher in the configuration, the easiest way to generate a valid key is using the php artisan key:generate --show command, which will print a key that you can copy and then paste into the next step.

You can simply set environment variables using the heroku config command, so run a heroku config:set as the last step before deploying your app for the first time:

$ heroku config:set APP_KEY=…
Setting config vars and restarting mighty-hamlet-1982... done, v3
APP_KEY: ZEqur46KTEG91iWPhKGY42wtwi3rtkx2
Replace … in the command above with the key you copied from the php artisan key:generate --show command output. Instead of manually replacing the … placeholder in the command above, you can also run
heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show).

Pushing to Heroku
Next, it’s time to deploy to Heroku:

$ git push heroku master

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 CLI to launch a new browser window, the application will respond.

$ heroku open

You should see a message in your browser that says “Laravel 5”.

Best Practices:


Changing the log destination for production
By default, Laravel will log errors and messages into a directory on disk, which isn’t ideal, because Heroku uses an ephemeral filesystem and treats logs as streams of events across all running dynos.

In order to ensure that errors, should they arise, are visible in heroku logs, the corresponding configuration in config/logging.php must be changed so that all relevant channels use the errorlog driver; for example:

<?php
return [
    'default' => env('LOG_CHANNEL', 'stack'),
    'channels' => [
        'stack' => [
            'driver' => 'stack',
            'channels' => ['single'],
        ],
        'single' => [
            'driver' => 'errorlog',
            'level' => 'debug',
        ],

Do not forget to add, commit, and, if appropriate, push this change:

$ git add config/logging.php
$ git commit -m "use errorlog"
$ git push heroku master

Trusting the Load Balancer:


Heroku’s HTTP Routing routes each request through a layer of reverse proxies which are, among other things, responsible for load balancing and terminating SSL connections. This means that requests received by a dyno will have the last router’s IP address in the REMOTE_ADDR environment variable, and the internal request will always be made using the HTTP protocol, even if the original request was made over HTTPS.

Like most common load balancers or reverse proxies, Heroku provides the original request information in X-Forwarded-… headers (as documented here). Laravel uses components from the Symfony framework for HTTP request handling, and Symfony can easily be configured to trust such headers.

Since Heroku sends all requests to an application through a load balancer first, and that load balancer always sets the headers (making it impossible for a client to forge their values), you can configure Laravel to treat the current remote address (which is the Heroku router) as a trusted proxy.

It is very important to also prevent Laravel from trusting the Forwarded and X-Forwarded-Host headers, because Heroku’s router does not set those, but Symfony’s Request component trusts them out of the box once a trusted proxy is set.

Following the Laravel documentation for trusting proxies, your final App\Http\Middleware\TrustProxies middleware should look like this:

<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Fideloper\Proxy\TrustProxies as Middleware;
class TrustProxies extends Middleware
{
    protected $proxies = '*';
    protected $headers = Request:: HEADER_X_FORWARDED_AWS_ELB;
}

Comments

Popular posts from this blog

Laravel 5 Chart example using Charts Package

Laravel Stats Tracker

PHPMyBackup - A PHP MySQL differential backup script