Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

davy_yg's avatar
Level 27

deployer

Anyone ever used deployer? https://deployer.org

I heard you can read the release version folder using it. And whenever a new release version folder being placed you can set to read it directly from the new folder?

So the domain can read directly from it. Any clue about it?

0 likes
4 replies
alanholmes's avatar

@davy_yg I looked at this recently for a possible deployment option.

The way it works, is it uploads into a release/1, release/2, releaseN folder.

It the has a current "folder" which is just a symlink to the latest release, so once it has finished uploading, it changes the symlink to the latest release.

It also has a shared folder for things like the .env file and storage folder.

So you point your domain to the /path/to/upload/current/public folder.

Its a very similar process to how Laravel Envoyer works, expect its manually triggered from your machine

1 like
gcwilliams's avatar

I've been using it for about a year and a half to deploy my projects to the server. It is a great way to do zero downtime deployments. Especially if you don't have Laravel Forge or Laravel Envoyer. Here is how I'm using it in one of my open source projects:

https://github.com/gcw07/whm-server-tracker/blob/master/deploy.php

If you don't want to go to the trouble of setting everything up yourself, there is a project that is using Deployer:

https://github.com/lorisleiva/laravel-deployer

It basically adds an artisan command to do the deployment instead of just using the default Deployer install methods.

Alternatively you can also use Laravel Envoy (https://laravel.com/docs/6.x/envoy). It basically is the same thing, but uses a slightly different syntax for setup. But both Envoy and Deployer work the same way with release folders and a symlink from a current folder.

Here is a Envoy configuration:

https://github.com/spatie/freek.dev/blob/master/Envoy.blade.php

davy_yg's avatar
Level 27

Here is my deploy file:

deploy.php

<?php

namespace Deployer;

require 'recipe/laravel.php';
require 'recipe/npm.php';

// Set SSH Multiplexing
set('ssh_multiplexing', true);

// Set default branch
set('branch', 'dev');

// Set git_tty
set('git_tty', false);

// Set php binary file path
set('bin/php', '/usr/bin/php7.2');

// Project name
set('application', 'sesa-living');

// Project repository
set('repository', 'git@***************.git');

// Shared files/dirs between deploys
add('shared_files', ['.env']);
add('shared_dirs', ['node_modules']);

// Writable dirs by web server
add('writable_dirs', []);

set('keep_releases', 5);

// Hosts
host('staging')
    ->hostname('167.172.76.143') // sesa suitdev.com
    ->forwardAgent(false)
    ->user('suitmedia')
    ->port(22)
    ->roles('app')
    ->stage('staging')
    ->set('deploy_path', '~/www/{{application}}');

// host('production')
//     ->hostname('104.248.96.189') // suitdev.com
//     ->forwardAgent(false)
//     ->user('suitmedia')
//     ->port(22)
//     ->roles('app')
//     ->stage('production')
//     ->set('deploy_path', '~/www/{{application}}');

// Tasks
// Override Tasks
task('deploy', [
    'deploy:info',
    'deploy:prepare',
    'deploy:lock',
    'deploy:release',
    'deploy:update_code',
    'deploy:shared',
    'deploy:vendors',
    'deploy:writable',
    'artisan:storage:link',
    // 'artisan:view:cache',
    'artisan:config:cache',
    'deploy:symlink',
    'deploy:unlock',
    'cleanup',
    'npm:install',
    'npm:build',
    'artisan:laravolt'
]);

task('deploy:composer-command', function () {
        set('composer_options', '{{composer_action}} --verbose --prefer-dist --no-progress --no-interaction --optimize-autoloader');
})->onStage('staging');

task('artisan:clear-compiled', function () {
        run('{{bin/php}} {{release_path}}/artisan clear-compiled');
});

task('restart:web', function () {
    run('sudo service php7.2-fpm restart');
    run('sudo service nginx restart');
    // run('sudo service varnish restart');
})->onRoles('app', 'webserver');

task('restart:workers', function () {
        // specify commands to restart workers
})->onRoles('app', 'worker');

task('restart:services', ['restart:web', 'restart:workers']);

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

// Update the task sequence
task('artisan:migrate', function () {
    run('{{bin/php}} {{release_path}}/artisan migrate --force');
    run('{{bin/php}} {{release_path}}/artisan migrate --force --path="database/migrations/migration_livings"');
})->once();

task('artisan:laravolt', function () {
    run('{{bin/php}} {{release_path}}/artisan laravolt:link-assets');
})->once();

// Build assets webpack
task('npm:build', function () {
    run("cd {{release_path}} && {{bin/npm}} run dev");
});

before('deploy:vendors', 'deploy:composer-command');
before('artisan:config:cache', 'artisan:clear-compiled');
// before('artisan:config:cache', 'artisan:route:cache');
// before('artisan:optimize', 'artisan:clear-compiled');
before('deploy:symlink', 'artisan:migrate');
before('success', 'restart:services');

There is no other confidential data in here that I have to hide right (besides the git)? I am also confuse why there is so many information in here. And the documentation is only a little bit.

ref: https://deployer.org/docs/getting-started.html

My deploy path:

->set('deploy_path', '~/www/{{application}}');

application is sesa-living so deploy path: ~/www/sesa-living' . What is deploy path? My release version is not there.

bugsysha's avatar

I've used it before and after a while it stops working. Also when Laravel version changes and there are some changes in the code it also stops working. Have no idea if this is still an issue cause I've started using Forge.

Please or to participate in this conversation.