Deploying a Laravel App to a VPS with Neo
A complete .neo.yml for Laravel: encrypted secrets, migrations on deploy, and a queue worker — no PaaS, no control plane.
The shape
A typical Laravel deploy needs four things beyond a bare Dockerfile: secrets that don't live in plaintext in git, migrations run against the new code before it takes traffic, a queue worker, and storage:link on first boot.
Secrets: encrypted, not gitignored-and-hoped-for
php artisan env:encrypt
Commit the resulting .env.encrypted; keep .env out of git.
env_encrypted: .env.encrypted
Neo decrypts it in memory at deploy — the key never touches disk on the server. If you don't have PHP handy on a given machine, neo env encrypt / neo env decrypt read and write the exact same format.
Migrations and setup, run in the right place
release:
- php artisan migrate --force
- php artisan storage:link
- php artisan config:cache
These run inside the new container, after its health check, before traffic switches — see Running Database Migrations Safely.
The queue worker
workers:
queue:
command: php artisan queue:work --tries=3 --max-time=3600
Shares the app's image and environment, runs as its own container (app-shop-worker-queue), and restarts automatically if it exits.
Putting it together
name: shop
port: 8080
env_encrypted: .env.encrypted
release:
- php artisan migrate --force
- php artisan storage:link
- php artisan config:cache
workers:
queue:
command: php artisan queue:work --tries=3
environments:
production:
server: prod-box
domain: shop.example.com
neo deploy --to production
If migrate --force fails against real data, the new container is torn down and the old one keeps serving — you get a failed deploy notification, not a broken production app.
Try it yourself — Neo is free, with every feature unlocked.
Get started free