Repository navigation
Let workspaces use git over https when ssh-agent forwarding is off - #17
Merged
Merged
Conversation
A forwarded ssh-agent and DevPod's git credential helper both need the user's computer, so agents running unattended in a workspace lose git access when the laptop sleeps. The new GIT_SSH_TO_HTTPS context option (auto by default, which enables it when SSH_AGENT_FORWARDING is false) writes url.<base>.insteadOf rules during container setup that rewrite the ssh urls of the workspace's hosts to https. The rules live in /var/devpod/ssh-to-https.gitconfig, included from the system git config, so the repository's .git/config is left alone. GIT_SSH_TO_HTTPS_HOSTS adds hosts and explicit from=to rewrites for servers with different ssh and https paths. Credentials are left to the dev container, so DevPod stays agnostic of git hosts. Removing DevPod's credential helper at the end of a session no longer deletes other helpers in the [credential] section of the global git config, such as one the dev container configured. Documents how to set up a workspace that keeps working unattended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Starts a workspace from a git repo with an ssh remote and an ssh submodule url while SSH_AGENT_FORWARDING is off, checks that git in the container uses https for both and that the repo on the host is untouched, then sets GIT_SSH_TO_HTTPS=false and checks that the rewrites are removed. The test runs in its own context so its options don't leak into other tests. It is labelled up-docker, so CI runs it with the other docker tests, and git-ssh-to-https to run it on its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Send GIT_SSH_TO_HTTPS as "true"/"false" and leave the rewrites alone when it is empty, so a container started by an older CLI keeps them. devpod ssh now also sends the context's options, so a stopped container that it starts again is set up as devpod up would. - Honour SSH_AGENT_FORWARDING=false for the container: the setup tunnel no longer forwards the ssh-agent into lifecycle commands, and the ssh config entry gets ForwardAgent no. The agent on the machine still gets it to clone the source. - Read the remotes of a local folder source on the host, so worktrees and submodule checkouts, whose git dir isn't mounted, get rewrites too. - Reject GIT_SSH_TO_HTTPS_HOSTS entries that are neither a host nor a from=https://... rewrite, and handle scp-like IPv6 urls and git@host:/path remotes. - Add the workspace folder to the system safe.directory, so git works with folders that aren't chowned (Docker Desktop on macOS and Windows). - Don't save CLI options in the agent's workspace config, as intended. - Extend the e2e test with a container restart, agent forwarding checks, no safe.directory workaround, and a worktree source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Why
Agents running unattended in a workspace lose git access as soon as the user's laptop sleeps. Both ways DevPod provides git credentials depend on the laptop:
devpod sshconnection;SSH can't fix this without putting private keys in the workspace. This PR makes git use https instead, with credentials that the dev container provides. DevPod doesn't handle tokens itself, so it stays agnostic of GitHub, Bitbucket and other hosts.
What
New context option
GIT_SSH_TO_HTTPS(auto|true|false, defaultauto).autoturns it on whenSSH_AGENT_FORWARDING=false.devpod upand passed to the container inCLIOptions(two new fields; older agents ignore them).What container setup does when it's on. This runs before any lifecycle hook:
remote.*.url/submodule.*.urlentries of the repository in the workspace folder. It reads the config files directly, so it isn't affected bysafe.directorychecks, and it follows worktree.gitfiles.url."https://<host>/".insteadOfrules for the URL's own ssh prefix,git@<host>:andssh://git@<host>/./var/devpod/ssh-to-https.gitconfig, which is included from the system git config..git/configis not touched. That matters for local-folder workspaces, where it is the user's own checkout.upremoves the file and the include.New context option
GIT_SSH_TO_HTTPS_HOSTS: extra hosts, or explicitfrom=torewrites for servers whose ssh and https paths differ (e.g. Bitbucket Data Center's:7999/vs/scm/).Fix:
removeCredentialHelperused to delete the whole[credential]section of the global gitconfig at the end of a session, including helpers the user or dev container added. It now removes only DevPod's own helper line.Docs: a new page, Run Workspaces Unattended, explaining:
git credential fill) and aghalternative;The credentials page links to it. CHANGELOG updated.
Testing
git remote get-url --pushagainst the generated config, covering ssh,ssh://…:7999with an explicit rewrite, and https remotes;autoresolution.go test ./pkg/... ./cmd/...,go vetand golangci-lint v1.60.1 pass locally. The docs build passes with no new broken links or anchors.devpod upagainst Docker. Docker wasn't available locally.🤖 Generated with Claude Code