I had been working with an eCommerce SaaS application a few months ago. Parts of it is built with Laravel 5 and the application is hosted on DigitalOcean on an Ubuntu Server. It's not yet in production but still the setups are pretty much the same. My specific server environment was an Ubuntu 18.04 OS, Nginx 1.14 web server and PHP 7.2
This application has many queued and scheduled tasks to handle. Many tasks had been made automated using Laravel's Scheduler and all the mailing jobs are queued. I used a very handy tool from Laravel called Horizon to monitor and maintain the queues, schedules and events. My intention here is to document the procedure I followed to setup the environment and how I made it work properly.
I am not going to get in details of deploying a laravel project on DigitalOcean droplet. I am diving straight in Horizon setup and it will work for any version of laravel greater than 5.4. I used redis-server
as laravel's queue management storage.
Step 1: Installing Redis Server on Ubuntu 18.04
First of all we have to ssh into our DigitalOcean droplet and after successful login we will get root access to our Ubuntu server.
We have to use the following commands to install Redis
$ apt-get update
$ apt-get upgrade
$ apt-get install redis-server
$ systemctl enable redis-server.service
Redis can be started without a configuration file using a built-in default configuration. But to make any extra parameter changes we can use its configuration file that is: /etc/redis/redis.conf
. We have to edit the Redis configuration file in a text editor to make changes
$ vim /etc/redis/redis.conf
The above configuration tells Redis to remove any key using the LRU algorithm when the max memory of 256mb is reached. Save the configuration file and restart the Redis service:
$ systemctl restart redis-server.service
Use redis-cli tool to verify the connection between Redis server and redis-cli.
$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379>
Step 2: Installing Predis for using Redis with Laravel
Before using Redis with Laravel, you will need to install the predis/predis
package via Composer:
$ composer require predis/predis
After predis
is installed we have to configure it for our application. The configuration file for redis is located in the config/database.php
configuration file. Within this file, you will see a redis
array containing the Redis servers utilized by your application:
/* config/database.php file */
'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
],
Step 3: Installing Horizon
We have to use composer
to intall Laravel Horizon.
$ composer require laravel/horizon
After installing Horizon, publish its assets using the horizon:install Artisan command:
$ php artisan horizon:install
We should also create the failed_jobs table which Laravel will use to store any failed queue jobs:
$ php artisan queue:failed-table
$ php artisan migrate
Horizon's primary configuration file will be located at config/horizon.php
. This configuration file allows us to configure our worker options and each configuration option includes a description of its purpose. In the file we must define connection as redis
.
/* config/horizon.php file */
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'simple',
'processes' => 10,
'tries' => 3,
],
],
'local' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'simple',
'processes' => 3,
'tries' => 3,
],
],
],
Now Horizon is installed. We have to start horizon with an Artisan command and keep the command running to be able to use horizon to process queues at this point. To do that navigate to project root and run:
$ php artisan horizon
After Horizon is run we can find it on http://project.link/horizon
. We will see a dashboard page like below:
Step 4: Dashboard Authorization
But this will work only in local
environment of the application. To use it in production we have to add dashboard authorization
to it so that no one can access the page without logging in. Within the app/Providers/HorizonServiceProvider.php
file, there is a gate method. This authorization gate controls access to Horizon in non-local environments. You are free to modify this gate as needed to restrict access to your Horizon installation:
/**
* Register the Horizon gate.
*
* This gate determines who can access Horizon in non-local environments.
*
* @return void
*/
protected function gate()
{
Gate::define('viewHorizon', function ($user) {
return in_array($user->email, [
'admin@application.com',
]);
});
}
This will allow the user with the email admin@application.com
to access /horizon
route and use horizon.
Step 5: Automate Horizon
If we are deploying Horizon to a live server, we should configure a process monitor to monitor the php artisan horizon command and restart it if it quits unexpectedly. When deploying fresh code to our server, we will need to instruct the master Horizon process to terminate so it can be restarted by your process monitor and receive your code changes. To handle that we will need supervisor
. To install supervisor
:
$ apt-get install supervisor
After installation is complete we have to run the following command to run supervisor
at startup.
$ systemctl enable supervisord
Now we have to create a new file in /etc/supervisor/conf.d/
named horizon.conf
and add the below configuration:
[program:horizon]
process_name=%(program_name)s
command=php /full/path/to/our/application/artisan horizon
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/full/path/to/our/application/horizon.log
Now to read and reload the config and restart the process we have to run the below commands:
$ supervisorctl reread
$ supervisorctl update
$ supervisorctl start horizon
This will setup Laravel horizon properly and make it run automatically on the server. But if some changes have been made
to the Queues or Schedules Horizon must be restarted to make those change take effect on the server. To do that navigate to project root and run:
$ php artisan horizon:terminate
These were pretty much the steps I followed to setup Laravel Horizon on Ubuntu 18.04 server on a DigitalOcean droplet. Hope this guide will help some of you to easily accomplish the task and be more productive.
Top comments (5)
Thanks for your post about this one, I'm surely will use Laravel Horizon too for my app. Can you please post about setup Laravel with Nginx on Ubuntu, and with whatever optimization you've done.
I'm about to deploy my laravel app soon
Thanks :)
Here is a post that you asked for. Hope you will benefit from this. Cheers...
I can tell that this post is new, you made it to fulfill my request. Thank Mr. Nawaz. I'll buy you beer when you are in Bali
You are welcome brother. I'd love to hang out in Bali. Hope to see you soon...
Thank you very much for your feedback. I am glad that you liked my post and that it will help you in your project deployment. Setting up Laravel with Nginx on Ubuntu server is fairly simple. I will definitely write about it as soon as I can. Keep an eye for it. I really appreciate your feedback.