Install Laravel 5
Laravel is the most PHPopular framework. Learn how to install and tune Laravel 5 on fortrabbit.
Get ready
Please make sure to have followed our get ready guide before starting here. You will also need a local Laravel installation.
MIND: This the install guide for Laravel version 5. We have an Laravel install guide for a newer version (9). Check out that article as well, it includes more up-to-date information.
Quick start
Execute the following in your local terminal to start from scratch with a fresh new Laravel installation on fortrabbit (see below on how to add an existing project):
# 1. Use Composer to create a local Laravel project named like your App
$ composer create-project laravel/laravel --prefer-dist {{app-name}}
# this installs Laravel locally and will take a while
# 2. Change into the folder
$ cd {{app-name}}
# 3. Initialize a local Git repo
$ git init .
# 4. Add all files
$ git add -A
# 5. Commit files for the first time
$ git commit -m 'Initial'
# 6. Add fortrabbit as a remote
$ git remote add fortrabbit {{ssh-user}}@deploy.{{region}}.frbit.com:{{app-name}}.git
# 7. Initial push and upstream
$ git push -u fortrabbit main
# this will install Laravel on remote and take another while
# The next deployments will be much faster
# 8. Push from now on only
$ git push
Got an error? Please see the access troubleshooting. Did it work? Cool, when this is done, you can visit your App URL in the browser to see the Laravel welcome screen:
Tune
Until now this is a vanilla Laravel. Now, make it yours.
MySQL
Use App secrets to attain database credentials. Replace all contents from config/database.php
in your editor like so:
<?php
// locally: use standard settings
$mysql = [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
];
// on fortrabbit: construct credentials from App secrets
if (isset($_SERVER['APP_SECRETS'])) {
$secrets = json_decode(file_get_contents($_SERVER['APP_SECRETS']), true);
$mysql = [
'driver' => 'mysql',
'host' => $secrets['MYSQL']['HOST'],
'port' => $secrets['MYSQL']['PORT'],
'database' => $secrets['MYSQL']['DATABASE'],
'username' => $secrets['MYSQL']['USER'],
'password' => $secrets['MYSQL']['PASSWORD'],
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
];
}
return [
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'mysql' => $mysql,
],
'migrations' => 'migrations'
// possible other code …
];
This example contains environment detection, so the App can run on your local machine with your local database, as well as with the one on fortrabbit.
Laravel uses the utf8mb4
character set by default, which includes support for storing "emojis" in the database.
You need to manually configure the default string length generated by migrations in order for MySQL to create indexes for them in your `AppServiceProvider:
use Illuminate\Support\Facades\Schema;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191);
}
MySQL access from local
Please see the MySQL article on how to access the database remotely from your computer.
Update database with artisan migrate command
You can execute remote commands via SSH, for example:
$ ssh {{ssh-user}}@deploy.{{region}}.frbit.com 'php artisan migrate --force'
$ ssh {{ssh-user}}@deploy.{{region}}.frbit.com 'php artisan migrate:rollback --force'
If APP_ENV
is set to production
- which is the default - then Laravel expects --force
for migrate commands.
You can also add this command to your composer.json
to have it run automatically every time you push changes.
"scripts": {
"post-install-cmd": [
"php artisan migrate --no-interaction --force",
],
}
With that in place, any time you deploy your code, database changes will be applied immediately. If no database changes are required, nothing happens, so it is safe to run all the time. Just make sure to test your upgrades and migrations locally first.
Database Session
Using the database
driver is the easiest way to persist sessions cross multiple PHP nodes. Since it requires a migration it is a good exercise.
# Create a migration for the session table locally
$ php artisan session:table
# Apply the migration locally
$ php artisan migrate
# Add, commit and push the migration file
$ git add .
$ git commit -m "session migration"
$ git push
# Run the migration
$ ssh {{ssh-user}}@deploy.{{region}}.frbit.com php artisan migrate --force
Add a new ENV var SESSION_DRIVER
with the value database
in the Dashboard to make use of the database sessions.
Object Storage
fortrabbit Apps have an ephemeral storage. If you require a persistent storage, for user uploads or any other runtime data your App creates, you can use our Object Storage Component. Once you have booked the Component in the Dashboard the credentials will become available via the App secrets.
Using our object-storage
driver reduces the configuration efforts to a minimum.
composer require fortrabbit/laravel-object-storage
To make your App access the Object Storage, open up config/filesystems.php
and modify it as following:
return [
'default' => env('FILESYSTEM_DRIVER', 'local'),
'cloud' => env('FILESYSTEM_CLOUD', 's3'),
'disks' => [
's3' => [
'driver' => 'object-storage'
// no further settings required
],
// other disk …
]
];
If you want to use the Object Storage with your fortrabbit App and a local storage with your local development setup then replace the "default" value in filesystems.php
as well.
Set FILESYSTEM_DRIVER
in your local .env
file to the value local
and the environment variables in the Dashboard to the value s3
.
Until Laravel 5.6 the env var FS_TYPE
was used instead of FILESYSTEM_DRIVER
.
Laravel Mix
You can use Mix locally - not on fortrabbit as there is no Node on remote. You can extend the Mix with the webpack-s3-plugin
to export your minified assets to the Object Storage. This is how it works. To start, execute in your terminal:
# Get your Object Storage credentials
$ ssh {{app-name}}@deploy.{{region}}.frbit.com secrets OBJECT_STORAGE
Then put the values to your .env file an prefix the keys with OBJECT_STORAGE_
. In your webpack.mix.js
you load the plugin and configure it with the env vars:
const mix = require('laravel-mix');
const S3Plugin = require('webpack-s3-plugin');
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
// S3Plugin config
if (process.env.npm_config_env === 'production') {
mix.webpackConfig({
plugins: [
new S3Plugin({
// Only upload css and js
include: /.*\.(css|js)/,
s3Options: {
accessKeyId: process.env.OBJECT_STORAGE_KEY,
secretAccessKey: process.env.OBJECT_STORAGE_SECRET,
endpoint: process.env.OBJECT_STORAGE_SERVER,
region: process.env.OBJECT_STORAGE_REGION,
signatureVersion: 'v2'
},
s3UploadOptions: {
Bucket: process.env.OBJECT_STORAGE_BUCKET
},
// the source dir
directory: 'public'
})
]
});
}
Back in your terminal:
# Install package via NPM
$ npm install webpack-s3-plugin --save
# Run the publish task
$ npm run production --env=production
Mind that you need to tell your source code to look for the minified CSS & JS files on the offshore Object Storage.
Logging
Per default Laravel writes all logs to storage/log/..
. Since you don't have direct file access, you need to configure Laravel to write to the PHP error_log
method instead.
In Laravel 5.6 - 5.8
Laravel's new logging.php
config allows you to define various log channels. Make sure to add the errorlog
channel to the stack
or simply set the default channel via ENV var:
LOG_CHANNEL=errorlog
In Laravel 5.1 - 5.5
That's easily done: open boostrap/app.php
and add the following just before the return $app
statement at the bottom:
$app->configureMonologUsing(function($monolog) {
// chose the error_log handler
$handler = new \Monolog\Handler\ErrorLogHandler();
// time will already be logged -> change default format
$handler->setFormatter(new \Monolog\Formatter\LineFormatter('%channel%.%level_name%: %message% %context% %extra%'));
$monolog->pushHandler($handler);
});
You can now use our regular log access to view the stream.
Do you need more than live logs? Consider Flare, the error tracker for Laravel, which provides a searchable log archive and SMS, Email & Slack notifications.
Memcache
Make sure you enabled the Memcache Component. Then you can use the App Secrets to attain your credentials. Modify the memcached
connection in your config/cache.php
like so:
// locally: use standard settings
$servers = [[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
]];
// on fortrabbit: construct credentials from App secrets
if (getenv('APP_SECRETS')) {
$secrets = json_decode(file_get_contents(getenv('APP_SECRETS')), true);
$servers = [[
'host' => $secrets['MEMCACHE']['HOST1'],
'port' => $secrets['MEMCACHE']['PORT1'],
'weight' => 100
]];
if ($secrets['MEMCACHE']['COUNT'] > 1) {
$servers []= [
'host' => $secrets['MEMCACHE']['HOST2'],
'port' => $secrets['MEMCACHE']['PORT2'],
'weight' => 100
];
}
}
if (extension_loaded('memcached')) {
$timeout_ms = 50;
$options = [
// Assure that dead servers are properly removed and ...
\Memcached::OPT_REMOVE_FAILED_SERVERS => true,
// ... retried after a short while (here: 2 seconds)
\Memcached::OPT_RETRY_TIMEOUT => 2,
// KETAMA must be enabled so that replication can be used
\Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
// Replicate the data, write it to both memcached servers
\Memcached::OPT_NUMBER_OF_REPLICAS => 1,
// Those values assure that a dead (due to increased latency or
// really unresponsive) memcached server is dropped fast
\Memcached::OPT_POLL_TIMEOUT => $timeout_ms, // milliseconds
\Memcached::OPT_SEND_TIMEOUT => $timeout_ms * 1000, // microseconds
\Memcached::OPT_RECV_TIMEOUT => $timeout_ms * 1000, // microseconds
\Memcached::OPT_CONNECT_TIMEOUT => $timeout_ms, // milliseconds
// Further performance tuning
\Memcached::OPT_NO_BLOCK => true,
];
}
return [
// other code …
'stores' => [
// other code …
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'servers' => $servers,
'options' => $options ?? []
],
// other code …
],
// other code …
];
In addition, set the CACHE_DRIVER
environment variable so that you can use memcached
in your production App on fortrabbit. If you don't have memcached on your local machine, set the driver to file
or array
via .env
.
Redis
Redis can be used in Laravel as a cache or a queue or both. First integrate with Redis Cloud then configure the redis database connection in config/database.php
:
// locally: use standards
$redis = [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
];
// on fortrabbit: construct credentials from App secrets
if (isset(getenv('APP_SECRETS'))) {
$secrets = json_decode(file_get_contents(getenv('APP_SECRETS')), true);
$redis = [
'host' => $secrets['CUSTOM']['REDIS_HOST'],
'port' => $secrets['CUSTOM']['REDIS_PORT'],
'password' => $secrets['CUSTOM']['REDIS_PASSWORD']
'persistent' => 1
];
}
return [
// other code …
'redis' => [
'cluster' => false,
'default' => $redis
],
// other code …
];
If you plan on using Redis as a cache, then open config/cache.php
and set the CACHE_DRIVER
environment variable to redis
in the Dashboard). For queue usage see below.
Queue
Laravel supports multiple queue drivers. One which can be used with fortrabbit out of the box is database
, which simple uses your database connection as a queue. That's great for small use-cases and tinkering, but if your App handles very many queue messages you should consider Redis.
Once you've decided the queue you want to use just open config/queue.php
and set default
to either redis
, database
, sqs
- or even better: set the QUEUE_CONNECTION
environment variable accordingly in the Dashboard.
To run php artisan queue:work
in the background, spin up a new Worker and define the artisan command as a Nonstop Job.
Make sure you have added VladimirYuldashev\LaravelQueueRabbitMQ\LaravelQueueRabbitMQServiceProvider::class
to providers
in config/app.php
.
Lastly set the QUEUE_DRIVER
environment variable in the Dashboard to rabbitmq
.
Using envoy
Easy. Here is an Envoy.blade.php
example:
@servers(['fr' => '{{ssh-user}}@deploy.{{region}}.frbit.com'])
@task('ls', ['on' => 'fr'])
ls -lha
@endtask
@task('migrate', ['on' => 'fr'])
php artisan migrate
@endtask
Then execute locally:
$ envoy run ls
$ envoy run migrate
Sending mail
You can not use sendmail on fortrabbit but Laravel provides a API over the popular SwiftMailer library. The mail configuration file is app/config/mail.php
, and contains options allowing you to change your SMTP host, port, and credentials, as well as set a global form address for all messages delivered by the library.
Using artisan down
artisan down
generates the file storage/framework/down
, which is then checked from your App's HTTP kernel as middleware — as far as we know. Modifying files via SSH remote execution does only affect the deployment Node, not your live App (i.e. any file changes via SSH remote exec do not affect your App).
There are at least two options to do this:
- Add
artisan down
as apost-install-cmd
script incomposer.json
, thengit push
(remove the command and push again to bring it back online) - Use a custom middleware and command which uses another source than a file, eg memcache or database
Add an existing project
You can also push your existing Laravel installation to fortrabbit. When you already using Git, you can add fortrabbit as an additional remote, like described above under point 6. When moving from another host to fortrabbit, please also read our migration guide as well.