The Ultimate Cheatsheet for Deploying Laravel Apps To Heroku
If you’re like me, you use Heroku to host many of your personal web projects. And why not? Heroku has become so popular because it spares developers the hassle of managing servers and all that, allowing you to achieve a lot with a few clicks or commands. Best of all, its free tier actually gives you a lot of freedom.
And if you’re like me, you’ve realized that, while Heroku supports PHP apps, it really wasn’t built for the traditional PHP/MySQL stack, thus you might find yourself running into a few snags here and there. Having hosted a few Laravel projects on Heroku, I decided to come up with this list of helpful tips so others can avoid many of the issues I battled with initially.
To get the most out of this article, you should read Heroku’s Devcenter article on deploying Laravel apps to Heroku first.
CLI vs Web Dashboard
Heroku has this nifty tool called the heroku-cli that allows you to manage your apps from the command line. Most of these functions can also be accessed online at your Heroku app dashboard at http://dashboard.heroku.com/app/<appname>. I recommend installing the CLI though. The web dashboard is useful for when you’ce on the move. And speaking of “on the move”…
Use the mobile app
Bet you didn’t know there was a mobile app. Well, you do now. An unofficial one called LovelyNezumi. I use it a lot to monitor logs, set config vars, run migrations, add collaborators and a lot more. It’s got a clean and simplistic UI, just like Heroku, and it’s easy to use. Best of all, it’s free. Kudos to the developer. Get it here.
Config vars in Heroku replace your .env file. They can be set in your app dashboard or via the heroku-cli:
heroku config:set APP_ENV=local
At a minimum, you’ll need to set the APP_KEY var for your app to run. Here’s a little script that does that (if you have PHP7 and your
config.app.cipher is set to the default
# on Bash KEY=`php -r "echo 'base64:’.base64_encode(random_bytes(32));"` heroku config:set APP_KEY=$KEY # on Windows PowerShell $KEY=`php -r "echo 'base64:’.base64_encode(random_bytes(32));"` heroku config:set APP_KEY=$KEY
If you don’t have PHP7, just copy APP_KEY from a local
See here for more on config vars
Procfile and buildpacks
Before making your first push to Heroku, you should create a file named
Procfile in your project directory with the following contents:
web: vendor/bin/heroku-php-apache2 public/
This tells Heroku your public document root.
Also, sometimes you might run into the error “Could not detect buildpack” when pushing to Heroku. To fix this, just run
heroku buildpacks:set heroku/php in your terminal.
Bad news here: Heroku has an ephemeral file system. This means that any files you store to the local disk get deleted at least once every 24 hours without you doing anything. Worse, they’re also deleted every time you push to Heroku.
How to get around this? Use a different storage location. Laravel supports different drivers for file storage, including Amazon S3. Instructions for using S3 can be found here.
Because of the filesystem’s temporary nature discussed above, using Laravel’s default log config won’t work. You need to change the log driver, as described here. I prefer doing this without changing any code, so I can retain the usual settings on your local. Just set config var APP_LOG=errorlog. You can view your app logs on your dashboard/mobile app or by running
Cache and Sessions
The default driver in Laravel for both cache and sessions is
file. If you plan on using caching/sessions in your application, you’ll need to change these to either
cookie for sessions). Again, all you need to change are config vars CACHE_DRIVER and SESSION_DRIVER.
If you choose to use
memcached, you’ll need to install the Heroku add-on Memcachier. (Don’t forget to
composer require ext-memcached:*.) See here for more details on Memcachier and here for more on sessions.
Using SQLite on Heroku is a very bad idea. Don’t do it, except you want your database getting deleted every time you push. You can read more on that here.
Ah, the traditional companion of PHP. Heroku supports MySQL through add-ons such as ClearDB and JawsDB.After installing the add-on, you’ll need to set the config var DB_CONNECTION=mysql and modify your
<?php $dbUrl = parse_url(env("CLEARDB_DATABASE_URL")); return [ // … 'mysql' => [ 'driver' => 'mysql’, 'host' => isset($dbUrl["host"]) ? $dbUrl["host"] : env("DB_HOST"), 'port' => isset($dbUrl["port"]) ? $dbUrl["port"] : env("DB_PORT"), 'database' => isset($dbUrl["path"]) ? ltrim($dbUrl["path"], '/') : env("DB_DATABASE"), 'username' => isset($dbUrl["user"]) ? $dbUrl["user"] : env("DB_USERNAME"), 'password' => isset($dbUrl["pass"]) ? $dbUrl["pass"] : env("DB_PASSWORD"), 'charset' => 'utf8mb4’, 'collation' => 'utf8mb4_unicode_ci’, 'prefix' => '’, 'strict' => true, 'engine' => null, ], ];
This is Heroku’s recommended database. To use it, install the add-on and change your DB_CONNECTION to pgsql. Then update your
<?php $dbUrl = parse_url(env("DATABASE_URL")); return [ // … ’pgsql' => [ 'driver' => 'pgsql’, 'host' => isset($dbUrl["host"]) ? $dbUrl["host"] : env("DB_HOST"), 'port' => isset($dbUrl["port"]) ? $dbUrl["port"] : env("DB_PORT"), 'database' => isset($dbUrl["path"]) ? ltrim($dbUrl["path"], '/') : env("DB_DATABASE"), 'username' => isset($dbUrl["user"]) ? $dbUrl["user"] : env("DB_USERNAME"), 'password' => isset($dbUrl["pass"]) ? $dbUrl["pass"] : env("DB_PASSWORD"), 'charset' => 'utf8’, 'prefix' => '’, 'schema' => 'public’, 'sslmode' => 'prefer’, ], ];
More details on Heroku Postgres can be found here.
To use queues on Heroku, youll need to add this line to your Procfile:
queue: php artisan queue:work
Essentially, this creates a worker dyno called queue (you can name it whateer you wish), started with the command
php artisan queue:work which is the command for starting the queue listener (see the documentation);
SSH (or close enough, anyway)
Heroku has this awesome feature called one-off dynos that allow you to perform admin tasks, such as running custom scripts, migrations, caching routes and clearing cached items. Essentially, you can run any terminal command. Here’s all you need to do:
$ heroku run php artisan migrate Migrations completed succesfully $ heroku run bash Running bash attached to terminal... up, run.1 ~ $ php artisan db:seed Seeding data...done. ~ $ ls app bootstrap config ... Procfile ~ $ php artisan inspire "Genius is one percent inspiration and ninety-nine percent perspiration. - Thomas Edison"
For the full gist on one-off dynos, go here.
Laravel and Heroku are both powerful platforms which are straightforward to use, for the most part. While I do try out other SaaS providers, most of the time I stick with Heroku, because of its roomy free tier, wonderful add-ons and complete documentation. The nice UI doesn’t hurt too. Have a lovely day with Heroku and Laravel.
Do you know any other useful tips for hosting Laravel apps on Heroku? Mention it down in the comments so we can all learn.
Thanks for reading. If you enjoyed this article, please recommend and share.
Hey👋. I write about interesting software engineering challenges. Want to get updated when I publish new posts? Just visit tntcl.app/blog.shalvah.me.
(Confession: I built Tentacle.✋ It helps you keep a clean inbox by combining your favourite blogs into one weekly newsletter.)