Set up CI/CD for your Laravel app with GitHub, Travis, and Deployer
Tags: article, laravel, tutorial, cd
Published: 2019-10-23 19:49:56

---
title: Set up CI/CD for your Laravel app with GitHub, Travis, and Deployer
published: true
date: 2019-10-23 19:30:09 UTC
tags: Article,Laravel,Tutorial,cd
canonical_url: https://www.danielwerner.dev/set-up-ci-cd-for-your-laravel-app-with-github-travis-and-deployer
---

The Laravel ecosystem has great tools for managing automatic deployments: [Envoyer](https://envoyer.io/), [Forge](https://forge.laravel.com/) and for serverless deployments there is [Vapor](https://vapor.laravel.com/). These are easy to use and affordable solutions for automatic deployment of Laravel applications. But if you are developing open source applications, or just looking for a free solution, you can set up [Travis CI](https://travis-ci.org/) for continuous integration and continuous deployment. It is free for public GitHub projects. In this article I am going walk you through all the necessary steps from configuring the server through deployer configuration all the way to setting up Travis.

## Server configuration

I assume you already have a VPS server, and a you are comfortable working in the linux cli. I also won’t deal with the Nginx configuration, only focusing on deployment. The examples here are using an Ubuntu server.  
As a first step create a user for the deployment with disabled password:

```
sudo adduser --disabled-password deploy
```

Let’s assume we are deploying the **example.com** website and it should be deployed to the `/var/www/vhosts/example.com` directory. Go to the `/var/www/vhosts/` and change the owner and the permissions of the `example.com` directory:

```
sudo chown -R youruser:deploy example.com sudo chmod -R 775 example.com
```

With the above command we made the directory writable for `youruser` and also for the `deploy` group (the deploy user is in this group by default). This could be handy if you need to do some modifications to the website manually, for example change values in the `.env` file.

In the next step we’ll allow the deploy user to reload the php-fpm service. Open the `/etc/sudoers`:

```
sudo nano /etc/sudoers
```

And add the following line to the file:

```
deploy ALL=(root) NOPASSWD: /usr/sbin/service php7.2-fpm reload
```

This allows the deploy user to run only the defined command with sudo without asking for a password. This step is optional, but it is recommended to reload the php-fpm service after the deploy, otherwise sometimes the deployed changes are not instantly visible.

## Deployer configuration

Go to the root of your project and install deployer with composer:

```
composer require deployer/deployer --dev
```

You could use the `/vendor/bin/dep init` command to initialize the deployer recipe, but you can just create `deploy.php` in the root of your project and add the following content:

```
<?php
 namespace Deployer;

 require 'recipe/laravel.php';

 // Project name
 set('application', 'Example');

 // Project repository
 set('repository', 'https://github.com/your/repository.git');

 // [Optional] Allocate tty for git clone. Default value is false.
 set('git_tty', true);

 // Shared files/dirs between deploys
 add('shared_files', []);
 add('shared_dirs', []);
 // Writable dirs by web server
 add('writable_dirs', []);

 // Hosts
 host('example.com')
     ->set('user', 'deploy')
     ->set('deploy_path', '/var/www/vhosts/example.com');

 // Tasks
 task('build', function () {
     run('cd {{release_path}} && build');
 });

 // [Optional] if deploy fails automatically unlock.
 after('deploy:failed', 'deploy:unlock');

 // Migrate database before symlink new release.
 before('deploy:symlink', 'artisan:migrate');

 task('reload:php-fpm', function () {
     run('sudo /usr/sbin/service php7.2-fpm reload');
 });

 after('deploy', 'reload:php-fpm');
```

The deployer recipe is quite self explanatory, you should make the following changes to the file:

Set up the url of the repository

```
 // Project repository
 set('repository', 'https://github.com/your/repository.git'); 
```

Change the host, user and deploy_path if needed

```
host('example.com')
     ->set('user', 'deploy')
     ->set('deploy_path', '/var/www/vhosts/example.com');
```

More details about deployer configuration can be found in deployer’s [documentation](https://deployer.org/docs/configuration.html).

## Travis configuration

Let’s assume your project uses [PHPUnit](https://phpunit.de/) as test framework, as usually Laravel projects do. We’ll set up the Travic CI to run all the tests, and if the tests run successfully it will automatically deploy the application.

### Connect Travis with GitHub

Before you can use the CI, you’d need to create an account on [travis-ci-org](https://travis-ci.org/). The simplest way to do so is to sign in with GitHub. After you’ve connected your GitHub account with Travis, you can enable travis for your public repositories, by clicking on the “+” beside My Repositories:

![](https://www.wernerd.info/wp-content/uploads/2019/10/image-4.png)

And choose the repositories you want to run the CI on:

![](https://www.wernerd.info/wp-content/uploads/2019/10/image-3-1024x685.png)

### Install Travis CLI

We will allow the deploy user to log in to our server using its private key, but we don’t want to put the private key into a public repository. We are going to use travis cli to encrypt our private key and the encrypted key would be committed and pushed to the repository. You need ruby for installing and running the Travis CLI:

```
gem install travis -v 1.8.10 --no-rdoc --no-ri
```

If you need further information on how to do this, detailed installation instructions can be found [here](https://github.com/travis-ci/travis.rb#installation).

### Create and encrypt the key

Go to your projects root directory, and generate the key pair by running the `ssh-keygen`:

```
ssh-keygen -t rsa -b 4096 -C 'build@travis-ci.org' -f ./deploy_rsa
```

This creates the private/public key pair. You should **NEVER** commit the private key to the repository!  
Now we can encrypt the private key using the CLI tool, so first log in to travis:

```
travis login --org
```

If you have signed it to travis with GitHub, it might ask you for your GitHub credentials, just follow the on screen instructions to login.

Encrypt the private key and add it to Travis environment:

```
travis encrypt-file deploy_rsa --add
```

The above command creates the encrypted key file: `deploy_rsa.enc` and adds the decrypt key as and environment variable to the `.travis.yml`.

Commit the `deploy_rsa.enc` to the repository, and delete the unencrypted private key:

```
rm deploy_rsa
```

SSH into your server and allow deploy user to login with the previously generated keys by copying the content of the `deploy_rsa.pub` to the `/home/deploy/.ssh/authorized_keys` file:

```
sudo nano /home/deploy/.ssh/authorized_keys
```

When it is done, the public key can also be deleted from the project:

```
rm deploy_rsa
```

### Configure the .travis.yml

As a first step we set up travis to run our unit tests by adding the following content to the `.travis.yml` file

```
language: php
php:
  - 7.2
before_script:
  - composer self-update
  - composer install --no-interaction
script:
  - vendor/bin/phpunit 
```

The next step is to decrypt the private key and set up the ssh configuration:

```
before_deploy:
  - openssl aes-256-cbc -K $encrypted_<put_your_key_here>_key -iv $encrypted_<put_your_key_here>_iv -in deploy_rsa.enc -out /tmp/deploy_rsa -d
  - eval "$(ssh-agent -s)"
  - chmod 600 /tmp/deploy_rsa
  - ssh-add /tmp/deploy_rsa
  - echo -e "HostName example.com\n\tStrictHostKeyChecking no\n\t"User deploy >> ~/.ssh/config
```

Now we are ready to set up the deployment, by adding the following lines to the `.travis.yml`:

```
deploy:
  skip_cleanup: true
  provider: script
  script: vendor/bin/dep deploy
  on:
    branch: master
```

We are using the **script**  **deploy provider** , skipping the cleanup after the build and run deployer on the **master** branch.

The deploy will only only run if the command(s) in the **script** section have been finished without error. The deployment is also skipped when the build is running on a pull request. For more information about Travis deployments please visit the Travis deployment [documentation page](https://docs.travis-ci.com/user/deployment).

If everything went well all the tests should run and the changes should be automatically deployed to your server when you push changes to the master branch.

## Conclusion

It is not so straightforward to set up a CI/CD pipeline manually as using Envoyer and Forge, but hopefully this article made it a bit easier for you.

If you have any questions or comments, please let me know in the comments section below.

Special thanks to Nicolas Martignoni, I learned the basics of Travis deployment, and key encryption from his blog [post](https://blog.martignoni.net/2019/03/deploy-your-hugo-site/).

The post [Set up CI/CD for your Laravel app with GitHub, Travis, and Deployer](https://www.wernerd.info/set-up-ci-cd-for-your-laravel-app-with-github-travis-and-deployer/) appeared first on [Daniel Werner](https://www.wernerd.info).