Skip to content

Instantly share code, notes, and snippets.

Created June 8, 2020 11:20
  • Star 38 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Allow configuring multiple ssh deploy keys with git
# Script to use custom ssh keys for various git repositories
# Run without arguments to get usage info.
# How it works:
# When used with SSH, git sends the path to the repository in the SSH command.
# @see:
# We extract this info and search for a key with the name.
# Based on the source, this seems to be used format since v2.0 at least.
# @see:
if [[ $# -eq 0 ]]; then
echo "Usage"
echo "Set script as GIT_SSH_COMMAND"
echo "Add SSH keys for git repositories under ~/.ssh/git-keys/ folder."
echo "File name format:"
echo " For the repository"
echo " Put the private key into the file github-practice"
echo " (Note: slash converted to dash in path, no extension)"
echo ""
echo "Uses ssh by default, use GIT_SSH_COMMAND_REALSSH envvar to override."
echo "For debugging set log output in envvar GIT_SSH_COMMAND_DEBUGLOG."
exit 1
function debuglog() {
[ ! -z "$GIT_SSH_COMMAND_DEBUGLOG" ] && (echo `date +%FT%T` "$@") >> $GIT_SSH_COMMAND_DEBUGLOG
return 0
for CMD_BUF in "$@"; do :; done
debuglog "Value of cmd.buf is: '$CMD_BUF'"
# @source:
declare -a "array=($( echo "$CMD_BUF" | sed 's/[][`~!@#$%^&*():;<>.,?/\|{}=+-]/\\&/g' ))"
for CMD_PATH in "${array[@]}"; do :; done
CMD_PATH=$(echo "$CMD_PATH" | sed 's/\\//g')
if [[ $CMD_PATH == *.git ]] ;
REPOKEY=$(echo "$CMD_PATH" | sed 's/\.git//g' | sed 's/\//-/g')
KEYFILE=$(echo ~/.ssh/git-keys/$REPOKEY)
if [[ -f "$KEYFILE" ]]
debuglog "Key '$KEYFILE' exists"
IDENTITY=$(echo "-i $KEYFILE")
debuglog "Key '$KEYFILE' is missing"
debuglog "No repo name detected. Skipping"
set -- $SSH $IDENTITY "$@"
debuglog "Calling with '$@'"
Copy link

gubatron commented Jun 8, 2020


Copy link

mpdude commented Jul 4, 2020

Could you please explain what the set -- does in combination with "$@"?

Copy link

gubatron commented Jul 6, 2020

@ Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" ... If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters, "$@" and $@ expand to nothing

Copy link

mpdude commented Jul 6, 2020

What does the set — do then?

Copy link

gubatron commented Jul 6, 2020

The -- is the standard "don't treat anything following this as an option"

Copy link

Very useful script. Could you possibly add a license?

Copy link

vhermecz commented Jul 6, 2020 via email

Copy link

That's great, TYVM!

Copy link

nice work! thanks!

Copy link

trompx commented Dec 19, 2020

Thanks for the script @vhermecz !
I have a hard time to make it work, I set the script in a bin folder and in my bashrc I export GIT_SSH_COMMAND=$(custom_keys_git_ssh). Unfortunately, when I run a git command in an initialized repo folder, no parameters are passed ($@ is empty). Any tips ?
Or do I have to set it directly in the local repo .gitconfig [core] sshCommand = ... ?
UPDATE: for those wondering the same, you just have to export GIT_SSH_COMMAND=custom_keys_git_ssh

Copy link

cvladan commented Apr 9, 2021

Great idea! And execution. Thanks!

Copy link

Skarlso commented Jun 29, 2021

Very cool! 2021 and we STILL have to use "hacks" in order to get this stuff working. :/ Super sad, but this is a very lovely script. Thanks. :)

Copy link

Weird that github requires this, on bitbucket it doesn't seem to be a problem

Copy link

reld commented Oct 8, 2021

Brilliant script!
Thank you very much for sharing this 🙏

Copy link

mav2287 commented Oct 20, 2021

For anyone wanting to use this with GitHub actions. You can create a deploy key for each repo you want to pull in, then put the private key into the GitHub Secret of the repo that will pull it. Then you need to add the following 2 steps before you call composer install in your main.yaml file:

      - name: Set Private Repos
        run : |
          mkdir ~/.ssh ~/.ssh/git-keys
          echo '${{ secrets.YOUR_SECRET_DEPLOY_KEY }}' > ~/.ssh/git-keys/VENDOR-REPO-NAME
          find ~/.ssh/git-keys/ -type f -name "*" -exec chmod 600 {} +

      - name: Set Git SSH Wrapper
        run : |
          sudo apt-get -qq -y update && sudo apt-get -qq -y install wget
          wget -nv -O ~/custom_keys_git_ssh
          chmod u+x ~/custom_keys_git_ssh
          git config --global core.sshCommand ~/custom_keys_git_ssh

This assumes you are using ubuntu-latest for your CI. You can also copy paste the echo '${{ secrets.YOUR_SECRET_DEPLOY_KEY }}' > ~/.ssh/git-keys/VENDOR-REPO-NAME below itself as many times as you need for the number of private repos you are using.

If you need to get the debug output you can just set the GIT_SSH_COMMAND_DEBUGLOG environmental variable and create a step with run: cat ~/git_ssh.log at some point after you run composer install. ​If setting GIT_SSH_COMMAND_DEBUGLOG in your main.yaml you MUST use /home/runner/ instead of ~/ or it won't write the output.

 ​GIT_SSH_COMMAND_DEBUGLOG: /home/runner/git_ssh.log

Copy link

abbluiz commented Jan 12, 2022

For some reason, I cannot make it work when ~/.ssh/config has:

Host *

Also, it gives me this warning:

Cloning into 'laravel-oauth-introspection'...
Warning: Identity file  /home/labb/.ssh/git-keys/userh-dev-laravel-oauth-introspection not accessible: No such file or directory.

Even though that file exists.

However, if I don't include .ssh/config, it does work.

Tested on Alpine 3.15 and Fedora 35.

Copy link

For those confused:

tested on

ubuntu 20.04 headless server


  1. save the above script as and chmod +x it
  2. note the full path
  3. create a new ssh key pair using ssh-keygen
  4. mkdir ~/.ssh/git-keys
  5. move the key pair in step 3 into ~/.ssh/git-keys and rename the keys as suggested by the script i.e. if the git url is then rename the private as github-practice and public
  6. run export GIT_SSH_COMMAND=/full/path/to/
  7. add the .pub to the repo deploy keys
  8. grab the ssh git url. DO NOT use the https git url.
  9. pick the place where you want to run git clone git ssh url


Copy link

In newer versions of git, we can set the "core.sshCommand" option to avoid using the "GIT_SSH_COMMAND" from the command line - see an more in depth answer here

Copy link

Sorry @cristiancalara i have issues understanding so I think I will stick to this ssh script but thanks for sharing

Copy link

nheimann1 commented Apr 23, 2022

Thank you for that.

It works for me when using git clone but doesn't work when the repo is deinfed in composer.

For some reason the debug log is not working for me as well ,so I can't provide the logs here.

What I did:

  • For context, I got to this script from this blog from the part of Repository-name based key selection
  • I config git to use this script by git config --global core.sshCommand /path/to/your/
  • My repo name is vendor/repo1.subname.git
  • I copied the private/public keys to ~/.ssh/git-keys/vendor-repo1.subname
  • When I git clone the project it only works when I keep the name of the private key vendor-repo1.subname. If I change it, it doesn't work, which tells me it indeed uses this script
  • When I'm doing composer install on a different project which consumes vendor/repo1.subname.git
               "type": "vcs",
               "url": ""

I get the result Your GitHub credentials are required to fetch private repository metadata (

Any ideas?

Copy link

I am just guessing here, but maybe the problem is related to this: composer/composer#5312 (also see

Copy link

We tested it again with clean environment and it seems like it is working well.

Thank you for your response.

Copy link

Hi just created a Github action that uses this gist.
Let me know if it works for you too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment