Specify an SSH key for git push for a given domain
Asked Answered
S

20

526

I have the following use case: I would like to be able to push to [email protected]:gitolite-admin using the private key of user gitolite-admin, while I want to push to [email protected]:some_repo using 'my own' private key. AFAIK, I can't solve this using ~/.ssh/config, because the user name and server name are identical in both cases. As I mostly use my own private key, I have that defined in ~/.ssh/config for [email protected]. Does anyone know of a way to override the key that is used for a single git invocation?

(Aside: gitolite distinguishes who is doing the pushing based on the key, so it's not a problem, in terms of access, ownership and auditing, that the user@server string is identical for different users.)

Sabayon answered 28/10, 2011 at 9:57 Comment(1)
Closely related: stackoverflow.com/questions/4565700/…Labio
G
845

Even if the user and host are the same, they can still be distinguished in ~/.ssh/config. For example, if your configuration looks like this:

Host gitolite-as-alice
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_rsa.alice
  IdentitiesOnly yes

Host gitolite-as-bob
  HostName git.company.com
  User git
  IdentityFile /home/whoever/.ssh/id_dsa.bob
  IdentitiesOnly yes

Then you just use gitolite-as-alice and gitolite-as-bob instead of the hostname in your URL:

git remote add alice git@gitolite-as-alice:whatever.git
git remote add bob git@gitolite-as-bob:whatever.git

Note

You want to include the option IdentitiesOnly yes to prevent the use of default ids. Otherwise, if you also have id files matching the default names, they will get tried first because unlike other config options (which abide by "first in wins") the IdentityFile option appends to the list of identities to try. See: https://serverfault.com/questions/450796/how-could-i-stop-ssh-offering-a-wrong-key/450807#450807

Grass answered 28/10, 2011 at 10:3 Comment(15)
Awesome, thanks. I hadn't understood that you could freely choose an 'alias' for the Host specification in the ~/.ssh/configSabayon
Thanks too for this answer! One gotcha for me was that IdentityFile needs to be a full path (I only put id_rsa.rick as my argument to IdentityFile, and this failed). See the ssh_config(5) man page for other syntax for IdentityFile.Superfamily
Thank you so much fo rthe clear and very helpful answer. I had tried to get this working for a while and gave up before with the assumption that the same user had to use the same id_rsa private key file.Bioastronautics
The git@ part in the remote is not necessary as it is given in the User line of the config.Dareen
You can use github-keygen to easily add such a config for Github accounts.Dareen
I'm using windows with Git Bash. For the identity file line do I write: IdentityFile ~davey/.ssh/id_rsa.davey or IdentityFile c:\Users\davey\.ssh\id_rsa.davey?Elana
I was struggling with this solution until I added another line containing IdentitiesOnly yes immediately after the line with IdentityFile for the host. It seems it was passing along multiple identities and one of those was blocked from accessing the host.Artificial
I had been constantly receiving repository access denied error with git commands while ssh commands worked. Adding the IdentitiesOnly yes line solved the issue.Bigamist
Make sure that you've added your key to ssh using ssh-add ~/.ssh/identity (Linux, Mac), otherwise it won't be used even if it is specified in the IdentifyFile.Vannoy
Do not forget to add the HostName to known_hosts : stackoverflow.com/questions/13363553/…Ohg
I posted a tweak to this answer below, using url rewriting in git, which removes the need to change remotes: https://mcmap.net/q/13948/-specify-an-ssh-key-for-git-push-for-a-given-domainGreed
For the ones who their host is like github.com/CompanyName, they need to set like Host github.com-companyname and clone like git clone [email protected]:companyname/reponame.gitBombycid
The examples in this post were confusing to me, therefore I struggled to get this to work. First of all if your trying to connect to github, make "host github.com" and "Hostname "github.com". Also "IdentityFile" is your PRIVATE key so put the full path "/home/yourusername/.ssh/id_ed25519" or "id_rsa" if using rsa. Looking at the example now I understand what they were trying to share, but it was confusing when first readingOctave
@JustinLau, IdentitiesOnly yes breaks (remote) agent way of authentication. JFYI, Mark.Hegarty
this didn't work for me (in my macbook) until i did this: ssh-add ~/.ssh/my_id_file i copied my key files from another computer.Toxoplasmosis
F
195

Configure your repository using git config

git config --add --local core.sshCommand 'ssh -i <PATH_TO_SSH_KEY>'

This applies to your local repository only.

Note: Use your private ssh key, not the one which by default ends with .pub.

Forelli answered 9/6, 2020 at 8:39 Comment(6)
I like this way because it works on a per repo basis and it's persistantEvered
very good answer - and unlike editing the ~/.ssh/config - this is repo-specificHartwig
Great answer! We are using it in jenkins job, so we need it only for a few seconds, so once it is done we are setting it off like this git config --unset --local core.sshCommand '<<ssh_token_path>>'Reproduce
Works on Windows as well - remember to replace the ` \ ` in the path with ` \\ `.Collective
You may also clone a repo and give it the appropriate config before fetching files using the -c option: git clone -c core.sshCommand="ssh -i <<<PATH_TO_SSH_KEY>>>" git@host:repo.git.Goosy
@SzczepanHołyszewski private. No need to abuse "?"Forelli
E
136

You can utilize git environment variable GIT_SSH_COMMAND. Run this in your terminal under your git repository:

GIT_SSH_COMMAND='ssh -i ~/.ssh/your_private_key' git submodule update --init

Replace ~/.ssh/your_private_key with the path of ssh private key you wanna use. And you can change the subsequent git command (in the example is git submodule update --init) to others like git pull, git fetch, etc.

Enthusiastic answered 13/5, 2017 at 12:58 Comment(6)
Full doc is at git-scm.com/docs/git#git-codeGITSSHcode; it needs a recentish Git (>=2.3.*) though.Waterfowl
Thank you for a simple solution that does not require anything except setting one environment variable.Debark
Note that your ~/.ssh/id_rsa (or whatever your default key is) will take precedence over the one you pass in via -i. So you really want to use GIT_SSH_COMMAND='ssh -i ~/.ssh/your_private_key -o IdentitiesOnly=yes' to make it ignore other keysCrooks
how can you update git push? I couldn't find it in the documentationSuellensuelo
Would be nice to create either bash or git aliases -- similar to sinelaw's answer but using this method instead of having to create scripts somewhere.Sharpwitted
I needed to also force an empty config because my main one was overwriting the -i flag -F /dev/nullTrimeter
C
60

An alternative approach to the one offered above by Mark Longair is to use an alias that will run any git command, on any remote, with an alternative SSH key. The idea is basically to switch your SSH identity when running the git commands.

Advantages relative to the host alias approach in the other answer:

  • Will work with any git commands or aliases, even if you can't specify the remote explicitly.
  • Easier to work with many repositories because you only need to set it up once per client machine, not once per repository on each client machine.

I use a few small scripts and a git alias admin. That way I can do, for example:

git admin push 

To push to the default remote using the alternative ("admin") SSH key. Again, you could use any command (not just push) with this alias. You could even do git admin clone ... to clone a repository that you would only have access to using your "admin" key.

Step 1: Create the alternative SSH keys, optionally set a passphrase in case you're doing this on someone else's machine.

Step 2: Create a script called “ssh-as.sh” that runs stuff that uses SSH, but uses a given SSH key rather than the default:

#!/bin/bash
exec ssh ${SSH_KEYFILE+-i "$SSH_KEYFILE"} "$@"

Step 3: Create a script called “git-as.sh” that runs git commands using the given SSH key.

#!/bin/bash
SSH_KEYFILE=$1 GIT_SSH=${BASH_SOURCE%/*}/ssh-as.sh exec git "${@:2}"

Step 4: Add an alias (using something appropriate for “PATH_TO_SCRIPTS_DIR” below):

# Run git commands as the SSH identity provided by the keyfile ~/.ssh/admin
git config --global alias.admin \!"PATH_TO_SCRIPTS_DIR/git-as.sh ~/.ssh/admin"

More details at: http://noamlewis.wordpress.com/2013/01/24/git-admin-an-alias-for-running-git-commands-as-a-privileged-ssh-identity/

Candycecandystriped answered 24/1, 2013 at 3:12 Comment(2)
Very nice answer. Don't forget to add double quotes around $@ -> "$@" to be safe.Mag
@Candycecandystriped Does this still work? I get Permission denied error all the timeFairlead
G
54

I've cribbed together and tested with github the following approach, based on reading other answers, which combines a few techniques:

  • correct SSH config
  • git URL re-writing

The advantage of this approach is, once set up, it doesn't require any additional work to get it right - for example, you don't need to change remote URLs or remember to clone things differently - the URL rewriting makes it all work.

~/.ssh/config

# Personal GitHub
Host github.com
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/github_id_rsa

# Work GitHub
Host github-work
  HostName github.com
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/work_github_id_rsa

Host *
  IdentitiesOnly yes

~/.gitconfig

[user]
    name = My Name
    email = [email protected]

[includeIf "gitdir:~/dev/work/"]
    path = ~/dev/work/.gitconfig

[url "github-work:work-github-org/"]
    insteadOf = [email protected]:work-github-org/

~/dev/work/.gitconfig

[user]
    email = [email protected]

As long as you keep all your work repos under ~/dev/work and personal stuff elsewhere, git will use the correct SSH key when doing pulls/clones/pushes to the server, and it will also attach the correct email address to all of your commits.

References:

Greed answered 24/10, 2019 at 23:12 Comment(3)
How does this work with cloning? includeIf should only work if there's a .git directory present I thought?Thereunder
Wait I get it, it's the URL rewriting that takes care of that. This answer is incredibly useful!Thereunder
Work but had to remove the UseKeychain line. For more info: https://mcmap.net/q/14120/-ssh-config-quot-bad-configuration-option-usekeychain-quot-on-mac-os-sierra-10-12-6Arleenarlen
T
25

To use a specific key on the fly:

GIT_SSH_COMMAND='ssh -i $HOME/.ssh/id_ed25519 -o IdentitiesOnly=yes -F /dev/null' git push origin c13_training_network

Explanation:

  • local ENV var before doing the push
  • -i specifies key
  • -F forces an empty config so your global one doesn't overwrite this temporary command
Trimeter answered 8/12, 2020 at 20:31 Comment(3)
This one actually helped in my case. The mere ssh -i ... wasn't enough, got to add these params as wellNicky
this should be the answer, as it was the only one that worked for me in 2023Hara
Honestly, might just be easier to alias this command :) thxCleruchy
P
17

From git 2.10 upwards it is also possible to use the gitconfig sshCommand setting. Docs state :

If this variable is set, git fetch and git push will use the specified command instead of ssh when they need to connect to a remote system. The command is in the same form as the GIT_SSH_COMMAND environment variable and is overridden when the environment variable is set.

An usage example would be: git config core.sshCommand "ssh -i ~/.ssh/[insert_your_keyname]

In some cases this doesn't work because ssh_config overriding the command, in this case try ssh -i ~/.ssh/[insert_your_keyname] -F /dev/null to not use the ssh_config.

Paderna answered 10/6, 2019 at 17:55 Comment(0)
M
13

One Unix based systems (Linux, BSD, Mac OS X), the default identity is stored in the directory $HOME/.ssh, in 2 files: private key: $HOME/.ssh/id_rsa public key: $HOME/.ssh/id_rsa.pub When you use ssh without option -i, it uses the default private key to authenticate with remote system.

If you have another private key you want to use, for example $HOME/.ssh/deploy_key, you have to use ssh -i ~/.ssh/deploy_key ...

It is annoying. You can add the following lines in to your $HOME/.bash_profile : ssh-add ~/.ssh/deploy_key ssh-add ~/.ssh/id_rsa

So each time you use ssh or git or scp (basically ssh too), you don't have to use option -i anymore.

You can add as many keys as you like in the file $HOME/.bash_profile.

Maggot answered 5/6, 2016 at 3:16 Comment(0)
V
10

Another alternative is to use ssh-ident, to manage your ssh identities.

It automatically loads and uses different keys based on your current working directory, ssh options, and so on... which means you can easily have a work/ directory and private/ directory that transparently end up using different keys and identities with ssh.

Vile answered 2/1, 2014 at 2:6 Comment(0)
G
8

I am using Git Bash on Win7. The following worked for me.

Create a config file at ~/.ssh/config or c:/users/[your_user_name]/.ssh/config. In the file enter:

Host your_host.com
     IdentityFile [absolute_path_to_your_.ssh]\id_rsa

I guess the host has to be a URL and not just a "name" or ref for your host. For example,

Host github.com
     IdentityFile c:/users/[user_name]/.ssh/id_rsa

The path can also be written in /c/users/[user_name]/.... format

The solution provided by Giordano Scalzo is great too. https://mcmap.net/q/14121/-cannot-push-to-heroku-because-key-fingerprint

Gunpaper answered 17/9, 2014 at 23:57 Comment(0)
M
8

If you already have default ssh key config but want to use different for specific repository then this should do the trick:

git config core.sshCommand "ssh -i ~/.ssh/github-personal -o IdentitiesOnly=yes -F /dev/null"
Mentor answered 8/4, 2021 at 20:3 Comment(0)
I
7

One possibility to use ~/.ssh/config is to use the Match restriction instead of the Host restriction. In particular Match Exec calls a shell command to decide whether to apply the declarations or not. In bash you could use the following command:

[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]

This uses the bash [ command to verify if two strings are equal. In this case it is testing if the string [email protected]:gitolite-admin matches the output that is obtained from the $(git config --get remote.origin.url)'' command.

You can use any other command that identifies the repository that the shell is on. For this to work it is important to have the $SHELL variable defined to your shell, in my case /bin/bash. The full example would then be the following ~/.ssh/config:

Match Exec "[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Match Exec "[ [email protected]:some_repo = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

In this example I assumed that ~/.ssh/yourOwnPrivateKey contains your own private key and that ~/.ssh/gitolite-admin contains the private key of the user gitolite-admin. I included the IdentitiesOnly yes declaration to make sure that only one key is offered to the git server, mentioned by Mark Longair. The other declarations are just standard ssh options for git.

You can add this configuration if you have several some_repo that you want to use with different keys. If you have several repositories at [email protected] and most of them use the ~/.ssh/yourOwnPrivateKey it makes more sense to include this key as default for the host. In this case the ~/.ssh/config would be:

Match Exec "[ [email protected]:gitolite-admin = $(git config --get remote.origin.url)'' ]"
  IdentityFile ~/.ssh/gitolite-admin
  IdentitiesOnly yes

Host git.company.com
  IdentityFile ~/.ssh/yourOwnPrivateKey
  IdentitiesOnly yes
  ForwardAgent no
  ForwardX11 no
  ForwardX11Trusted no

Note that the order matters and the Host git.company.com restriction should appear after the Match Exec one or ones.

Inundate answered 19/5, 2020 at 10:4 Comment(4)
Thank you - this actually solves an issue that's been bugging me on VSCode - the Open On Github extensions would use the Host value in Host gitolite-as-alice (ignoring HostName) but this method avoids that problem! Note that you can also use wildcard to match: Match Exec "[[ $(git config --get remote.origin.url)'' == '[email protected]:YourOrganization'* ]]"Adila
Thanks you, I used second case and work with Match Exec "[[ $(git config --get remote.origin.url)'' == '[email protected]:YourOrganization'* ]]"Contrapose
Out of interest (I haven;t tried this approach yet though): why those single quotes are needed for? If this is plain Bash then the conditional can be as simple as this: Match Exec "[[ $(git config --get remote.origin.url) == [email protected]:YourOrganization/* ]]" (notice the trailing slash after the org name so it doesn't overlap with YourOrganizationAnother)Tanked
This is pretty awesome because you don't have to manipulate the actual git URL. However, it appears that this only works after the initial clone. git config --get remote.origin.url doesn't return a value when git clone is run.Manufactory
L
6

As someone else mentioned, core.sshCommand config can be used to override SSH key and other parameters.

Here is an exmaple where you have an alternate key named ~/.ssh/workrsa and want to use it for all repositories cloned under ~/work.

  1. Create a new .gitconfig file under ~/work:
[core]
  sshCommand = "ssh -i ~/.ssh/workrsa"
  1. In your global git config ~/.gitconfig, add:
[includeIf "gitdir:~/work/"]
  path = ~/work/.gitconfig
Loraine answered 30/1, 2020 at 2:35 Comment(0)
A
5

For git to figure out, that it should use a different SSH keys, apart from changing your config file, as mentioned here: https://mcmap.net/q/13948/-specify-an-ssh-key-for-git-push-for-a-given-domain you may also need to purge and reload an active SSH identities.

On Mac, do the following:

ssh-add -D
ssh-add ~/.ssh/id_rsa_one_that_you_want_to_use_instead

Using these two commands, and setting up the GIT URL to match the string defined in the Host of the ssh/config file, should allow you to use different SSH keys, for a different repositories.

For example for Host work.github.com use work.github.com as an URL when cloning your repository [email protected]:your/repository.git.

Anlace answered 7/7, 2021 at 14:32 Comment(0)
S
4

If using Git's version of ssh on windows, the identity file line in the ssh config looks like

IdentityFile /c/Users/Whoever/.ssh/id_rsa.alice

where /c is for c:

To check, in git's bash do

cd ~/.ssh
pwd 
Scram answered 20/8, 2014 at 6:6 Comment(0)
T
3

You might need to remove (or comment out) default Host configuration .ssh/config

Thirteenth answered 28/10, 2017 at 8:37 Comment(0)
V
3

Note: There's a way to apply the git config proposed in a previous answer for directories, not just at the repo level.

In my case, all projects were under the ~/work/ directory, so I updated my gitconfig as follows:

# ~/.gitconfig
...

[includeIf "gitdir:~/work/**"]
  path = "~/work/.gitconfig"
# ~/work/.gitconfig
[user]
  email = [email protected]
  name = Amr Awad
  sshCommand = ssh -i ~/.ssh/work

and now all repos inside the ~/work/ directory use the work key ~/.ssh/work without the need for configuring each repo separately.

Vivianviviana answered 14/4, 2022 at 8:14 Comment(0)
R
3

Here is the simple approach :

Default case

-From your local root git folder.

-Check the current type of authentication method HTTPS or SSH of your local repository.

   git remote -v

 Example using HTTPS:
 origin  https://github.com/juantorres9/SQLite_crash_cours.git (fetch)
 origin  https://github.com/juantorres9/SQLite_crash_cours.git (push)
 Example using SSH:
 origin  [email protected]:juantorres9/SQLite_crash_cours.git (fetch)
 origin  [email protected]:juantorres9/SQLite_crash_cours.git (push)

-Set the new authentication method of your choice in case it's not already set.

 For setting SSH
 git remote set-url origin [email protected]:USERNAME/REPOSITORY.git
 For setting HTTPS
 git remote set-url origin https://github.com/USERNAME/REPOSITORY.git

-Check again in case you want to double check

 git remote -v; 

-You are now able to use git push:fetch using your configured method.

git push origin master

Note special cases:

Multiple SSH keys: If you have multiple SSH keys for different services (e.g., GitHub, GitLab) and you want to specify which key to use for a particular repository. This is common when you have different accounts on different platforms, the use the following command

git config --local core.sshCommand 'ssh -i /path/to/your/private-key'

Using a non-default SSH key file: If your SSH key file is not in the default location (~/.ssh/id_rsa), and you want to specify its location use the same command above.

Last but not least , check updated official doc https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories

Reticulate answered 11/6, 2022 at 15:2 Comment(2)
In most cases this should work, but rarely cases where the git remote commands like push, pull, and fetch have no idea what your SSH private key is. In such a case, you might need to configure the key manually.Monde
Thanks for the contribution @OgadaStanleyChinedu, indeed we might need to specify a non default private SSH key when contacting the remote repository, otherwise we could have authentication issues if the wrong key is used or not set . (update done )Reticulate
M
2

you most specified in the file config key ssh:

# Default GitHub user
Host one
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-one
 IdentitiesOnly yes

#two user
Host two
 HostName gitlab.com
 User git
 PreferredAuthentications publickey
 IdentityFile ~/.ssh/key-two
 IdentitiesOnly yes
Mainspring answered 26/1, 2019 at 5:40 Comment(0)
M
1

If you are getting an SSH permission denied Error when running commands like git push, pull, or fetch even after you have copied your SSH public key to GitHub.

Use this:

git config --add --local core.sshCommand 'ssh -i /path-to-ssh-private-key'

E.g

git config --add --local core.sshCommand 'ssh -i /home/user/.ssh/github-key'

You're done!

Optionally you can verify your change with this:

git config --local --get core.sshCommand
Monde answered 28/1 at 1:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.