2017-05-30 #laravel

Deploying With Envoy

In this tutorial we're going to look at how you can use Envoy to make it very easy to deploy your Laravel applications. Envoy provides a nice blade style syntax way of running commands on your remote servers. You can use it for multiple purposes but the most common way I've found is for deployments. It allows you to enter the command envoy run deploy to quickly deploy your code.


Before you start using Envoy on your Laravel application you first need to install it by using composer.

composer global require "laravel/envoy=~1.0"


To get started with Envoy you need to create a file at the root level of your project called Envoy.blade.php Now you can use the normal Laravel blade syntax to define the commands you want to run on the remote server. Everything you do in Envoy needs to be done by tasks. You can also define different servers by using @servers. So, if you want to run a command on a remote server to list the files on the server you can use the following code.

@servers(['web' => ['[email protected]']])

@task('foo', ['on' => 'web'])
    ls -la

This defines a new server called web with a task called foo. You can run this command at the root of project by running the command

envoy run foo

If you want to always run some code before you run through the tasks you can use a @setup directive to define variable you can use in your tasks.

    $now = new DateTime();

    $environment = isset($env) ? $env : "testing";

If you want to pass in different variables into your script you can define this on the command line when calling envoy, for the branch of passing the environment you want to deploy you can use the command.

envoy run deploy --env=production

You'll now be able to pick up this variable in your Envoy script by using the PHP syntax $env. You can also group tasks together by creating stories, for example when you run a deploy script you want to get the code from git and then run an install on composer to bring in the dependencies and you will define them with the following.

@servers(['web' => ''])


    git pull origin master

    composer install

Creating A Deployment Script

Now that we have an understanding of how Envoy works we can create a deployment script, the deployment script will need to do multiple activities. - Clone git repository into a new folder

  • Change permissions on storage folder
  • Apply the correct environment file
  • Install composer dependencies
  • Run migration files
  • Restart any queue runners
  • Run artisan optimize
  • Symlink the new release folder with the current version of the site
  • Clean up old code

Setup The Deployment

In the setup section, we need to define the server we want to use, the repository we want to use, the path to deploy into, the timestamp of the deployment, the environment, the branch of the repository and the release folder.

    throw new Exception('User option not set.');

$server = $user . '@';
$repo = '[email protected]:paulund/vagrant-ubuntu-nginx.git';
$path = '/var/www/website';

if ( substr($path, 0, 1) !== '/' ) throw new Exception('Careful - your deployment path does not begin with /');

$date = ( new DateTime )->format('YmdHis');
$env = isset($env) ? $env : "production";

$branch = isset($branch) ? $branch : "master";
$path = rtrim($path, '/');
$release = $path.'/'.$date;

Create Deploy Story

We're going to create a deploy story which will perform all the tasks that we need to do during the deployment.


At the start of the deployment, we need to clone the repository from the required branch into the release folder.

cd {{ $path }};
echo "Deployment ({{ $date }}) started";
git clone {{ $repo }} --branch={{ $branch }} --depth=1 -q {{ $release }} ;
echo "Repository cloned";

After the code has been cloned into the new folder then we can change the permissions of the bootstrap and the storage folder. We'll then take the env variable and copy the required environment to the .env file.

cd {{ $release }};
chmod 777 bootstrap/*
echo "Bootstrap permissions done";

chmod 777 -R {{ $release }}/storage
echo "Changed storage permission"

cp {{ $release }}/.env.{{ $env }} {{ $release }}/.env
echo "Change Environment link"

Then we can install the composer dependencies inside the release folder.

cd {{ $release }};
composer install --no-interaction --quiet;

We're able to update the database with any new changes by running the migration files for the correct environment.

php {{ $release }}/artisan migrate --env={{ $env }} --force --no-interaction;

If you're running any queue workers then you may need to restart the queues.

php {{ $release }}/artisan queue:restart --no-interaction;

You will need to clear your application cache to make sure everything has refreshed correctly.

php {{ $release }}/artisan view:clear --quiet;
php {{ $release }}/artisan cache:clear --quiet;
php {{ $release }}/artisan config:cache --quiet;
echo 'Cache cleared';

You can optimize the class loader by running the following command.

php {{ $release }}/artisan optimize --quiet;

At the end of the deployment you can add the symlink from the release folder to the current folder

ln -nfs {{ $release }} {{ $path }}/current;
echo "Deployment ({{ $date }}) finished";

As you clone into a new release folder these can add up over time and you can use the following command to remove any old folders.

cd {{ $path }};
find . -maxdepth 1 -name "20*" -mmin +2880 | head -n 5 | xargs rm -Rf;
echo "Cleaned up old deployments";

To run this envoy script you can use the command

envoy run deploy --env=production --user=paulund

To deploy your application onto your server, if you also want to use this for your UAT server then you simply need to add the server to the web server array and change the environment variable you pass into the script.