Deployer is Zero downtime deployment tool, Automatic server provisioning tool, which is written in PHP with support for popular frameworks out of the box.
In this tutorial, you would learn deployer installation, multi server and multi environment config, multi tasks, tasks group as well.
Installation
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep
cd your-project-direction
dep init
Understanding Deployment Process
Flow is very simple. first ssh login to servers then git clone and make some instruction.

In this diagram, we have multi production servers and multi testing server.
Define Servers (hosts)
To connect to remote host we need to specify IP address, identity key or private key.
We can add our identity key directly into host definition, but better to put it in ~/.ssh/config file:
Host *
IdentitiesOnly yes
Host gatewayServer
HostName xxx.xxx.xxx.xxx
User ec2-user
ForwardAgent yes
IdentityFile ~/ssh/key/gatewayServer.pem
host production-svr1
HostName 10.0.1.12
User ec2-user
ForwardAgent yes
IdentityFile ~/ssh/key/productionsvr.pem
ProxyCommand ssh -W %h:%p gatewayServer
host production-svr2
HostName 10.0.1.13
User ec2-user
ForwardAgent yes
IdentityFile ~/ssh/key/productionsvr.pem
ProxyCommand ssh -W %h:%p gatewayServer
host testing-svr1
HostName 10.0.1.14
User ec2-user
ForwardAgent yes
IdentityFile ~/ssh/key/testingsvr.pem
ProxyCommand ssh -W %h:%p gatewayServer
host testing-svr2
HostName 10.0.1.15
User ec2-user
ForwardAgent yes
IdentityFile ~/ssh/key/testingsvr.pem
ProxyCommand ssh -W %h:%p gatewayServer
"ForwardAgent yes" is the meaning of forwarding ssh agent.
ssh login flow ( ssh from localhost to => gateway => production/testing servers ).
we use gatewayServer as jump server.
Define Stages
Define production and testing stage as the following code. "deployer.php"
<?php
namespace Deployer;
require 'recipe/common.php';
/*
Production servers
production-svr1: 10.0.1.12
production-svr1: 10.0.1.13
Testing servers
testing-svr1: 10.0.1.14
testing-svr1: 10.0.1.15
*/
host('production-svr1','production-svr2')
->stage('production')
->user('ec2-user');
host('testing-svr1','testing-svr2')
->stage('testing')
->user('ec2-user');
Define Tasks and variables
In this example, I will execute "pwd" command on the servers and use the "deploy_path" variable.
<?php
namespace Deployer;
require 'recipe/common.php';
/*
Production servers
production-svr1: 10.0.1.12
production-svr1: 10.0.1.13
Testing servers
testing-svr1: 10.0.1.14
testing-svr1: 10.0.1.15
*/
host('production-svr1','production-svr2')
->stage('production')
->user('ec2-user')
->set('deploy_path','/var/www/html/production');
host('testing-svr1','testing-svr2')
->stage('testing')
->user('ec2-user')
->set('deploy_path','/var/www/html/testing')
task('pwdCommand', function () {
cd('{{deploy_path}}');
$msg = run("pwd");
writeln($msg);
});
OutPut
$ dep pwdCommand -- production
Executing task pwdCommand
/var/www/html/production
/var/www/html/production
Ok
for the next, let's study why "Demo - Public subnet" become "public". why?
Group the Tasks
In this example, We would deine 4 tasks to deploy to our stages ( production, testing )
- git:clone
- git:pull
- apache:restart
- success : output success message
we will not execute all task one by one from the terminal. we will execute only one time. so we have to group the tasks.