CLI tool
lerd-env/lerd avatar
lerd-env/lerd

lerd: a rootless Podman PHP dev environment for Linux and macOS

Project brief: Open-source, Herd-like local PHP development environment for Linux and macOS. Automatic .test domains, per-project PHP/Node isolation, one-command TLS. Podman-native, rootless.

1,351 stars83 forksGoMIT

At a glance

What is it?
lerd replaces Docker and hand-written vhosts with rootless Podman containers, automatic .test domains and per-project PHP and Node versions. It fits PHP developers on Linux; the Windows story is WSL2 only and still labelled beta.
Who is it for?
Adopt lerd if you write PHP on Linux or macOS and want per-project PHP and Node versions without sudo, a Docker daemon or a hand-edited hosts file. Skip it if you are on native Windows, need a Kubernetes-shaped local stack, or your team standardises on Docker Compose files that must run unchanged.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem lerd targets: PHP version drift and sudo-shaped setup

A PHP developer on Linux usually ends up with one of two setups. Either PHP comes from the distribution, which means one version for every project on the machine, or it comes from a container stack the developer assembles themselves: a compose file, a hosts entry per site, a self-signed certificate that expires unnoticed, and a Node version managed separately from the PHP version. The second setup works, but every new project repeats the work, and the pieces drift apart.

lerd is aimed at that second group. The README describes it as an "open-source Herd-like local PHP development environment for Linux and macOS", with Windows supported through WSL2 in beta. The comparison to Herd matters because Herd is the macOS-first PHP environment from the Laravel ecosystem; lerd is the Linux answer, and it is explicit that it is "built for PHP developers on Linux".

The claim that separates it from a compose file is the combination of rootless Podman, no sudo, and no system pollution. Nginx, PHP-FPM and the services run as containers under your own user. The README states there is no dnsmasq and no system resolver tweak for the DNS side, and that `lerd link` is enough to get a project answering at `project.test` over HTTPS.

How lerd works: containers, a proxy, and a framework store

The architecture visible in the repository is a Go binary that orchestrates Podman. The `go.mod` module is `github.com/geodro/lerd` and requires Go 1.25.8; the dependency list is a CLI and terminal-UI stack (cobra, viper, bubbletea, lipgloss, huh) plus `github.com/coreos/go-systemd/v22` for service integration on Linux, `github.com/fsnotify/fsnotify` for filesystem watching, and `modernc.org/sqlite` for a pure-Go SQLite driver. There is no Docker client library in the direct requirements, which is consistent with the README's "No Docker" line.

The runtime picture the README paints: Nginx, PHP-FPM and your services run as rootless Podman containers. Linking a project gives it a hostname under `.test` and a TLS certificate that is reissued before it expires. Per-project PHP versions run from 8.1 to 8.5, with a frozen 7.4 and 8.0 tier for older codebases, and FrankenPHP is available per site as an alternative to shared PHP-FPM, with Laravel Octane and Symfony Runtime worker modes. Node 22 or 24 is isolated per project through bundled fnm or an nvm you already have.

The part that reduces per-project work is the framework store. Community definitions exist for Laravel, Symfony, WordPress, Drupal, Magento, CakePHP, CodeIgniter, Statamic and Tempest, with versioned auto-detection. Linking a project configures the workers, the nginx vhost and the environment values for you, and the README is careful about what "env" means: the file your framework actually reads, whether that is `.env`, WordPress's `wp-config.php`, Magento's `env.php` or Drupal's `settings.php`. The store updates without a new lerd release, so a definition published later arrives on its own.

Git worktrees get first-class treatment rather than being an afterthought. A `git worktree add` is provisioned automatically, branch domains are detected, and PHP and Node versions plus optional database isolation are per worktree. `lerd worktree wait` blocks until the tree is ready, which is the kind of detail that matters in a script or a CI step.

Installing lerd and linking a first project

The repository ships an `install.sh` at the top level and a `Makefile` whose install target places the binary in `$(HOME)/.local/bin`. The README does not spell out a package-manager route in the text available here, so the installer script is the documented entry point. Building from source is also supported: the `build` target runs the web UI build first, then compiles with `CGO_ENABLED=0` and the `nogui` tag.

bash
make build

That target builds the web UI into `internal/ui/web` and then produces `./build/lerd` via `go build -tags nogui -o $(BUILD_DIR)/$(BINARY) ./cmd/lerd`. The Makefile's `INSTALL_DIR` is `$(HOME)/.local/bin`, so that directory needs to be on PATH if it is not already. The JS package manager is chosen at build time: npm if present, otherwise bun, including a check for `~/.bun/bin/bun`.

Once you have the binary, the first real use is linking an existing project. The README's own summary is that `lerd link` is all it takes for the project to be live at `project.test` with HTTPS.

bash
lerd link

What you should see is the project registered in the dashboard, a `.test` hostname derived from the directory, and a certificate issued for it. If you want to look at the same information in the terminal rather than the browser, `lerd tui` opens the terminal dashboard, and the README notes that the documentation itself ships inside the binary, readable with `lerd man`. That matters on a machine with no internet, which is exactly when a hosted docs site is useless.

Where lerd gets awkward: DNS, Windows, and the Podman dependency

The DNS story is the first place to look before adopting. lerd manages DNS so that `.test` domains resolve without dnsmasq and without touching the system resolver, but the README also documents opting out for `*.localhost` and toggling the behaviour with `dns:enable`, `dns:disable` and `dns:repair`. The existence of a repair command tells you the mechanism can break. If you already run a local resolver on port 53, or your machine is managed by an IT policy that owns `/etc/resolv.conf`, that is the conflict to check first.

Windows is the second constraint. The README says Windows is supported via WSL2 and marks it beta. That is not the same as a native Windows build, and anyone expecting a Herd-style Windows installer should read that line twice.

The Podman requirement is the third. lerd is Podman-native and rootless, which is a deliberate choice with a cost: rootless Podman depends on the host's user-namespace configuration, and on some distributions that is not enabled by default. The README does not document a fallback to a rootful daemon or to Docker, so a host where rootless Podman does not work is a host where lerd does not work. That is a real failure mode, not a hypothetical one.

There is also a scope limit worth naming. lerd assumes PHP. The host-proxy site feature lets you put a Node, Python or Go dev server behind nginx on a `.test` domain, but the per-project runtime isolation, the framework store and the debug tooling are PHP-shaped. A team whose local stack is mostly non-PHP services will be using a fraction of what lerd provides.

lerd against DDEV and plain Docker Compose

DDEV is the closest well-known alternative, and the difference is architectural rather than cosmetic. DDEV generates and manages a docker-compose project per site; you get a `.ddev` directory committed alongside the code, and the configuration is inspectable and portable because it is compose YAML at the bottom. lerd goes the other way: it manages Podman containers itself from a single Go binary, and the per-project configuration is derived rather than written into the repository. That means less to commit and less to keep in sync, but also less to inspect when something goes wrong, and no compose file to hand to a colleague on a machine without lerd.

The runtime difference is the second axis. DDEV uses Docker; lerd uses rootless Podman and states "No Docker. No sudo." If your organisation already runs Docker and its tooling assumes a Docker socket, lerd's choice is friction rather than a benefit. If you specifically want to avoid a root daemon on a developer laptop, it is the reason to pick lerd.

The third difference is the surrounding surface. lerd bundles a web UI in fourteen languages, a terminal dashboard, an SPX profiler with one-click on/off, a debug window that captures `dump()` and `dd()` output and streams it to the dashboard, TUI, MCP and `lerd dump tail`, SQL capture with N+1 and slow-query detection, request timing analytics, and a Tinker tab backed by phpantom_lsp. DDEV has its own add-on ecosystem and a different set of debugging integrations. Choosing between them is mostly a question of whether you want the batteries included in one binary or assembled from compose files and add-ons.

Licence, upgrade cost, and what the binary embeds

lerd is MIT licensed, and the repository carries a `THIRD-PARTY-LICENSES.md` alongside the LICENSE file, which is the place to look for the terms of the bundled components. MIT is permissive and imposes no copyleft obligation on your own code; that is a statement about the licence text, not legal advice, and if you redistribute lerd inside a commercial product you should read the third-party file yourself rather than assume the top-level licence covers everything.

On upgrades, the release cadence visible in the repository is brisk: v1.33.1 on 2026-08-14, v1.33.0 the day before, v1.32.0 on 2026-08-05. The last push to the default branch was on 2026-08-14. Frequent releases are good for fixes and bad for churn, and the README's promise that add-ons and framework definitions "update without a lerd release" is the design answer to that: the parts most likely to change, service definitions and framework detection, are decoupled from the binary. The parts that do not move, the container orchestration and the CLI, are in the binary.

The upgrade cost that is easy to miss is the embedded documentation. Every documentation page ships inside the binary, which is why `lerd man` works offline, and it also means the docs version is tied to the binary version. Upgrading lerd upgrades the documentation you read in the dashboard. That is a small thing until you are debugging against a page that describes a command your installed binary does not have.

Editorial conclusion

Adopt lerd if you write PHP on Linux or macOS and want per-project PHP and Node versions without sudo, a Docker daemon or a hand-edited hosts file. Skip it if you are on native Windows, need a Kubernetes-shaped local stack, or your team standardises on Docker Compose files that must run unchanged. Before committing, check that your distribution's Podman is new enough for rootless containers, run lerd link on one real project and confirm the .test hostname resolves and the certificate is issued, and read the DNS page if you already run a local resolver on port 53.

Frequently asked questions

Does lerd need Docker?

No. The README states that lerd runs Nginx, PHP-FPM and your services as rootless Podman containers, and the project describes itself as Podman-native with "No Docker. No sudo." The direct dependencies in go.mod contain no Docker client library.

Which PHP versions can lerd run per project?

The README lists 8.1 to 8.5, plus a frozen 7.4 and 8.0 legacy tier for projects on the old stack. The version is switched per project, and FrankenPHP is available per site as an alternative to shared PHP-FPM.

Does lerd work on Windows?

Only through WSL2, and the README labels that support beta. No native Windows build is described in the repository, so a Windows user should plan on a WSL2 environment rather than a Windows installer.

How do I get a .test domain for a project in lerd?

The README says one command gives a project a hostname and TLS, and that `lerd link` is enough for the project to be live at `project.test` with HTTPS. lerd manages the DNS for it without dnsmasq and without a system resolver tweak, and you can opt out for `*.localhost` or toggle it with `dns:enable` and `dns:disable`.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lerd-env-lerd.svg)](https://hysenlabs.com/projects/lerd-env-lerd)