Atomic releases.
Each deploy checks out into its own releases/ directory. Composer and asset builds run there while the live release keeps serving. Going live is one symlink flip.
symflip does what your Deployer or Capistrano script does (releases, a
current symlink, rollback) as a hosted or self-hosted app with
live logs and multi-server deploys. Nothing to install on your servers.
It fits best today when .env is the main thing your app shares
between releases; check the list below first.
Free for one project on one server. Multi-server deploys need Team (€29/mo).
Read this before you move a Symfony app.
.env and storage/. These are Laravel's defaults. Symfony's var/log and upload directories aren't shared automatically yet..env. It writes your symflip secrets to shared/.env and links that over the .env in each release, which replaces the one committed in your repo. Add every variable your app needs, including the defaults from your committed .env, to symflip secrets.APP_ENV and APP_SECRET as secrets. With no secrets, symflip writes no shared/.env, the link points at a missing file, and Symfony won't boot.mkdir -p /var/www/app/shared/var/log /var/www/app/shared/uploads
rm -rf var/log && ln -sfn /var/www/app/shared/var/log var/log
ln -sfn /var/www/app/shared/uploads public/uploads
It works, but you're doing by hand what a Deployer recipe does with
shared_dirs. Configurable shared paths are on the roadmap. If
you need them today, Deployer's Symfony recipe
[1] is a
reasonable choice.
Each deploy checks out into its own releases/ directory. Composer and asset builds run there while the live release keeps serving. Going live is one symlink flip.
php bin/console doctrine:migrations:migrate --no-interaction runs on one server you choose, before any server goes live. If it fails, nothing switches.
Every server builds first; none go live until all are ready. If a server fails to switch, or the release fails its health check with auto-rollback on, the servers that switched roll back so the fleet ends on one release. Multi-server deploys start on Team.
Previous releases stay on every server, so rolling back is a symlink flip. A failed health check can trigger it across the fleet automatically. The one-click button covers single-server projects today.
Watch each step stream into your browser. On Business, require a teammate's approval before production and keep a record of who shipped what.
# Build
APP_ENV=prod composer install --no-dev --optimize-autoloader --no-interaction
npm ci && npm run build
# Migrate (runs once, on the primary server)
php bin/console doctrine:migrations:migrate --no-interaction
# Pre-activate hook (Team and up)
php bin/console cache:clear --env=prod
php bin/console cache:warmup --env=prod
# Reload
sudo -n systemctl reload php8.3-fpm
# Post-deploy hook (Team and up)
php bin/console messenger:stop-workers
# Health check (a route your app provides)
curl -fsS http://127.0.0.1/health -H 'Host: example.com'
/health is an example. Symfony has no health route by default; point the check at any route of yours that touches the database.
Deployer is free and agentless, and its Symfony recipe is good
[1]. symflip
works the same way under the hood. What you get on top is a UI your whole
team can use, live logs in the browser, fleet deploys that build everywhere
before going live, optional automatic rollback on a failed health check,
encrypted secrets, approvals and an audit trail, without a
deploy.php that one person on the team understands.
A Deployer alternative your whole team can use.
Deployer detail checked on . Source:
Laravel, Laravel Forge and Laravel Envoyer are trademarks of their owner. Deployer is an independent open-source project. symflip is not affiliated with or endorsed by either. Competitor details are as published on the cited pages on and may have changed since.
Free for one project on one server. No card to start.