Symfony walkthrough
End-to-end: from lerd install to a Symfony app running on https://myapp.test with Doctrine, MySQL, and a Messenger worker.
Prerequisites
You've already run lerd install once on this machine. If not, see Installation.
Drive it from your AI assistant
Run lerd mcp:enable-global once and your AI assistant (Claude Code, Cursor, Junie, Codex, Gemini, Copilot, Antigravity, Windsurf) can call every command below through the grouped MCP tools: framework action: "project_new", site action: "link", env action: "setup", framework action: "setup", db action: "create", site action: "tls_enable", worker, etc. See AI Integration.
1. Create the project
cd ~/Lerd
lerd new myapp --framework=symfony
# runs: composer create-project symfony/skeleton:^8.0 ./myappcd ~/Lerd
composer create-project symfony/skeleton myappcd ~/Lerd
git clone git@github.com:you/myapp.git2. Register the site
cd myapp
lerd linklerd link detects Symfony (via symfony.lock or the composer package), assigns http://myapp.test, and sets the document root to public/. Detection also resolves the major version from composer.lock and pulls the matching definition, symfony@8 for a current skeleton, from the framework store. There is nothing to register by hand.
3. Configure PHP, Node, database, services
lerd init? PHP version: 8.5
? Node version (clear to follow the lerd default instead of pinning): 22
? Enable HTTPS? Yes
? Database: mysql
? Services: [mailpit]
? Workers to auto-start: [messenger]
Saved .lerd.yamlThe wizard discovers messenger as an available worker because the definition declares it and the check: composer: symfony/messenger rule matches your project. A project that also pulls in symfony/scheduler gets a scheduler worker beside it on the same terms.
4. Bootstrap the project
lerd setup? Select setup steps to run:
◉ composer install
◉ npm ci # only if package.json exists
◉ lerd env # injects DATABASE_URL, MAILER_DSN, DEFAULT_URI
◉ Run migrations # from the definition's setup block
◯ Load fixtures
◉ Clear cache
◉ Install assets
◉ lerd secure # mkcert TLS for myapp.test
◉ messenger:start
◉ lerd open"Run migrations", "Load fixtures", "Clear cache" and "Install assets" come from the setup: block in symfony@8. Lerd surfaces them automatically and respects the check: rules, so migrations only appear with doctrine/doctrine-migrations-bundle installed and fixtures only with doctrine/doctrine-fixtures-bundle.
When it finishes, https://myapp.test opens in your browser and lerd-messenger-myapp is running as a systemd user service.
5. Verify
lerd status# Tail messenger logs
journalctl --user -u lerd-messenger-myapp -fApp logs show up in the Web UI App Logs tab. The definition already points at var/log/*.log and parses them as Monolog, so a standard project needs nothing; a user overlay is where you would change the paths or the parser.
What just happened
| Command | What it did |
|---|---|
lerd link | Detected Symfony, fetched symfony@8 from the store, assigned myapp.test, set document root to public/ |
lerd init | Wrote .lerd.yaml with PHP, Node, MySQL, Mailpit, messenger |
lerd env (via setup) | Wrote DATABASE_URL=mysql://root:lerd@lerd-mysql:3306/myapp and MAILER_DSN=smtp://lerd-mailpit:1025 into .env.local, seeded from the committed .env |
lerd secure (via setup) | Issued mkcert cert, set DEFAULT_URI=https://myapp.test |
| Doctrine migrations + cache:clear | Ran via the framework's setup: block |
lerd worker start messenger (via setup) | Launched lerd-messenger-myapp |
FrankenPHP / Symfony Runtime (optional)
By default your site runs on the shared PHP-FPM stack. To run it on a per-site FrankenPHP container instead (useful for testing under the long-running worker model Symfony Runtime provides):
lerd runtime frankenphp # classic mode
lerd runtime frankenphp --worker # Symfony Runtime, keeps the kernel in memory
lerd runtime fpm # back to shared PHP-FPMWorker mode needs composer require runtime/frankenphp-symfony. Lerd starts the FrankenPHP container with --watch so edits to controllers and config reload within a second or two without restarting the worker manually. See the FrankenPHP runtime page for limitations.
Next steps
- Frameworks & Workers: add custom workers, customise log paths, define more setup steps
- Database:
lerd db:import,lerd db:shell, switching to Postgres - Services: start Meilisearch, RustFS (S3), custom services
- HTTPS: how
lerd secureworks under the hood - AI Integration (MCP): drive lerd from Claude Code, Cursor, Junie, etc.