NOTE: This tutorial is partially out of date.
The following stuff mentioned in this tutorial is no longer necessary:
-
Step 2, 3, 9 and 10 chocolately and custom
OpenSSH
is not a requirement,OpenSSH
that comes with Windows will work, only make sure to set it auto start and create an ECDSA key. -
Step 16 to create an
ECDSA
key run:# if .ssh directory doesn't exist create it mkdir $env:USERPROFILE\.ssh # Create new ECDSA key ssh-keygen -t ecdsa -b 521 -C "GitHub" -f $env:USERPROFILE\.ssh\key_file_name
-
Step 18 is not recommended because it's may cause issues with
gpg-agent
reading created file, you can configure all this inKleopatra
UI as well. -
Step 19 Installing pre-release of
posh-git
is no longer necessary since there is a release version now, just omit the-AllowPrerelease
switch.
The rest of the tutorial should work fine for years to come, but I'm leaving outdated material intact to serve for research and troubleshooting.
- work with git in Powershell, you won't need to use MSYS terminal any more
- you will have colored prompt in powershell when in working tree
- git will not ask you for ssh password every time (not even after reboot) because ssh-agent will run as windows service.
- your commits will be automatically signed by default
- git will use gpg-agent from gpg4win suite, to sign your commits (meaning being able to manage and generate your keys with Kleopatra as well as many other GUI options for GPG)
- you will be asked for gpg key only once, with the ability to customize how often gpg asks you for GPG key password
- you will communicate with github over ssh
git comes as you might know bundled with it's own gpg and ssh executables, however if you want git to use gpg4win version of gpg for signing commits and if you don't want to be prompted for ssh and gpg keys every time you push and commit and if in addition you want all that in powershell then you are likely to get into a lot of trouble.
Other uses of this setup include use of git with custom ssh and gpg for what ever reason, or if you just want to be able to cache keys in a more efficient ways.
The biggest problem is that ssh that comes with git doesn't run ssh-agent automatically, posh-git doesn't start
ssh-agent properly at the time of writing, (maybe some new version in the future will), because there is a conflict between
openSSH that comes with windows and ssh that comes with git, so the alternative way is to use OpenSSH
that comes bundled
with Windows 10.
For more information see OpenSSH in Windows
However even that won't work perfectly because bundled ssh in Windows 10 is out of date and outputs annoying
signature warning when doing push (at least on Windows 1903), so we need to install manually latest version of OpenSSH
!
Note that even if posh-git manages to start ssh it still won't be perfect for our key-caching goal because ssh that comes with git doesn't offer windows service!
I won't go into details too much as to providing technical details why default setup doesn't work, because it would take a lot of explanation, and since you're reading this you might already know that!
NOTE: Portion of the steps here are based on instructions from documentation on github.com
but
updated to reflect powershell usage, and some stuff has been removed because it's irrelevant with our setup.
Also some of the content is based on git-scm.com
instructions and many other sites,
the point is that all this information is now assembled here in one place for a complete tutorial.
At the end of this tutorial is a list of links to original documentation and references that describe the problem.
NOTE: All of the commands below are executed in powershell, also these steps have been tested on Windows 10 only
-
First if you didn't already download and install gpg4win and git
-
Windows 10 only step: next we need to get rid of faulty openSSH that comes with windows:
- log into Administrative account (if you're not Administrator)
- press
Windows key + I
to open settings - type "Optional Feature" from the list
- select "Manage optional features" to go to the Setting App.
- click on "OpenSSH Client" and uninstall
-
There are multiple ways to install
chocolatey
as explained here we'll useInstall-Package
version and if that doesn't work thennuget.exe
option because these seem to be the most practical options. -
If you are running an older version of windows such as Windows 7 it's possible your powershell is pretty old so let's first check powershell version, Open up powershell and type:
$PSVersionTable.PSVersion
In order for all of the commands in this tutorial to work you will need at least Windows PowerShell 5.x or PowerShell Core 6.0.
If for some reason you can't upgrade powershell this tutorial provides a subset of alternative commands that will work exceptposh-git
module which requires powershell minimum version 5.To grab and install latest PowerShell core follow this link Get PowerShell Core
Otherwise if you need to update Windows PowerShell then grab zipped powershell installer as windows update, but with some restricted installation opportunities as explained on this link: Installing Windows PowerShell
-
Before you're able to run PowerShell scripts on your machine, you need to set your local ExecutionPolicy to RemoteSigned
- More about PowerShell Scopes
- More about PowerShell ExecutionPolicy
-
Open up Powershell (Admin) and check current execution policy:
Get-ExecutionPolicy
NOTE: PowerShell Core defaults to
RemoteSigned
while Windows PowerShell defaults toRestricted
If it's not
RemoteSigned
change execution policy:Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
-
Because we'll install some modules, you might want to set
NuGet
andPSGallery
package sources as trusted, also you might want to do it for both Administrative and standard account (by opening respective PowerShell for each user).NOTE: commands for nuget.org (NuGet provider) in this step and steps 8 and 9 that follow may fail in PowerShell core, and the workaround is not worth spending time, if your Core is up to date you're fine! I'll let you know the alternative options, for now just skip "NuGet" steps if it doesn't work.
To see package sources first run:
Get-PackageSource
To set nuget.org as trusted run:
Set-PackageSource -Name nuget.org -Trusted
More information about NuGet provider
To set PSGallery as trusted run:
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
More information about PowerShell Gallery
-
Next logical step is to install/update prerequisites.
Let's first check if we have required NuGet package provider installed:
Get-PackageProvider
If NuGet is not listed (or to check if it's out of date) find out if it's possible to install/update it:
Find-PackageProvider -Name "NuGet" -AllVersions
If NuGet is out of date or not installed run new Powershell (Admin) instance and install it (or update with
-Force
switch)Install-PackageProvider -Name NuGet
Restart administrative PowerShell and then we also need to update PowerShellGet version which is required for latest posh-git, this is possible to install only with
-Force
switch as explained here, otherwise you should get an error:To see currently installed versions:
Get-Module -ListAvailable -Name PowerShellGet
To install new version on top of that is preinstalled:
Install-Module -Name PowerShellGet -Force
To update existing PowerShellGet: (the one you personally already installed with
Install-Module
)Update-Module -Name PowerShellGet
If you get an error such as "Unable to find module providers" in Windows PowerShell (in core it might not work anyway) restart administrative powershell for each of these 2 sets of commands before executing them, and make sure you use
-Force
withInstall-Module
-
Next again restart admin powershell and search for available
chocolatey
versions:NOTE: Command below may fail in PowerShell core, if so there is "option 2" for you.
Find-Package chocolatey -MinimumVersion 0.10.14`
Install
chocolatey
by using either option 1 or option 2:NOTE: You can of course build openssh from source and exclude nuget.exe and
chocolatey
but I prefer the easy way.
If you wish to build it from source grab ported sources here: PowerShell/openssh-portableNOTE: We'll install this openssh which is based on Microsoft fork on github, the difference is that this one will also give us the option to install windows service for ssh-agent.
To input more parameters see previous openssh link, we use-pre
to get latest prerelease.OPTION 1: Using Install-Package To download
chocolatey
, replaceRequiredVersion
option
with version obtained fromFind-Package
above:Install-Package -Name chocolatey -ProviderName NuGet -RequiredVersion x.x.x
Next to install
chocolatey
do:Initialize-Chocolatey
this should finish installation, if this does not work then:
NOTE: updatecd
command to matchchocolatey
versioncd "C:\Program Files\PackageManagement\NuGet\Packages\chocolatey.0.10.14\tools" & .\chocolateyInstall.ps1
Finally to install
OpenSSH
, restart administrative PowerShell and run:
choco install openssh -pre --package-parameters="/SSHAgentFeature"
OPTION 2: Using nuget.exe This is alternative method to install
chocolatey
andOpenSSH
:Get latest
nuget.exe
from NuGet, put it somewhere for exampleC:\tools
and addC:\tools
(or what ever path you choose) toPATH
environment variable.NOTE: we need
nuget.exe
inPATH
to install chocolatey, and we needchocolatey
because it will let us install openssh.NOTE: if you wish to install chocolately somewhere else update first command, and ensure chosen path is in
%PATH%
environment variable.cd C:\tools nuget install chocolatey cd choco*\tools & .\chocolateyInstall.ps1 choco install openssh -pre --package-parameters="/SSHAgentFeature"
-
For option 1,
Install-Package
will downloadchocolatey
into:
C:\Program Files\PackageManagement\NuGet\Packages\chocolatey.x.x.x
.
For option2: nuget.exe will temporary downloadchocolatey
toC:\tools\chocolatey.x.x.x
.In both cases chocolately will be installed into
%PROGRAMDATA%\chocolatey
andOpenSSH
with service configuration will be installed intoC:\Program Files\OpenSSH-Win64
. -
Now open
services.msc
as Administrator and make suressh-agent
service is started and set to automatic startup. -
Close Admin powershell and start new powershell instance (as standard user, if your acc isn't admin of course) Please first ensure that ssh and gpg paths below are correct paths on your system, and if not update as needed, for example, if you installed gpg4win or openSSH somewhere else. You can verify installation path by typing:
where.exe ssh where.exe gpg
Now start telling git about our setup: (btw. hard to tell why this syntax for paths)
git config --global --replace-all core.sshCommand "'C:\Program Files\OpenSSH-Win64\ssh.exe'" git config --global --replace-all gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"
And to verify these commands are input correctly:
git config --global --edit
The input must look like this (I'm showing this so that tutorial changes don't mess up with expected result):
[core] sshCommand = 'C:\\Program Files\\OpenSSH-Win64\\ssh.exe' [gpg] program = C:\\Program Files (x86)\\GnuPG\\bin\\gpg.exe
NOTE: above paths are pointing git to use gpg4win executables of gpg and our fresh installed openSSH portable as ssh program
-
Now everything is set up, and it's time to setup the keys!
If you have existing gpg keys made by gpg4win in
%appdata%\gnupg
which you would like to backup first (because we might override them) then issue the following command:robocopy $env:APPDATA\gnupg $env:APPDATA\gnupg-backup /MOVE /E
If you have existing gpg keys in
~\.gnupg
which is where gpg keys are put by git version of gpg and you would like to use them with gpg4win to sign commits, then issue the following commands to move entire contents into%appdata%\gnupg
robocopy $env:USERPROFILE\.gnupg $env:APPDATA\gnupg /MOVE /E
If you have existing key somewhere else (ex. backup on USB) then import them with Kleopatra.
-
Otherwise if you don't have any gpg keys at all then generate new keys. you can generate gpg keys with Kleopatra that comes with gpg4win or you can do the same in powershell by typing:
gpg --default-new-key-algo rsa4096 --gen-key
At the prompt, specify your options, email, password etc. when asked.
-
Now it's time to gather information and tell git about our gpg keys:
gpg --list-secret-keys --keyid-format LONG
From the list of GPG keys, copy the GPG key ID you'd like to use. In the following example, the GPG key ID is
3AA5C34371567BD2
Example:
C:\Users\User> gpg --list-secret-keys --keyid-format LONG C:/Users/User/AppData/Roaming/gnupg/pubring.kbx ----------------------------------------------- sec 4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10] 4096R/42B317FD4BA89E7A uid [ultimate] your_username (key for github) <youremail@mail.com> ssb 4096R/42B317FD4BA89E7A 2017-09-13 [E] [expires: 2017-09-12]
Paste the text below, substituting in the GPG key ID you'd like to use. Tell git about your signing key, and tell it that you want to sign all commits by default:
git config --global user.signingkey 3AA5C34371567BD2 git config --global commit.gpgsign true
Export public key to clipboard (Note that Set-Clipboard cmdlet works only with newer powershell versions) if Set-Clipboard doesn't work export the the key using cmd, as shown in the second command:
gpg --armor --export 3AA5C34371567BD2 | Set-Clipboard
Version to export public key to clipboard if
Set-Clipboard
doesn't work:gpg --armor --export 3AA5C34371567BD2 > gpgkey.txt cmd clip < gpgkey.txt exit del gpgkey.txt
Now go to your Github account > settings > SSH and GPG Keys > Add new GPG key and press CTRL+V into box to paste the key.
-
Same applies to ssh keys, if you don't have existing ones generate new ones, you don't need to worry about where keys are (will be) stored because all ssh programs write keys to same directory that is
~\.ssh
Type following to generate new keys:
ssh-keygen -t rsa -b 4096 -C "[email protected]"
When you're prompted to "Enter a file in which to save the key," press Enter. This accepts the default file location, also specify new password for the key.
If your ssh keys are somewhere else, (ex. backed up on USB), you'll first need to create a new folder for them:
NOTE: I provide command for this because on server platforms it might not be possible with mouse.mkdir $env:USERPROFILE\.ssh
Copy/paste
id_rsa
andid_rsa.pub
from your backup into new~\.ssh
folder.Once you have your keys in default location, add your private key to ssh-agent:
ssh-add $env:USERPROFILE\.ssh\id_rsa
NOTE:
ssh-add
without arguments adds the default keys~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa. ~/ssh/id_ed25519, and ~/.ssh/identity
if they exist.Copy ssh public key to clipboard (again if
Set-Clipboard
doesn't work see second command below)Get-Content $env:USERPROFILE\.ssh\id_rsa.pub | Set-Clipboard
Version to copy ssh public key to clipboard if
Set-Clipboard
doesn't work:Get-Content $env:USERPROFILE\.ssh\id_rsa.pub > sshkey.txt cmd clip < sshkey.txt exit del sshkey.txt
Now go to your Github account > settings > SSH and GPG Keys > Add new SSH key and press CTRL+V into box to paste the key.
-
You also want to tell git about yourself, for users of private email type in private email below ex.
[email protected]
:git config --global user.name "your name or username" git config --global user.email youremail@example.com
-
next thing to do is to make
gpg-agent
cache your password longer, say for at least 2h so that you don't have to input gpg key password every time you commit!Next we'll create
gpg-agent.conf
in%appdata%\gnupg
and input settings into a file:New-Item -Path $env:appdata\gnupg\gpg-agent.conf -ItemType File Set-Content -Path $env:appdata\gnupg\gpg-agent.conf -Encoding utf8 -Value "default-cache-ttl 7200" Add-Content -Path $env:appdata\gnupg\gpg-agent.conf -Encoding utf8 -Value "max-cache-ttl 14400"
To set pin entry to wait 2 minutes for input set:
Add-Content -Path $env:appdata\gnupg\gpg-agent.conf -Encoding utf8 -Value "pinentry-timeout 120"
To have gpg-agent log it's activity about password caching run this:
Add-Content -Path $env:appdata\gnupg\gpg-agent.conf -Encoding utf8 -Value "debug-level guru" Add-Content -Path $env:appdata\gnupg\gpg-agent.conf -Encoding utf8 -Value "log-file $env:appdata\gnupg\gpg-agent.log"
Next we stop gpg-agent and start it again:
gpgconf --kill gpg-agent gpgconf --launch gpg-agent
You can adjust these numbers which represent for how many seconds gpg-agent will cache password.
Above numbers mean, default-cache 2h, max-cache 4h and pin entry 2 minutes.The meaning of these options is as follows:
-
default-cache-ttl n
Sets the time a cache entry is valid to n seconds. Each time a cache entry is accessed, the entry's timer is reset. Default is 10 minutes (600 seconds)
-
max-cache-ttl n
Sets the maximum time a cache entry is valid to n seconds. After this time a cache entry will be expired even if it has been accessed recently. Default is 2 hours (7200 seconds)
-
pinentry-timeout n
This option sets the pinentry to timeout after n seconds with no user input. Default value of 0 does not ask the pinentry to timeout
-
-
Now last thing to do is to install posh-git module so that you get color prompt in powershell when working with git repos.
More about posh-git and it's options
NOTE: If you have at least PowerShell 5 with PackageManagement installed, you can use the package manager to install posh-git for you.
Close Administrative powershell and the other powershell too, to update environment and open a new user mode powershell, then install posh-git:
First we need to check and if necessary set execution policy for current user, Open up Powershell (standard user) and check current execution policy:
Get-ExecutionPolicy
If it's not RemoteSigned change execution policy:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
If you never installed posh-git then:
PowerShellGet\Install-Module posh-git -Scope CurrentUser -AllowPrerelease
Otherwise to update existing one:
PowerShellGet\Update-Module posh-git
Finally import module and tell powershell to import it each next time:
Import-Module posh-git Add-PoshGitToProfile -AllHosts
NOTE: Keep in mind, that there are multiple $profile scripts. ex: one for the console and a separate one for the ISE. That's why we use
-AllHosts
-
Final step is to reverse/reset execution policy for both administrative and user mode PowerShell:
For Windows PowerShell, default itsRestricted
and for PowerShell Core it isRemoteSigned
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
That's it, it's recommended to reboot system and start testing your git setup with PowerShell, try experimenting push/pull/commit etc.., but basically you should now be able to work with git in powershell, and the ssh-agent will not ask you for password because it runs as service on Windows, and also gpg-agent will ask you for password either every 2h or max. 4h
NOTE: Now treat your MSYS terminal that comes with git as obsolete on your system, you have no reason to use it anymore, because even though git will use your new setup the MSYS terminal itself continues to use old settings and variables and ssh-agent will most likely not cache your keys because in MSYS terminal environment there are now two ssh programs resulting in conflict.
If you encounter problems or have suggestion please report. happy coding! 😀
-
Show options used by gpg-agent now
gpgconf --list-options gpg-agent
In this output you want to see values your options only and make sure values are those you entered into gpg-agent.conf
-
See if gpg-agent has issues with options
gpgconf --check-options gpg-agent
result of
gpg-agent.exe:1:1:
means no problems, anything else is error -
List directories used by gpg suite
gpgconf --list-dirs
what you are looking for here is
homedir
which is where your gpg-agent.conf must be saved to be recognized -
Test gpg-agent.conf file (replace USERNAME with your )
gpgconf --check-config "$env:appdata\\gnupg\\gpg-agent.conf"
Test gpg-agent.conf file, this will likely fail probably a bug
-
Test gpg software suite
gpgconf --check-programs
Verify all programs of gpg suite are OK (status must be :1:1) -
parse the configuration file and returns with failure if the configuration file would prevent gpg from startup
gpg-agent --gpgconf-test
-
If things don't work well wit gpg even after reboot, make sure to delete
gpg-agent.conf
file, and set these settings in Kleopatra program that comes with gpg4win in following location- Kleopatra -> Settings -> Configure Kleopatra -> GnuPG system -> Private keys -> Options controlling the security
- Here setup caching options, click apply/OK to let Kleopatra generate new gpg-agent.conf and reboot system
This were the most useful links to help me out assemble this tutorial:
An even easier solution is mentioned here, but let's detail it a bit.
scoop
Scoop is a package manager. It downloads, installs, updates and manages packages.
git
,win32-openssh
andsudo
.And there you go.