Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Background Jobs in Python
      • Working with Django
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Language Support
  • PHP
  • Getting Started with Laravel on Heroku

Getting Started with Laravel on Heroku

English — 日本語に切り替える

Last updated March 16, 2023

Table of Contents

  • Prerequisites
  • Creating a Laravel application
  • Deploying to Heroku
  • Best Practices
  • Further reading

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_heroku 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_heroku
Installing laravel/laravel (v5.1.11)
  - Installing laravel/laravel (v5.1.11)
    Downloading: 100%

Created project in hello_laravel_heroku
...
...

$ cd hello_laravel_heroku

Initializing a Git repository

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

$ git init -b main
Initialized empty Git repository in ~/hello_laravel_heroku/.git/
$ git add .
$ git commit -m "new laravel project"
[main (root-commit) 6ae139d] new laravel project
 76 files changed, 5458 insertions(+)
...

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"
[main 1eb2be6] Procfile for Heroku
 1 file changed, 1 insertion(+)
 create mode 100644 Procfile

Creating a new application on Heroku

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

$ heroku create
Creating mighty-hamlet-1982... done, stack is heroku-18
http://mighty-hamlet-1982.herokuapp.com/ | git@heroku.com:mighty-hamlet-1982.git
Git remote heroku added

As you can see, a random name was automatically chosen for your application (in the example above, it’s mighty-hamlet-1982).

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 main
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 379 bytes | 0 bytes/s, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Fetching custom git buildpack... done
remote: -----> PHP app detected
remote: -----> Resolved 'composer.lock' requirement for PHP to version 5.6.14.
remote: -----> Installing system packages...
remote:        - PHP 5.6.14
remote:        - Apache 2.4.10
remote:        - Nginx 1.6.0
remote: -----> Installing PHP extensions...
remote:        - mbstring (composer.lock; bundled)
remote:        - zend-opcache (automatic; bundled)
remote: -----> Installing dependencies...
remote:        Composer version 1.0.0-alpha10 2015-04-14 21:18:51
remote:        Loading composer repositories with package information
remote:        Installing dependencies from lock file
...
remote:          - Installing laravel/framework (v5.1.19)
remote:            Downloading: 100%
remote:
remote:        Generating optimized autoload files
remote:        Generating optimized class loader
remote:        Compiling common classes
remote: -----> Preparing runtime environment...
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing... done, 74.5MB
remote: -----> Launching... done, v5
remote:        https://mighty-hamlet-1982.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/mighty-hamlet-1982.git
   1eb2be6..1b70999  main -> main

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
Opening mighty-hamlet-1982... done

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"
[main 1b70999] use errorlog
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push heroku main

As you can see in the code snippet above, a modern standard Laravel installation will already honor the LOG_CHANNEL environment variable for determining the default log destination. Because errorlog is also a logging channel in Laravel’s default logging configuration, you can thus use that environment variable, without any code changes, to set the log destination for your app:

$ heroku config:set LOG_CHANNEL=errorlog

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;
}

With this approach, if you deploy your application to other environments, you must similarly ensure that all traffic arrives through a trusted source, or conditionally only set the trusted proxy when you detect Heroku as the environment your application is running in.

Further reading

  • Read the Heroku PHP Support Dev Center article to learn about available versions, extensions, features and behaviors.
  • Review the instructions on customizing web server and runtime settings for PHP to learn more about configuring Apache, Nginx and PHP.
  • Browse the PHP category on Dev Center for more resources.

Keep reading

  • PHP

Feedback

Log in to submit feedback.

Uploading Files to S3 in PHP Heroku PHP Support

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences