The Laravel ecosystem has great tools for managing automatic deployments: Envoyer, Forge and for serverless deployments there is Vapor. 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 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.
Travis configuration
Let’s assume your project uses PHPUnit 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. 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:
And choose the repositories you want to run the CI on:
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.
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.
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.
The post Set up CI/CD for your Laravel app with GitHub, Travis, and Deployer appeared first on Daniel Werner.
Top comments (0)