Running SSH Agent when starting Git Bash on Windows
Asked Answered
M

11

211

I am using git bash. I have to use

eval `ssh-agent.exe`
ssh-add /my/ssh/location/

every time when I start a new git bash.

Is there a way to set ssh agent permanently? Or does windows has a good way to manage the ssh keys?

I'm a new guy, please give me detailed tutorial, thanks!

Methylal answered 23/8, 2013 at 13:37 Comment(6)
is /my/ssh/location/ equalivent to something like /c/Users/Foobar/.ssh/?Upswell
A similar problem has been posted at superuser.com/q/1238486/478378 which is resolved now. The following gist contains all the details gist.github.com/jiggneshhgohel/afe96f0d57bdbf8beba305a73905402d. Thanks.Cordy
For people reaching this question and if your ssh -Tv git@server-host-name works, in my case, it was the GIT_SSH environment variable that was set to Putty Plink from Tortoise Git. Deleting GIT_SSH did the trick. TortoiseGit still working fine.Coleencolella
^ Addressing @Nick's upvoted comment-question up there: No, it can't be directory, it has to be the private key file, e.g. ssh-add ~/.ssh/my_private_key.pem.Gossipry
There is now OpenSSH installed in Windows, and a ssh-agent service that just needs to be enabled. Install Git to install with external SSH to use it. I'll write full answer when I find how to forward it to WSL2 too.Prawn
See also: Super User: How to maintain ssh-agent login session with Windows 10's new OpenSSH and PowerShellAnnabal
P
196

2013: In a git bash session, you can add a script to ~/.profile or ~/.bashrc (with ~ being usually set to %USERPROFILE%), in order for said session to launch automatically the ssh-agent.
If the file doesn't exist, just create it.

This is what GitHub describes in "Working with SSH key passphrases".

The "Auto-launching ssh-agent on Git for Windows" section of that article has a robust script that checks if the agent is running or not.
Below is just a snippet, see the GitHub article for the full solution.

# This is just a snippet. See the article above.
if ! agent_is_running; then
    agent_start
    ssh-add
elif ! agent_has_keys; then
    ssh-add
fi

Other Resources:

"Getting ssh-agent to work with git run from windows command shell" has a similar script, but I'd refer to the GitHub article above primarily, which is more robust and up to date.


hardsetting adds in the comments (2018):

If you want to enter the passphrase the first time you need it, and not when opening a shell, the cleanest way to me is:

This way you don't even have to remember running ssh-add.


And Tao adds in the comments (2022):

It's worth noting why this script makes particular sense in Windows, vs (for example) the more standard linuxey script noted by @JigneshGohel in another answer:

By not relying on the SSH_AGENT_PID at all, this script works across different msys & cygwin environments.
An agent can be started in msys2, and still used in git bash, as the SSH_AUTH_SOCK path can be reached in either environment.
The PID from one environment cannot be queried in the other, so a PID-based approach keeps resetting/creating new ssh-agent processes on each switch.


szx mentions in the comments:

There is a downside to this solution: Once you kill/exit the initial Git Bash bash.exe instance that started ssh-agent, the agent is not accessible by other shell instances until you open a new one. This is not good.

Then you can modify the script to make sure ssh-agent persists across different Git Bash sessions. That would involve saving the agent's environment variables in a file that can be sourced by subsequent shells.

Add the check for an existing ssh-agent process to your ~/.bashrc or ~/.profile, and connect to it, or start a new one if necessary:

# Define a file to store the SSH agent environment variables
SSH_ENV="$HOME/.ssh/environment"

# Function to start ssh-agent and save its environment variables
function start_agent {
    echo "Initializing new SSH agent..."
    # Start new ssh-agent, with the environment variables stored in SSH_ENV
    ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
    echo "succeeded"
    chmod 600 "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    ssh-add
}

# Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    # Check if the agent is running
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

The .ssh/environment is used to store the ssh-agent environment variables (SSH_AGENT_PID and SSH_AUTH_SOCK).

  • If the file exists, it sources (loads) the environment variables from it and checks if the ssh-agent process referenced by SSH_AGENT_PID is still running. If the process is not running, it starts a new ssh-agent and updates the .ssh/environment file with the new environment variables.
  • If the .ssh/environment file does not exist, it means no ssh-agent has been started yet, or the file was deleted. The script then initializes a new ssh-agent, saves the environment variables in .ssh/environment, and adds the SSH key.
Problem answered 23/8, 2013 at 13:50 Comment(10)
One slight annoyance I had was if I knew I wasn't going to be using git I wouldn't enter in the ssh key passphrase, then every shell I opened asked for it again. This is state 1, agent running w/o key, so you could remove ssh-add from this section then if you don't enter your passphrase first time around you won't be asked again until you manually run ssh-add.Mononucleosis
@Gordon Which part of that help.github.com/articles/working-with-ssh-key-passphrases GitHub link has changed? Its content is still there, and does still seem relevant for this answer.Problem
@Andy2K11 If you want to enter the passphrase the first time you need it, and not when opening a shell, the cleanest way to me is removing the ssh-add from the .bash_profile, as you mentioned, and adding "AddKeysToAgent yes" to your .ssh/config file (see this answer: superuser.com/a/1114257/523133). This way you don't even have to remember running ssh-add.Gonagle
It's worth noting why this script makes particular sense in Windows, vs (for example) the more standard linuxey script noted by @JigneshGohel in another answer: by not relying on the SSH_AGENT_PID at all, this script works across different msys & cygwin environments. An agent can be started in msys2, and still used in git bash, as the SSH_AUTH_SOCK path can be reached in either environment. The PID from one environment cannot be queried in the other, so a PID-based approach keeps resetting/creating new ssh-agent processes on each switch.Enormous
@Enormous Thank you for this feedback. I have included your comment in the answer for more visibility.Problem
I get agent_start: command not found on Windows 11Gabriellagabrielle
@Gabriellagabrielle That is because, as commented right above that code (in the answer): "This is just a snippet". The associated article defines the agent_start() function in the .bashrc.Problem
Excellent! Upvoted. For anyone looking for super-beginner-friendly instructions all in one place, I just added this answer.Annabal
There is a downside to this solution: Once you kill/exit the initia Git Bashl bash.exe instance that started ssh-agent, the agent is not accessible by other shell instances until you open a new one. This is not good.Liquesce
@Liquesce Good point. I have edited this eleven-year-old answer to address your comment.Problem
C
37

P.S: These instructions are in context of a Bash shell opened in Windows 10 Linux Subsystem and doesn't mention about sym-linking SSH keys generated in Windows with Bash on Ubuntu on Windows

1) Update your .bashrc by adding following in it

# Set up ssh-agent
SSH_ENV="$HOME/.ssh/environment"

function start_agent {
    echo "Initializing new SSH agent..."
    touch $SSH_ENV
    chmod 600 "${SSH_ENV}"
    /usr/bin/ssh-agent | sed 's/^echo/#echo/' >> "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    /usr/bin/ssh-add
}

# Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    kill -0 $SSH_AGENT_PID 2>/dev/null || {
        start_agent
    }
else
    start_agent
fi

2) Then run $ source ~/.bashrc to reload your config.

The above steps have been taken from https://github.com/abergs/ubuntuonwindows#2-start-an-bash-ssh-agent-on-launch

3) Create a SSH config file, if not present. Use following command for creating a new one: .ssh$ touch config

4) Add following to ~/.ssh/config

Host github.com-<YOUR_GITHUB_USERNAME> 
HostName github.com
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_work_gmail # path to your private key
AddKeysToAgent yes


Host csexperimental.abc.com
IdentityFile ~/.ssh/id_work_gmail # path to your private key
AddKeysToAgent yes

<More hosts and github configs can be added in similar manner mentioned above>

5) Add your key to SSH agent using command $ ssh-add ~/.ssh/id_work_gmail and then you should be able to connect to your github account or remote host using ssh. For e.g. in context of above code examples:

$ ssh github.com-<YOUR_GITHUB_USERNAME>

or

$ ssh <USER>@csexperimental.abc.com

This adding of key to the SSH agent should be required to be performed only one-time.

6) Now logout of your Bash session on Windows Linux Subsystem i.e. exit all the Bash consoles again and start a new console again and try to SSH to your Github Host or other host as configured in SSH config file and it should work without needing any extra steps.

Note:

Thanks.

Cordy answered 8/8, 2017 at 8:14 Comment(5)
Interesting alternative, using WSL. +1Problem
@JigneshGohel Thank you, this script is perfect and v. clean! I did just wonder though, why do you have >> "${SSH_ENV}"? Shouldn't it just be > "${SSH_ENV}"? Yours works, of course, but it just ends up with a slowly longer and longer ~/.ssh/environment file, for (as I currently think!?) no reason... Many, many thanks though! I feel this script should just be included in the default .bashrc for WSL Ubuntu, it is so useful!Tetrabrach
Just a quick note that if you want to load an SSH key other than the default, change the "/usr/bin/ssh-add" line to "/usr/bin/ssh-add <your key name>"Sophi
I don't have the file ~/.ssh/environment. What is it supposed to contain?Elnora
Just in case the shopt no clobber' is on, you can future proof errors and force the redirect with "${SSH_ENV}" >| /dev/nullSpoon
L
15

If the goal is to be able to push to a GitHub repo whenever you want to, then in Windows under C:\Users\tiago\.ssh where the keys are stored (at least in my case), create a file named config and add the following in it

Host github.com
    HostName github.com
    User your_user_name
    IdentityFile ~/.ssh/your_file_name

Then simply open Git Bash and you'll be able to push without having to manually start the ssh-agent and adding the key.

Lousy answered 19/1, 2021 at 12:26 Comment(1)
A bit annoying to have a prompt for the passphrase everytime, but this is nice for me because my default shell can't run agent anyway.Chopping
M
8

I found the smoothest way to achieve this was using Pageant as the SSH agent and plink.

You need to have a putty session configured for the hostname that is used in your remote.

You will also need plink.exe which can be downloaded from the same site as putty.

And you need Pageant running with your key loaded. I have a shortcut to pageant in my startup folder that loads my SSH key when I log in.

When you install git-scm you can then specify it to use tortoise/plink rather than OpenSSH.

The net effect is you can open git-bash whenever you like and push/pull without being challenged for passphrases.

Same applies with putty and WinSCP sessions when pageant has your key loaded. It makes life a hell of a lot easier (and secure).

Matildamatilde answered 4/3, 2015 at 0:57 Comment(0)
L
6

I could not get this to work based off the best answer, probably because I'm such a PC noob and missing something obvious. But just FYI in case it helps someone as challenged as me, what has FINALLY worked was through one of the links here (referenced in the answers). This involved simply pasting the following to my .bash_profile:

env=~/.ssh/agent.env

agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }

agent_start () {
    (umask 077; ssh-agent >| "$env")
    . "$env" >| /dev/null ; }

agent_load_env

# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2= agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)

if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
    agent_start
    ssh-add
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
    ssh-add
fi

unset env

I probably have something configured weird, but was not successful when I added it to my .profile or .bashrc. The other real challenge I've run into is I'm not an admin on this computer and can't change the environment variables without getting it approved by IT, so this is a solution for those that can't access that.

You know it's working if you're prompted for your ssh password when you open git bash. Hallelujah something finally worked.

Lonlona answered 19/2, 2020 at 19:13 Comment(0)
C
4

Put this in your ~/.bashrc (or a file that's source'd from it) which will stop it from being run multiple times unnecessarily per shell:

if [ -z "$SSH_AGENT_PID" ]; then
        eval `ssh-agent -s`
fi

And then add "AddKeysToAgent yes" to ~/.ssh/config:

Host *
    AddKeysToAgent yes

ssh to your server (or git pull) normally and you'll only be asked for password/passphrase once per session.

Callable answered 27/6, 2020 at 17:2 Comment(0)
M
2

As I don't like using putty in Windows as a workaround, I created a very simple utility ssh-agent-wrapper. It scans your .ssh folders and adds all your keys to the agent. You simply need to put it into Windows startup folder for it to work.

Assumptions:

  • ssh-agent in path
  • shh-add in path (both by choosing the "RED" option when installing git
  • private keys are in %USERPROFILE%/.ssh folder
  • private keys names start with id (e.g. id_rsa)
Mylonite answered 28/7, 2017 at 5:14 Comment(3)
Nice! +1. I always work with openssh (not putty), so it is an interesting solution for private keys with passphrases.Problem
As you are on github already, then why not just make the source a git repository?Quinquereme
Just remove the /releases from the path. ;-)Mylonite
A
2

@VonC provided an excellent answer here.

I just want to provide the full script and all instructions in one place.

Reference these instructions here: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/working-with-ssh-key-passphrases?platform=windows

How to get ssh-agent to load your private ssh keys and require their passwords only once per boot in Windows

Tested in Windows 10 with Git For Windows 2.41.0-64-bit.

  1. In Git Bash, create your ~/.bashrc file

    # Create your `~/.bashrc` file (usually at `/c/Users/myusername/.bashrc`)
    touch ~/.bashrc
    
  2. In your editor of choice, edit that file now, and paste the following into the bottom of it. This script is from here. I only added the top and bottom comments, and the echo commands:

    # -------------------------------- START -----------------------------------
    # Auto-launch the ssh-agent and load all private keys on Git for Windows
    # Copied from: https://mcmap.net/q/12331/-running-ssh-agent-when-starting-git-bash-on-windows
    env=~/.ssh/agent.env
    
    agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }
    
    agent_start () {
        (umask 077; ssh-agent >| "$env")
        . "$env" >| /dev/null ; }
    
    agent_load_env
    
    # agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2=agent not
    # running
    agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)
    
    if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
        echo "Starting ssh-agent and adding your private keys."
        agent_start
        ssh-add
    elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
        echo "Adding your private keys to ssh-agent."
        ssh-add
    fi
    
    unset env
    # -------------------------------- END -------------------------------------
    
  3. Make Git Bash re-source the ~/.bashrc file changes.

    Either: manually re-source your ~/.bashrc file with . ~/.bashrc, or:

    close and re-open all Git Bash terminal windows.

    This auto-starts the ssh-agent, due to the script above you just added to your ~/.bashrc file.

  4. Add all private keys to your ssh-agent, if needed:

    Private keys with standard paths, such as ~/.ssh/id_ed25519 or ~/.ssh/id_rsa, are automatically added by the script when it calls ssh-add. However, if you have private keys with custom names or paths, add them now:

    ssh-add path/to/my/keys/id_ed25519
    ssh-add path/to/my/keys/id_rsa_custom_name
    # etc. 
    
  5. That's it! As the tutorial says:

    The ssh-agent process will continue to run until you log out, shut down your computer, or kill the process.

    Now, you only have to type each ssh key's private password once per Windows reboot, rather than once per git push or git pull-type operation, or once per Git Bash terminal, both of which were obnoxious options.

See also

  1. I'd also like to point out an alternative, well-documented solution by Atlassian and Bitbucket, here: https://support.atlassian.com/bitbucket-cloud/docs/set-up-personal-ssh-keys-on-windows/. In this solution, they require explicitly installing the Windows version of OpenSSH, as well as running some commands in the Windows PowerShell, and having Git Bash use the Windows version of OpenSSH. This is significantly different from my solution above, but it also works. I prefer my solution above, however, as I think it's easier, faster, and more-universal, and it doesn't require tinkering with Windows executables or PowerShell commands. Instead, it uses just the tools packaged with and provided by Git for Windows.
Annabal answered 27/6, 2023 at 21:32 Comment(1)
Nice. That should work indeed.Problem
I
1

Create a new .bashrc file in your ~ directory.

There you can put your commands that you want executed everytime you start the bash

Interfuse answered 23/8, 2013 at 13:50 Comment(3)
It has to work. Try to put something simple to such .bashrc file (like echo test and check if it's loaded when you execute Git Bash.Hadj
Also note that ~ in PowerShell is likely different than ~ in Git Bash/Cygwin depending on what version was installed and the user options specified.Carnahan
@Yar On Windows, put .bashrc in your user folder e.g. C:\Users\john.Prog
B
1

I wrote a script and created a git repository, which solves this issue here: https://github.com/Cazaimi/boot-github-shell-win .

The readme contains instructions on how to set the script up, so that each time you open a new window/tab the private key is added to ssh-agent automatically, and you don't have to worry about this, if you're working with remote git repositories.

Buckshot answered 27/12, 2020 at 13:40 Comment(0)
F
0

Simple two string solution from this answer:

For sh, bash, etc:

# ~/.profile
if ! pgrep -q -U `whoami` -x 'ssh-agent'; then ssh-agent -s > ~/.ssh-agent.sh; fi
. ~/.ssh-agent.sh

For csh, tcsh, etc:

# ~/.schrc
sh -c 'if ! pgrep -q -U `whoami` -x 'ssh-agent'; then ssh-agent -c > ~/.ssh-agent.tcsh; fi'
eval `cat ~/.ssh-agent.tcsh`
Fossil answered 13/10, 2017 at 20:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.