Windows nanoserver github portable (ssh auth) fatal: Could not read from remote repository

Hey all! Looking for some help in figuring out an issue with building a Windows Nano Server Container and getting Git to work on with SSH auth keys on it. I am finding that if I use Windows Core the git clone works. I believe I stumbled into what may be causing it as when I run .\ssh.exe from C:\Program Files\Git\usr\bin no command line options are shown. Yet when I run this from server core or even my workstation I get the command line options outputted to the console.

Originally I was installing Git into Nano but I did move to the Portable version thinking there may be a dependency missing and hoped that would solve the issue; it did not.

Anyone out there that has experience with adding Git into Windows Server Nano. I would really appreciate the help.

Here is my dockerfile being used thus far (I’m new to the docker world so please take it easy)

# escape=`
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Args used by from statements must be defined here:
ARG InstallerEnvHost=mcr.microsoft.com
ARG InstallerEnvRepo=windows/servercore
ARG InstallerEnvTag=ltsc2022
ARG NanoEnvHost=mcr.microsoft.com
ARG NanoEnvRepo=windows/nanoserver
ARG NanoEnvTag=ltsc2022

# --------------------------------------------------------------------------------------------------------------------------------------
#                                         STAGE 1 Build Environment
# --------------------------------------------------------------------------------------------------------------------------------------
FROM ${InstallerEnvHost}/${InstallerEnvRepo}:$InstallerEnvTag  AS installer-env1

# disable telemetry
ENV POWERSHELL_TELEMETRY_OPTOUT="1"

ARG PS_VERSION=7.3.2
ARG PS_PACKAGE_URL=https://github.com/PowerShell/PowerShell/releases/download/v$PS_VERSION/PowerShell-$PS_VERSION-win-x64.zip
ARG ZIP_VERSION=2201
ARG ZIP_PACKAGE_URL=https://www.7-zip.org/a/7z$ZIP_VERSION-x64.exe

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; `
    New-Item -ItemType Directory -Path C:\installer | Out-Null; `
    Write-Output "Download PowerShell from $env:PS_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:PS_PACKAGE_URL -outfile C:\installer\powershell.zip -verbose; `
    Expand-Archive C:\installer\powershell.zip -DestinationPath \PowerShell; `
    Write-Output "Download 7-Zip from $env:ZIP_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:ZIP_PACKAGE_URL -OutFile C:\installer\7z.exe; `
    Start-Process -FilePath C:\installer\7z.exe -ArgumentList '/S' -NoNewWindow -Wait -Verbose

#Start the NanoServer Build of ePledge
# --------------------------------------------------------------------------------------------------------------------------------------
#                                         STAGE 2 Build Environment
# --------------------------------------------------------------------------------------------------------------------------------------
FROM ${NanoEnvHost}/${NanoEnvRepo}:$NanoEnvTag  AS installer-env2

COPY --from=installer-env1 ["/PowerShell", "/Program Files/PowerShell"]
COPY --from=installer-env1 ["/Program Files/7-Zip", "/Program Files/7-Zip"]

#Need to switch user to ContainerAdministrator in order to do a setx
USER ContainerAdministrator
RUN setx PATH "%PATH%;%ProgramFiles%\PowerShell;%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\7-zip" /M
USER ContainerUser

ARG GIT_VERSION=2.39.2
ARG GIT_PACKAGE_URL=https://github.com/git-for-windows/git/releases/download/v$GIT_VERSION.windows.1/PortableGit-$GIT_VERSION-64-bit.7z.exe
ARG GH_CLI_VERSION=2.23.0
ARG GH_CLI_PACKAGE_URL=https://github.com/cli/cli/releases/download/v$GH_CLI_VERSION/gh_${GH_CLI_VERSION}_windows_amd64.zip

SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; `
    New-Item -ItemType Directory -Path C:\installer | Out-Null; `
    Write-Output "Download Git from $env:GIT_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:GIT_PACKAGE_URL -OutFile C:\Installer\Git.7z.exe; `
    7z x C:\Installer\Git.7z.exe -ogit; `
    Write-Output "Download Git CLI from $env:GH_CLI_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:GH_CLI_PACKAGE_URL -OutFile C:\Installer\GHCLI.zip; `
    7z x C:\Installer\GHCLI.zip -ogit
    

# --------------------------------------------------------------------------------------------------------------------------------------
#                                         Final Build STAGE
# --------------------------------------------------------------------------------------------------------------------------------------
FROM ${NanoEnvHost}/${NanoEnvRepo}:$NanoEnvTag  AS nanoserver-git

COPY --from=installer-env1 ["/PowerShell", "/Program Files/PowerShell"]
COPY --from=installer-env1 ["/Program Files/7-Zip", "/Program Files/7-Zip"]
COPY --from=installer-env2 ["/Git", "/Program Files/Git"]

USER ContainerAdministrator
RUN setx PATH "%PATH%;%ProgramFiles%\PowerShell;;%ProgramFiles%\Git;%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\7-zip" /M
USER ContainerUser

SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

#Create Base Level Directories
RUN New-Item -ItemType Directory -Path C:\AdminScripts | Out-Null; `
    New-Item -ItemType Directory -Path C:\AdminScripts\epledge-deploy | Out-Null; `
    New-Item -ItemType Directory -Path C:\Users\ContainerUser\.ssh | Out-Null; `
    Set-Location $ENV:ProgramFiles\Git

# Copy Over Files & Folders
COPY IdentityFiles C:/AdminScripts/IdentityFiles
COPY .ssh C:/Users/ContainerUser/.ssh

RUN git config --global core.sshCommand 'ssh -o StrictHostKeyChecking=no'

CMD ["pwsh.exe"]

Here are some items I’m reading over now:

A regression introduced in Git for Windows v2.38.0 that prevented
git.exe from running in Windows Nano Server containers was fixed.

You can see I’m using 2.39.2 Git Portable currently which appears to state at least git.exe is fixed.

These parts have been tested and are working in Windows Core Container and on my actual system.

On the Nano based container I place my SSH Keys into C:\AdminScripts\IdentityFiles and in the C:\Users\ContainerUser.ssh\config file I have entries that look like this:

Host github.com-repo1
        Hostname github.com
        User <MyUser>
        IdentityFile=C:\Users\ContainerUser\.ssh\id_ed25519_repo1

I issue the git clone command of

git clone --recursive --depth 1 --no-tags --single-branch --config advice.detachedHead=false --config core.bare=true git@github.com-repo1:<Company>/<repo1>.git C:\AdminScripts\<repo1>

getting the following error back:

Cloning into ‘C:\AdminScripts\repo1’…
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Also opened up an issue on GitHub here: Git SSH does not output command line options · Issue #4320 · git-for-windows/git · GitHub

Update on this. I believe that my guess is correct; GitHub ssh does not work in Nano. I moved over to using OpenSSH 9.2.0.0p1-Beta and forced git to use OpenSSH as it’s client.

RUN git config --global core.sshcommand 'C:/AdminScripts/OpenSSH/ssh.exe'

We also ran into an issue where when the git clone was running it would complain about the github.com address not being trusted so we had to add in the following statement to the ssh config file.

Host *
        StrictHostKeyChecking no

After that was done I ran into a further issue that the git clone command was still returning a non-zero value and with some trickery and help from a co-worker we did the following:

RUN $result = (git clone --recursive --depth 1 --no-tags --single-branch --config advice.detachedHead=false --config core.bare=true git@github.com-repo1:<company>/<repo>.git C:\AdminScripts\repo1);$error.clear();return 0

Full working dockerfile

# escape=`
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Args used by from statements must be defined here:
ARG InstallerEnvHost=mcr.microsoft.com
ARG InstallerEnvRepo=windows/servercore
ARG InstallerEnvTag=ltsc2022
ARG NanoEnvHost=mcr.microsoft.com
ARG NanoEnvRepo=windows/nanoserver
ARG NanoEnvTag=ltsc2022

# --------------------------------------------------------------------------------------------------------------------------------------
#                                         STAGE 1 Build Environment
# --------------------------------------------------------------------------------------------------------------------------------------
FROM ${InstallerEnvHost}/${InstallerEnvRepo}:$InstallerEnvTag  AS installer-env1

# disable telemetry
ENV POWERSHELL_TELEMETRY_OPTOUT="1"

ARG PS_VERSION=7.3.2
ARG PS_PACKAGE_URL=https://github.com/PowerShell/PowerShell/releases/download/v$PS_VERSION/PowerShell-$PS_VERSION-win-x64.zip
ARG ZIP_VERSION=2201
ARG ZIP_PACKAGE_URL=https://www.7-zip.org/a/7z$ZIP_VERSION-x64.exe

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; `
    New-Item -ItemType Directory -Path C:\installer | Out-Null; `
    Write-Host "Download PowerShell from $env:PS_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:PS_PACKAGE_URL -outfile C:\installer\powershell.zip -verbose; `
    Expand-Archive C:\installer\powershell.zip -DestinationPath \PowerShell; `
    Write-Host "Download 7-Zip from $env:ZIP_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:ZIP_PACKAGE_URL -OutFile C:\installer\7z.exe; `
    Start-Process -FilePath C:\installer\7z.exe -ArgumentList '/S' -NoNewWindow -Wait -Verbose

#Start the NanoServer Build of ePledge
# --------------------------------------------------------------------------------------------------------------------------------------
#                                         STAGE 2 Build Environment
# --------------------------------------------------------------------------------------------------------------------------------------
FROM ${NanoEnvHost}/${NanoEnvRepo}:$NanoEnvTag  AS installer-env2

COPY --from=installer-env1 ["/PowerShell", "/Program Files/PowerShell"]
COPY --from=installer-env1 ["/Program Files/7-Zip", "/Program Files/7-Zip"]

#Need to switch user to ContainerAdministrator in order to do a setx
USER ContainerAdministrator
RUN setx PATH "%PATH%;%ProgramFiles%\PowerShell;%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\7-zip" /M
USER ContainerUser

ARG GIT_VERSION=2.39.2
ARG GIT_PACKAGE_URL=https://github.com/git-for-windows/git/releases/download/v$GIT_VERSION.windows.1/PortableGit-$GIT_VERSION-64-bit.7z.exe
ARG GH_CLI_VERSION=2.23.0
ARG GH_CLI_PACKAGE_URL=https://github.com/cli/cli/releases/download/v$GH_CLI_VERSION/gh_${GH_CLI_VERSION}_windows_amd64.zip

SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12; `
    New-Item -ItemType Directory -Path C:\installer | Out-Null; `
    Write-Host "Download Git from $env:GIT_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:GIT_PACKAGE_URL -OutFile C:\Installer\Git.7z.exe; `
    7z x C:\Installer\Git.7z.exe -ogit; `
    Write-Host "Download Git CLI from $env:GH_CLI_PACKAGE_URL"; `
    Invoke-WebRequest -Uri $env:GH_CLI_PACKAGE_URL -OutFile C:\Installer\GHCLI.zip; `
    7z x C:\Installer\GHCLI.zip -ogit
    

# --------------------------------------------------------------------------------------------------------------------------------------
#                                         Final Build STAGE
# --------------------------------------------------------------------------------------------------------------------------------------
FROM ${NanoEnvHost}/${NanoEnvRepo}:$NanoEnvTag  AS nanoserver-epledge

COPY --from=installer-env1 ["/PowerShell", "/Program Files/PowerShell"]
COPY --from=installer-env1 ["/Program Files/7-Zip", "/Program Files/7-Zip"]
COPY --from=installer-env2 ["/Git", "/Program Files/Git"]

USER ContainerAdministrator
#RUN setx PATH "%PATH%;%ProgramFiles%\PowerShell;;%ProgramFiles%\Git;%ProgramFiles%\Git\cmd;%ProgramFiles%\Git\usr\bin;%ProgramFiles%\7-zip" /M
RUN setx PATH "%PATH%;%ProgramFiles%\PowerShell;;%ProgramFiles%\Git;%ProgramFiles%\Git\cmd;C:\AdminScripts\OpenSSH;%ProgramFiles%\7-zip" /M
USER ContainerUser

SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

#Create Base Level Directories
RUN New-Item -ItemType Directory -Path C:\AdminScripts | Out-Null; `
    New-Item -ItemType Directory -Path C:\AdminScripts\epledge-deploy | Out-Null; `
    New-Item -ItemType Directory -Path C:\Users\ContainerUser\.ssh | Out-Null; `
    Set-Location $ENV:ProgramFiles\Git

# Copy Over Files & Folders
COPY .ssh C:/Users/ContainerUser/.ssh
#https://github.com/PowerShell/Win32-OpenSSH/releases
#download and place into folder to be copied over.
COPY OpenSSH C:/AdminScripts/OpenSSH

RUN git config --global core.sshcommand 'C:/AdminScripts/OpenSSH/ssh.exe'

RUN $result = (git clone --recursive --depth 1 --no-tags --single-branch --config advice.detachedHead=false --config core.bare=true git@github.com-repo1:<company>/<repo1>.git C:\AdminScripts\repo1);$error.clear();return 0

SSH Config file example

Host *
        StrictHostKeyChecking no
Host github.com-repo1
        Hostname github.com
        User <user>
        IdentityFile=C:\Users\ContainerUser\.ssh\id_ed25519_repo1

I would still rather just use GitHub and not have to jump through a hoop by also including OpenSSH but at the least this works. Hoping the GitHub team will dive into this more to find out what’s going on.