deployer/recipes
A collection of ready-made Deployer recipes for PHP deployment, covering frameworks, CMSs, and services so you can ship faster without writing tasks from scratch.
deployer/recipes is a grab-bag of extra recipes for Deployer that were never part of the core package: notifications (Slack, Rollbar, Sentry, Bugsnag, New Relic, PaperTrail), opcache clearing via CacheTool, rsync, npm/yarn builds, and platform recipes for CMSes you probably don't use. Recipes are plain PHP files that call task(), set(), after(), before() — there is no autoloading, no service provider, no service container. You require a file and it registers tasks in the global Deployer registry.
composer require --dev deployer/recipes
Because the package was last released in 2019, it targets Deployer 6.x. If you are on Deployer 7 it will usually still load (the recipe API is stable); on Deployer 8 expect breakage. The pragmatic move is to install it, copy the two or three recipe files you actually want into deploy/recipes/ in your own repo, and drop the dependency.
Look first at the recipe/ directory and grep for the task you need:
grep -R "task(" vendor/deployer/recipes/recipe/
A minimal Laravel setup that adds Slack notifications on top of the core Laravel recipe:
// deploy.php
require 'recipe/laravel.php';
require __DIR__ . '/vendor/deployer/recipes/recipe/slack.php';
set('slack_webhook', getenv('SLACK_WEBHOOK'));
after('deploy:success', 'slack:notify:success');
after('deploy:failed', 'slack:notify:failure');
The first genuinely useful use case for a Laravel app is CacheTool opcache reset after deploy:symlink — core Deployer has nothing for this, and it is the single most common cause of "I deployed but the change isn't live."
Notifications as a deploy audit trail. Wire the notification tasks to deploy:success and deploy:failed so the channel gets a message with release name, stage, and the deployer's user. Read the recipe file first — task names differ between versions (slack:notify vs slack:notify:success / slack:notify:failure) and config keys are plain set() calls with no validation.
Opcache reset with CacheTool. Typically:
set('cachetool', '/usr/sbin/cachetool');
set('cachetool_options', ['--fcgi' => '127.0.0.1:9000']);
after('deploy:symlink', 'cachetool:clear:opcache');
On a multi-host setup, set cachetool_options per host (see gotchas below) — the PHP-FPM socket is almost never identical across app servers.
Asset/build steps with the npm or yarn recipe. These historically hook into the update phase and run install/build on the server. For Laravel + Vite, prefer building in CI and shipping public/build inside the release; use the recipe only if you genuinely build server-side. If you do use it, verify what it hooks with dep list before trusting it, and add within('{{release_path}}', ...) if you write your own build task.
rsync for non-git state. The rsync recipe is the clean way to move storage/app/public uploads between releases or from local to remote. It's also a decent escape hatch when you need a quick "copy these files to the server" task without a full deploy.
Model your own recipes on these files. They are short (~40–80 lines) and idiomatic: desc(), task(), run(), within(), on(host(...)). Copying the pattern is faster than reading the Deployer docs:
desc('Warm the Laravel cache');
task('app:warm', function () {
within('{{release_path}}', function () {
run('{{bin/php}} artisan cache:clear');
run('{{bin/php}} artisan config:cache');
});
});
after('deploy:symlink', 'app:warm');
Keep a deploy.local.php (gitignored) for webhooks, hostnames, and tokens, and require it at the bottom of deploy.php. This is a convention, not a package feature, but it's the only sane way to keep credentials out of the repo when recipes want raw set() values.
laravel.php, symfony.php, wordpress.php) all live in deployer/deployer now. Requiring a stale copy from this package silently redefines tasks — the last task() with a given name wins, and you'll spend an hour debugging why deploy:vendors behaves differently. Check vendor/deployer/deployer/recipe/ and contrib/ first.__DIR__ . '/vendor/deployer/recipes/recipe/slack.php'; bare relative requires resolve against the working directory and break when dep is invoked from a different directory (CI, IDE run configs).set('slack_web_hook', ...) instead of slack_webhook fails silently — you get a request to a null URL, or nothing at all. Grep the recipe for the exact key, then dep config:dump or a task('debug:config', function(){ ... }) if you need to inspect values.getenv() or deploy.local.php; a leaked Slack webhook is a low-grade but real incident.Could not connect or a reset that targets the wrong pool. Verify per host with on(host('app1'), ...) blocks; on chrooted setups you need --fcgi-chroot with the release path.on(host(...), function () { ... }) for per-host config, fail() to abort, after()/before() to hook — all core Deployer, none of it from this package. The package's real value today is as a library of reference implementations for those primitives.How can I help you explore Laravel packages today?