Summary
Commands executed by dploy (before_commands / after_commands) inherit APP_ENV=dev (and APP_DEBUG=1) from dploy's own Symfony runtime. For Laravel/Symfony applications, real environment variables take precedence over the application's .env file, so a php artisan optimize deploy hook caches the application config with env=dev and debug=true — in production.
Impact
- Laravel apps deployed with the stock
laravel template end up running with APP_ENV=dev and debug mode enabled, even when the overlay .env correctly sets APP_ENV=production / APP_DEBUG=false.
- Debug mode in production exposes stack traces and environment values on error pages, so this is effectively a security issue.
- It is very confusing to diagnose: running the exact same
php artisan optimize manually as the site user produces the correct result. Only commands executed through dploy are affected.
Root cause
- The dploy PHAR ships its own
.env.local containing APP_ENV=dev:
https://github.com/cloudpanel-io/dploy/blob/master/.env.local
- The Symfony Runtime loads it and populates
APP_ENV (deriving APP_DEBUG=1 for the dev environment) into the process environment of the running PHAR.
CommandExecutor runs the hooks via Process::fromShellCommandline(...) without cleaning the environment, so child processes inherit APP_ENV / APP_DEBUG:
https://github.com/cloudpanel-io/dploy/blob/master/src/Deployment/Command/CommandExecutor.php
- In Laravel (and Symfony) applications, real environment variables win over the
.env file, so the deployed app gets configured as dev with debug enabled.
Steps to reproduce
dploy init laravel for any Laravel app; put a production .env (APP_ENV=production, APP_DEBUG=false) in ~/.dploy/overlays/.env.
- Keep the template's
php8.x artisan optimize as a before_command.
- Run
dploy deploy main.
- In the new release:
php artisan about shows Environment: dev / Debug Mode: ENABLED (from the cached config), while the .env in the very same directory says production.
- Run
php artisan optimize manually inside the release: php artisan about now correctly shows production / OFF.
Workaround
Prefix the hook commands with env -u APP_ENV -u APP_DEBUG ... (or call a shell script that does unset APP_ENV APP_DEBUG before running artisan/console commands).
Suggested fix
Execute before_commands / after_commands with a cleaned environment — e.g. strip the PHAR runtime's own variables (APP_ENV, APP_DEBUG, APP_SECRET, APP_VERSION, SYMFONY_DOTENV_VARS, ...) before Process::run(), or start the process with an explicit environment instead of inheriting the parent's.
Environment
- dploy: latest release (July 2026)
- CloudPanel v2 on Debian, PHP 8.4 site (FPM)
- Application: Laravel 12 using the stock
laravel template
Summary
Commands executed by dploy (
before_commands/after_commands) inheritAPP_ENV=dev(andAPP_DEBUG=1) from dploy's own Symfony runtime. For Laravel/Symfony applications, real environment variables take precedence over the application's.envfile, so aphp artisan optimizedeploy hook caches the application config withenv=devanddebug=true— in production.Impact
laraveltemplate end up running withAPP_ENV=devand debug mode enabled, even when the overlay.envcorrectly setsAPP_ENV=production/APP_DEBUG=false.php artisan optimizemanually as the site user produces the correct result. Only commands executed through dploy are affected.Root cause
.env.localcontainingAPP_ENV=dev:https://github.com/cloudpanel-io/dploy/blob/master/.env.local
APP_ENV(derivingAPP_DEBUG=1for thedevenvironment) into the process environment of the running PHAR.CommandExecutorruns the hooks viaProcess::fromShellCommandline(...)without cleaning the environment, so child processes inheritAPP_ENV/APP_DEBUG:https://github.com/cloudpanel-io/dploy/blob/master/src/Deployment/Command/CommandExecutor.php
.envfile, so the deployed app gets configured asdevwith debug enabled.Steps to reproduce
dploy init laravelfor any Laravel app; put a production.env(APP_ENV=production,APP_DEBUG=false) in~/.dploy/overlays/.env.php8.x artisan optimizeas abefore_command.dploy deploy main.php artisan aboutshowsEnvironment: dev/Debug Mode: ENABLED(from the cached config), while the.envin the very same directory saysproduction.php artisan optimizemanually inside the release:php artisan aboutnow correctly showsproduction/OFF.Workaround
Prefix the hook commands with
env -u APP_ENV -u APP_DEBUG ...(or call a shell script that doesunset APP_ENV APP_DEBUGbefore running artisan/console commands).Suggested fix
Execute
before_commands/after_commandswith a cleaned environment — e.g. strip the PHAR runtime's own variables (APP_ENV,APP_DEBUG,APP_SECRET,APP_VERSION,SYMFONY_DOTENV_VARS, ...) beforeProcess::run(), or start the process with an explicit environment instead of inheriting the parent's.Environment
laraveltemplate