feat(auth): lerd auth ssh — shared ssh-agent for composer git over SSH#646
Merged
Conversation
The FPM runtime image installs git but no SSH client, so composer cannot fetch private packages over git+ssh — git's ssh transport is missing entirely, which surfaces as an auth failure during `lerd composer install`. Add openssh-client to the runtime apk list. With $HOME already bind-mounted, on-disk keys without a passphrase plus the user's ~/.ssh/known_hosts then work after an FPM image rebuild. Sharing an ssh-agent for passphrase-protected keys builds on this and is tracked separately (lerd-env#643).
FrankenPHP sites serve from a separate image that shipped neither git nor an SSH client, so git over SSH run inside the FrankenPHP container (private composer packages, source installs) failed. Add git + openssh-client to match the FPM image, so every PHP runtime lerd builds can do git+ssh.
Private composer packages pulled over git+ssh with passphrase-protected keys can't authenticate inside the FPM container: there is no agent, and the host agent socket isn't reachable (it can't cross the podman-machine VM boundary on macOS). Add `lerd auth ssh`, mirroring `ddev auth ssh`: a shared ssh-agent sidecar container holds the unlocked keys in memory and exposes its socket on the lerd-ssh-agent named volume, which is also mounted into the FPM containers. `lerd composer` injects SSH_AUTH_SOCK only when the agent is running, so it falls back to on-disk keys otherwise. - internal/podman/sshagent.go: sidecar quadlet + SSH_AUTH_SOCK env helper - FPM quadlet template mounts the lerd-ssh-agent named volume - internal/cli/auth_ssh.go: `lerd auth ssh [key...]`, --list, --remove - php_exec.go injects SSH_AUTH_SOCK into the composer/php container exec The sidecar reuses the FPM image (its openssh-client provides ssh-agent and ssh-add), so no extra image is pulled or built. Keys live only in the agent's memory and are cleared when it stops or the machine restarts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #643
What
lerd auth ssh, mirroringddev auth ssh: load SSH keys into a shared ssh-agent solerd composercan authenticate to private git repositories, including passphrase-protected keys.Keys without a passphrase already work via the bind-mounted
~/.sshonce the image has an SSH client (#645). The agent covers passphrase-protected keys, which need an agent the FPM container can reach. On macOS the host agent socket can't cross the podman-machine VM boundary, so the agent runs inside podman.How
lerd-ssh-agentsidecar container runsssh-agentand holds the unlocked keys in memory. It reuses the FPM image (the openssh-client added in fix(podman): enable git+ssh in PHP runtime images (FPM + FrankenPHP) #645 providesssh-agent/ssh-add), so no extra image is pulled or built.lerd-ssh-agentnamed volume, which is also mounted into the FPM containers, so the socket never crosses the host-VM boundary on macOS.lerd composer/lerd phpinjectSSH_AUTH_SOCKinto the container exec only when the agent is running, so they fall back to on-disk keys otherwise.~/.sshread-only; unlocked key material stays in the agent's memory; keys clear when the agent stops or the machine restarts.Commands:
lerd auth ssh [key...](default~/.ssh/id_*),--list,--remove.Verified end-to-end (local macOS, podman machine)
php:rebuild 8.5 --local→ image shipsssh/ssh-agent/ssh-add.lerd auth ssh <key>→ sidecar up, key loaded (Identity added).SSH_AUTH_SOCK=/ssh-agent/agent.sock ssh-add -llists the key, proving the socket is shared across containers via the named volume.lerd php -r 'echo getenv("SSH_AUTH_SOCK")'→/ssh-agent/agent.sock, the composer/php path injects it.go build ./...,go vet,go test ./internal/cli/ ./internal/podman/(1229 pass) all green with-tags nogui.