Solving Dev Container SSH Frustrations
There is so much information about containers, git, and ssh–it’s a lot to wade through. I’ll have slept several times before I need to use this again, so hopefully this will help me. If this helps other folks… that’s awesome :)
This is the collection of tidbits that helped get git working from in containers for BOTH authentication and commit signing with SSH. It’s the latter one that made searches maddening.
So we are all on the same page
- Windows 11 is the host
- WSL using the default Ubuntu distro
- Git Bash is installed
- VSCode
- Dev Container extension
It’s all about the host: #1 item that illuded me
DevContainers shares Windows SSH credentials. Even if you have your SSH keys set up in Git Bash or WSL. Even if the DevContainer is started from WSL… doesn’t matter. The Windows SSH credentials are what is available inside the container.
With the setup mentioned above, nothing was needed to make it work. I only needed to realize the ssh
key I wanted should be in C:\Users\<me>\.ssh
It has something to do with Git Credential
Manager,
but I’m not sure if it was already part of Windows, came with Git Bash, or something else.
There was a bug in SSH on Windows: #2 illusive item
There is a known bug that impacted my setup. It may not be a problem for future readers, but the end result was a permission denied message–which could be almost anything.
To correct this bug SSH has to be updated. Sounds easy? This is Windows, no package management you have to double click and things.
This is where the MSI can be downloaded. Don’t worry that it’s called “Win32”, install it and move on with life (I should have too). You’ll probably have to restart or something.
Now we know, let’s make things happen
Why are services so hard on Windows?
I don’t know, but give up with PowerShell, hit Windows Key + R, and type services.msc
.
Search for “OpenSSH Authentication Agent” with your eyes because there is no search bar. You can
mash o
to get to the general area. Then double click to open a dialog.
Change Startup type to Automatic so it will always start with Windows. Click the Start button to start it now.
Why is command line so hard on Windows?
I don’t know this either, but don’t trust it. I found it easier to use the full path when running
ssh binaries than figuring out PowerShell’s equivalent of which
.
This command will verify the version:
& 'C:\Program Files\OpenSSH\ssh.exe' -V
This will show the current ssh keys:
& 'C:\Program Files\OpenSSH\ssh-add.exe' -l
No I don’t know why it needs the
&
, just copy and paste. The Windows part is almost over.
Before setting all this up, in my case, running ssh-add
was not using the correct binaries, which
is not what Windows shares with containers.
Double check keys
Now that we know what windows is doing with ssh.We can make sure we’re not crazy. The following is done in a basic Alpine Dev Container.
In the Dev Container bash terminal:
$ ssh-add -l
256 SHA256:OMsbcAsYBPVemwyi3tyNo92fjaOxhP6uootR3/KxpRM james@geekwagon.net (ED25519)
In the Windows host PowerShell:
PS C:\Users\james> & 'C:\Program Files\OpenSSH\ssh-add.exe' -l
256 SHA256:OMsbcAsYBPVemwyi3tyNo92fjaOxhP6uootR3/KxpRM james@geekwagon.net (ED25519)
The same key in both!
Fun fact: the lower case
-l
shows key’s fingerprints, making the keys easier to corelate with keys used in most web-based git repository hosting services (GitLab, GitHub, or Gitea). The upper case-L
displays public keys as a giant wall of un-breaking text.
Why does it work? Beats me, there is a bind mount from WSL(?) that looks like it may have something to do with it. VSCode or the extension must be handling the heavy lifting.
Run git config --list --show-origin
in both terminals will show most of the git config comes from
Windows too. You may want to copy settings from WSL or Git Bash to the .gitconfig
file in your
Windows user directory.
SSH Commit Signing in the Container
Great, we’re in the container, did a git pull
. Later, we git commit
, spend minutes to write the
a thoughtful and descriptive message that leaves no ambiguity about the change. Save the commit
and…. too bad it cannot be signed.
Assuming you already have ssh signing working in Windows, this is not a difficult setup in the container.
I had used the public key file path in my git config user.signingKey
value because I followed
GitHub’s
or GitLab’s
instructions to set up commit signing with SSH keys. This can work if a bind mount is added from
your user’s .ssh directory to the same directory in the container. Something like
/home/james/.ssh
. In most containers there is no directory for my user, even though it works it’s
an ugly solution.
A less ugly, no mounting needed option is to use the public key instead of the path.
user.signingKey=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9q11GxmdSFCQ3M02W/GFpEKDmtIFrPpkTJLbIEIkEw
It has to be the key, not the fingerprint. Looks like the comment can be left out too.
Git’s docs for
user.signingKey
are not super clear in my opinion. There is a key::<private key>
option that works for private
keys but not public keys.
Also, why would anyone put their public key in the git config? Seems like a bad idea, especially if you use something like GNU Stow to save config files.
Some how I stumbled onto [this thread(?) that gave some
clues(https://lore.kernel.org/git/20220628162342.ootjobbjtxg7b7ay@fs/t/). In this case they use
cat
to print out the public key contents, but that relies on knowing where the file is too.
I also suspect the key will need to be added into the running ssh-agent in Windows. In my case I use the same key for signing and authentication so it is already there.
I would like to reiterate, I’m not a security expert. I don’t believe anything in here would introduce security issues, but do your own homework.