Problem
In a workspace, only git can use the Coder-managed SSH key: the startup script sets GIT_SSH_COMMAND to coder gitssh, which fetches the key with the workspace agent's credentials for each git command. There is no SSH agent (SSH_AUTH_SOCK is unset), so plain ssh in the workspace doesn't have the key, and DDEV's containers have neither the coder binary nor the credentials. Anything inside web that needs the key fails, for example composer install with private repositories, drush aliases, or git in a post-start hook.
Solution
Load the Coder key into a regular ssh-agent at startup and point DDEV at it. This was tested by hand in two workspaces (freeform and drupal-contrib templates), where ddev exec ssh -T git@github.com authenticated with the Coder key; details are in HANDOFF.md on ddev/ddev#8861.
In the startup script, after the Docker daemon is up:
# Start an agent on a fixed socket in its own directory, and load the Coder key.
AGENT_DIR="$HOME/.coder-ssh-agent"
mkdir -p "$AGENT_DIR" && chmod 700 "$AGENT_DIR"
rm -f "$AGENT_DIR/agent.sock"
setsid ssh-agent -a "$AGENT_DIR/agent.sock" >/dev/null
curl -fsS -H "Coder-Session-Token: $CODER_AGENT_TOKEN" \
"$${CODER_AGENT_URL%/}/api/v2/workspaceagents/me/gitsshkey" \
| jq -r .private_key | SSH_AUTH_SOCK="$AGENT_DIR/agent.sock" ssh-add -q -
# Make plain ssh in the workspace use it.
sed -i '/^export SSH_AUTH_SOCK=/d' ~/.bashrc || true
echo "export SSH_AUTH_SOCK=$AGENT_DIR/agent.sock" >> ~/.bashrc
The $${...} is escaped for Terraform, as elsewhere in template.tf; in a plain shell it is ${CODER_AGENT_URL%/}.
Then make DDEV's containers use the same agent. With a DDEV release that includes ddev/ddev#8861:
ddev config global --ssh-agent-upstream="$HOME/.coder-ssh-agent/agent.sock" > /dev/null 2>&1 || true
With released DDEV, a global override file does the same:
# ~/.ddev/ssh-auth-compose.coder-agent.yaml
services:
ddev-ssh-agent:
volumes:
- ${HOME}/.coder-ssh-agent:/upstream
command: ["socat", "UNIX-LISTEN:/tmp/.ssh-agent/socket,perm=0666,fork,unlink-early", "UNIX-CONNECT:/upstream/agent.sock"]
healthcheck:
test: "killall -0 socat"
Notes:
- The socket needs a directory of its own. DDEV mounts the socket's directory into its relay container so that a restarted agent keeps working, so a socket directly in
~/.ssh or $HOME would expose that whole directory.
- Docker runs inside the workspace, so workspace paths are Docker host paths and the mount works as on native Linux.
- The key is never printed or written to disk;
ssh-add - reads it from the pipe.
- The
rm -f is needed because the home directory persists across restarts and ssh-agent -a refuses an existing socket file.
- Check that the agent survives the end of the startup script. It is started with
setsid for that reason, since the script's children may be cleaned up.
GIT_SSH_COMMAND can stay as it is; git in the workspace keeps working either way.
- The same change applies to the
drupal-contrib and drupal-core templates.
- Every container on the DDEV network can then ask the agent to sign with the Coder key, which is the same key the workspace user can already fetch.
Problem
In a workspace, only
gitcan use the Coder-managed SSH key: the startup script setsGIT_SSH_COMMANDtocoder gitssh, which fetches the key with the workspace agent's credentials for each git command. There is no SSH agent (SSH_AUTH_SOCKis unset), so plainsshin the workspace doesn't have the key, and DDEV's containers have neither thecoderbinary nor the credentials. Anything insidewebthat needs the key fails, for examplecomposer installwith private repositories,drushaliases, orgitin a post-start hook.Solution
Load the Coder key into a regular
ssh-agentat startup and point DDEV at it. This was tested by hand in two workspaces (freeformanddrupal-contribtemplates), whereddev exec ssh -T git@github.comauthenticated with the Coder key; details are inHANDOFF.mdon ddev/ddev#8861.In the startup script, after the Docker daemon is up:
The
$${...}is escaped for Terraform, as elsewhere intemplate.tf; in a plain shell it is${CODER_AGENT_URL%/}.Then make DDEV's containers use the same agent. With a DDEV release that includes ddev/ddev#8861:
With released DDEV, a global override file does the same:
Notes:
~/.sshor$HOMEwould expose that whole directory.ssh-add -reads it from the pipe.rm -fis needed because the home directory persists across restarts andssh-agent -arefuses an existing socket file.setsidfor that reason, since the script's children may be cleaned up.GIT_SSH_COMMANDcan stay as it is; git in the workspace keeps working either way.drupal-contribanddrupal-coretemplates.