Context
Deployed a Laravel 13 + Vue/Vite app (a Postman-style tool) to a PHP pod via deploy --repo. It worked, but I hit four framework-deploy papercuts that each cost a debugging cycle. Filing together since they're all "PHP-framework DX".
1. deploy has no --version, so deploy --repo can't pick the PHP version
pods create has -v/--version (8.2/8.3/8.4), but deploy does not. A repo whose composer.lock needs PHP 8.4 fails on the 8.3 default with no way to override — I had to pods delete and pods create --version 8.4 first, then connect git. Please add --version to deploy.
2. PHP preset sets nginx docroot to the repo root, not public/
Deploy logs even say Detected php (artisan), but nginx root is /home/instapod/app, so a fresh Laravel app returns 403 until you hand-edit the vhost to .../public. When artisan/public/index.php is detected, docroot should default to public/.
3. php-fpm runs as www-data, but deployed files are owned by the deploy user (instapod)
storage/ and bootstrap/cache/ are owned by instapod (0775), so the www-data fpm worker can't write them → tempnam(): file created in the system's temporary directory → 500 on any page that touches the session/cache/views. Fix by either running fpm as the app user or making those dirs writable by the fpm user during build.
4. Managed env (env set) does not survive a git deploy
instapods env set writes .env, but a git deploy regenerates .env from .env.example, wiping it — so DB creds / APP_KEY set via env set are lost on every deploy, and migrate falls back to the sqlite default. I worked around it with a persistent overlay file outside the checkout that the build merges in, but there's no first-class persistent env / secrets store that survives redeploys. This is important for any framework app.
Minor
- No
domains / pods domain command — custom domains seem web-UI-only; a CLI equivalent would help automation.
services UX: services add NAME -s mysql works but services NAME add mysql is shown in one help path; creds output suggests --service while a positional is also accepted. Slightly confusing.
Each of these is individually small but together they make first-time framework deploys rough. Happy to help test fixes.
Context
Deployed a Laravel 13 + Vue/Vite app (a Postman-style tool) to a PHP pod via
deploy --repo. It worked, but I hit four framework-deploy papercuts that each cost a debugging cycle. Filing together since they're all "PHP-framework DX".1.
deployhas no--version, sodeploy --repocan't pick the PHP versionpods createhas-v/--version(8.2/8.3/8.4), butdeploydoes not. A repo whosecomposer.lockneeds PHP 8.4 fails on the 8.3 default with no way to override — I had topods deleteandpods create --version 8.4first, then connect git. Please add--versiontodeploy.2. PHP preset sets nginx docroot to the repo root, not
public/Deploy logs even say
Detected php (artisan), but nginxrootis/home/instapod/app, so a fresh Laravel app returns 403 until you hand-edit the vhost to.../public. Whenartisan/public/index.phpis detected, docroot should default topublic/.3. php-fpm runs as
www-data, but deployed files are owned by the deploy user (instapod)storage/andbootstrap/cache/are owned byinstapod(0775), so thewww-datafpm worker can't write them →tempnam(): file created in the system's temporary directory→ 500 on any page that touches the session/cache/views. Fix by either running fpm as the app user or making those dirs writable by the fpm user during build.4. Managed env (
env set) does not survive a git deployinstapods env setwrites.env, but a git deploy regenerates.envfrom.env.example, wiping it — so DB creds /APP_KEYset viaenv setare lost on every deploy, andmigratefalls back to the sqlite default. I worked around it with a persistent overlay file outside the checkout that the build merges in, but there's no first-class persistent env / secrets store that survives redeploys. This is important for any framework app.Minor
domains/pods domaincommand — custom domains seem web-UI-only; a CLI equivalent would help automation.servicesUX:services add NAME -s mysqlworks butservices NAME add mysqlis shown in one help path;credsoutput suggests--servicewhile a positional is also accepted. Slightly confusing.Each of these is individually small but together they make first-time framework deploys rough. Happy to help test fixes.