DEV Community

Shah Nawaz Shuvo
Shah Nawaz Shuvo

Posted on

Laravel Horizon with Nginx and Ubuntu 18.04 on DigitalOcean

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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),
    ],

],
Enter fullscreen mode Exit fullscreen mode

Step 3: Installing Horizon


We have to use composer to intall Laravel Horizon.

$ composer require laravel/horizon
Enter fullscreen mode Exit fullscreen mode

After installing Horizon, publish its assets using the horizon:install Artisan command:

$ php artisan horizon:install
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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,
            ],
        ],
    ],
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

After Horizon is run we can find it on http://project.link/horizon. We will see a dashboard page like below:

Horizon

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',
        ]);
    });
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

After installation is complete we have to run the following command to run supervisor at startup.

$ systemctl enable supervisord
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (5)

Collapse
pramanadiputra profile image
Ida Bagus Gede Pramana Adi Putra

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 :)

Collapse
shuv1824 profile image
Shah Nawaz Shuvo Author

Here is a post that you asked for. Hope you will benefit from this. Cheers...

Collapse
pramanadiputra profile image
Ida Bagus Gede Pramana Adi Putra

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

Thread Thread
shuv1824 profile image
Shah Nawaz Shuvo Author

You are welcome brother. I'd love to hang out in Bali. Hope to see you soon...

Collapse
shuv1824 profile image
Shah Nawaz Shuvo Author • Edited on

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.