Deploying a Laravel Application

Back in October, I wrote about getting started with the Laravel (php) framework. In that post, I outlined how to set up a basic Laravel application. Once I had figured that out, I dove head first into rebuilding our custom content management system (CMS) using Laravel. I have successfully completed that task, along with 3 packages containing additional functionality that can be added to a site as needed. We now have a brand spanking new CMS package that can be turned into an awesome website for a client.

Over the past couple of weeks, I took this CMS package and rebuilt my professional website, partly so that I could test the system out and work out the bugs before using it on an actual client project, but mostly so I could replace the website I had with a better (looking and functioning) site. I had the site all finished up and all content entered into my local version of the site on Monday. So that left me with just one thing to do … deploy it to the VPS server where I host my websites.

Laravel Code Base
Laravel Code Base

When I launch a website at work, I generally follow the same procedure. I zip up the files for the site (from my local version of the site, from the beta version of the site, or from the Git repository if there is one for the site) and upload them to the web server via command line. I then SSH into the web server to unzip the files. Normally all of the files for the site go into the public_html directory on the web server (i.e. /home/accountname/public_html/). Because of how the Laravel code base is structured (refer to the screenshot), I had to come up with a new plan for this CMS.

The files for the public display of the website are inside of the public directory within the Laravel code base. This directory is at the same level as the Laravel core files. If you put the entire code base into the public_html directory on your server, then your site will have URLs that contain the word “public” (i.e. http://www.domain.com/public/) and this is probably something that you don’t want. I know I don’t. In order to deploy a Laravel application so that the URLs are “clean” (i.e. http://www.domain.com), you need to split up the Laravel core files and the “public” files.

I used my experience launching my website to put together the following procedure for deploying a Laravel application. I left out the steps that were specific to how I built the CMS. Hopefully you will find it useful if you are deploying your own Laravel application.

0) Before you start this launch procedure, I recommend you put your site into a forced maintenance mode via the .htaccess file. What I mean is that you force anyone (except for you) coming to your website to a static maintenance page. This will allow you to set up your site without having users visit it and see errors because you’re in the middle of the process.

1) Create a database and database user in the control panel for your hosting account. If your application does not use a database, you can skip this step.

2) Make sure that your web server meets the server requirements for the Laravel code base. On my server, I needed to enable the proc_open and exec php functions since they were disabled by default by my web host. The proc_open function is needed when installing Composer packages (actually it is needed for the Artisan commands that are run after the packages are installed by Composer) and run Artisan commands, and the exec function is needed if any of the Artisan commands that you plan on running are asking for information. If you don’t have access to a control panel (such as WHM) to make these changes, you will have to ask your web host to make them for you.

Also make sure that your server meets the requirements for any of the Composer packages that you are using in your project. I included the Glide image manipulation package in the portfolio section of my website, so I had to enable the php Fileinfo and Exif extensions.

3) On your web server, create a directory that is at the same level as the public_html directory that will contain the Laravel core files. I recommend you call this directory laravel (i.e. /home/accountname/laravel/).

4) Upload the following directories and files from your project into the directory you created in step #3. I have excluded some of the directories and files from my code base because they are only necessary during development.

  • app/
  • bootstrap/
  • config/
  • database/
  • resources/
  • storage/
  • artisan
  • composer.json
  • composer.lock
  • .env

5) Upload the contents of the public directory from your project into the public_html directory on your web server (i.e. /home/accountname/public_html/) .

6) Modify the laravel/.env file so that it contains the values specific to your application, such as database connection information.

7) Modify the laravel/bootstrap/app.php file to set the public.path value. Add the following block of code to the file before the “Bind Important Interfaces” block. Adjust the path as needed if you are deploying the application on a subdomain.

/*
|--------------------------------------------------------------------------
| Public Path
|--------------------------------------------------------------------------
|
| Set the path to the Laravel "public" directory so that any files/packages
| that use app('path.public') to get the "public" path find the right path.
| DO NOT include a trailing slash on the path.
|
*/
$app->bind('path.public', function ()
{
    return __DIR__.'/../../public_html';
});

8) Modify the public_html/index.php file to adjust the paths to point to the directory containing the Laravel core files. Refer to the following code block. Again, adjust the paths as needed if you are deploying the application on a subdomain.

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels nice to relax.
|
*/

require __DIR__.'/../laravel/bootstrap/autoload.php';

/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/

$app = require_once __DIR__.'/../laravel/bootstrap/app.php';

9) SSH into your web server (if you haven’t already) and navigate to the laravel directory that you created in step #3. I recommend you use the account credentials for the hosting account where you are installing the application rather than the credentials for the root user.

10) Install Composer. You will need Composer to install the dependencies needed for Laravel to run.

curl -sS https://getcomposer.org/installer | php

11) Install the Composer packages needed by Laravel core and any additional packages that your application is using. The --no-dev flag will exclude any packages that you included in your composer.json file that were strictly for development (i.e. the packages listed in the require-dev block).

php composer.phar install --no-dev

12) Generate your application key. This command will generate a random key and update your laravel/.env file with the value.

php artisan key:generate

13) If your application uses a database, run the following commands to run your migration files and execute your seeders. If you don’t have any seeders, then you can skip the second command.

php artisan migrate
php artisan db:seed

Your website should now be up and running. Depending on how you set up your application, you may have to include some additional steps, but this should get a basic application up and running on your server.

My actual launch procedure included running an Artisan command that I wrote to take care of setting up the core CMS package, including running the migrations and seeders and inserting some additional information into the database. This command replaced step #13. Two of the packages that I developed for the system required me to set up some SSH keys on my server and adding them to the Bitbucket git repository where they are located (because they are private packages). I also ran some commands on my local server before migrating the public files to the VPS server in order to install some additional development dependencies and compile some assets and publish them to the public directory. But I’ll leave that for a future post. 🙂