Tuesday, March 15, 2016

Set up SSH for Git on GitHub

Step 1: Check for SSH keys:

First, we need to check for existing SSH keys on your computer. Open up your Git Bash and type:

# ls -al ~/.ssh

Check the directory listing to see if you already have a public SSH key. The default public key file names are:


Step 2: Generate a new SSH key:

To generate a new SSH key, copy and paste the text below, making sure to substitute in your email address. The default settings are preferred, so when you're prompted to "Enter a file in which to save the key", just press Enter to continue.

# ssh-keygen -t rsa -C "username@example.com"

Note: we strongly recommend a very good, secure passphrase. For more information, see Working with SSH key passphrases.

Next, you'll be asked to enter a passphrase. Type a passphrase.

Step 3: Run ssh-agent - a passphrase manager:

ssh-agent can securely save your passphrase, so you don't have to re-enter it every time you use the key.

On FreeBSD, start the ssh-agent in the background. The following command will generate C-shell commands on stdout:
# eval `ssh-agent -c`

On Linux, start the ssh-agent in the background. The following command will generate Bourne shell commands on stdout:
# eval `ssh-agent -s`

Agent pid 5989

Note: Why do we need to use eval instead of just ssh-agent? It is because ssh-add and ssh (assuming you are using the openssh implementations) require an environment variable to know how to talk to the ssh agent. If you started the agent in a different command prompt window to the one you're using now, or if you started it incorrectly, neither ssh-add nor ssh will see that environment variable set (because the environment variable is set locally to the command prompt it's set in).

This will start an agent automatically for each new command prompt window that you open (which is suboptimal if you open multiple command prompts in one session, but at least it should work):

# cat ~/.bashrc

# start up ssh-agent automatically when a new bash session starts.
# Note: the reason why I added -n "$SSH_TTY" is because without it, sftp and/or scp may fail at connection time if you have shell initialization (.profile, .bashrc, .cshrc, etc) which produces output for non-interactive sessions. This output confuses the sftp/scp client.
# Note: the other way: if [ -z "$SSH_AUTH_SOCK" -a -x "$SSHAGENT" ]; then

if [[ -z "$SSH_AUTH_SOCK" && -n "$SSH_TTY" && -a "$SSHAGENT" && -x "$SSHAGENT" ]]; then
  trap "kill $SSH_AGENT_PID" 0

With a little bit of if-then and a flat file, you can do this once and have all other consoles use the same one, instead of starting one per console, and (if you use key auth) having to ssh-add each time.

Just pipe the output of ssh-agent to a file, then run the file (e.g. with ‘source’ command), check the $SSH_AGENT_PID with ps, and if it’s not running, then run ssh-agent (again, piping its output to the file and then sourcing the file). Put your ssh-adds in there too so it will ask you on start.

For example here’s what I did:

if [[ -e $HOME/.sshagent.conf ]]; then
  . $HOME/.sshagent.conf

if `ps -p ${SSH_AGENT_PID}>/dev/null`; then
  ssh-agent >| $HOME/.sshagent.conf
  . $HOME/.sshagent.conf
  ssh-add ~/.ssh/id_dsa

This will run the SSH agent and authenticate only the first time you need it, not every time you open your Bash terminal. It can be used for any program using SSH in general, including ssh itself and scp. Just add this to /etc/profile.d/ssh-helper.sh:

ssh-auth() {
    # Start the SSH agent only if not running
    [[ -z $(ps | grep ssh-agent) ]] && echo $(ssh-agent) > /tmp/ssh-agent-data.sh

    # Identify the running SSH agent
    [[ -z $SSH_AGENT_PID ]] && source /tmp/ssh-agent-data.sh > /dev/null

    # Authenticate (change key path or make a symlink if needed)
    [[ -z $(ssh-add -l | grep "/home/$(whoami)/.ssh/id_rsa") ]] && ssh-add

# You can repeat this for other commands using SSH
git() { ssh-auth; command git "$@"; }

Note: ssh-agent is a tool that provides a secure way of storing and using your SSH keys.

Make sure ssh-agent is running:

# ps auxww | grep ssh-agent

If you want ssh-agent to forget your key after some time, you can configure it to do so by running:

# ssh-add -t 3600

You can change the passphrase for an existing private key without regenerating the keypair. Just type the following command:

# ssh-keygen -p

Start the SSH key creation process
Enter file in which the key is (/Users/you/.ssh/id_rsa): [Hit enter]
Key has comment '/Users/you/.ssh/id_rsa'
Enter new passphrase (empty for no passphrase): [Type new passphrase]
Enter same passphrase again: [One more time for luck]
Your identification has been saved with the new passphrase.

Step 4: Add your new key to the ssh-agent:

# ssh-add ~/.ssh/id_rsa

Note: if you see, Could not open a connection to your authentication agent, try running the ssh-agent by using the following command before you run ssh-add:

On FreeBSD:
# eval `ssh-agent -c`

On Linux:
# eval `ssh-agent -s`

Step 5: Add your SSH key to your GitHub account, copy the text:

# cat ~/.ssh/id_rsa.pub

Note: paste the text you copied above to your GitHub account.

Step 6: go to https://github.com/:

In the top right corner of any page, click on the "settings" icon.

In the user settings sidebar, click on "SSH keys".

Click on "Add SSH key".

In the "Title" field, add a descriptive label for the new key. For example, if you're using a personal Mac, you might call this key "Personal MacBook Air".

Paste your key into the "Key" field.

Click on "Add key".

Confirm the action by entering your GitHub password.

Step 7: Test everything out:

To make sure everything is working, you'll now try SSHing to GitHub. When you do this, you will be asked to authenticate this action using your password, which was the passphrase you created earlier.

# ssh -T git@github.com

Note: if you're switching from HTTPS to SSH, you'll now need to update your remote repository URLs (see below).

Note: if you receive a message about "access denied," you can read these instructions for diagnosing the issue.

Step 8: start pulling data from the repository stored on GitHub:

Clone the repository:

# git clone git@github.com:USERNAME/REPOSITORY_NAME.git

Switching remote URLs from HTTPS to SSH:

# git remote -v

origin https://github.com/USERNAME/REPOSITORY_NAME.git (fetch)
origin https://github.com/USERNAME/REPOSITORY_NAME.git (push)

# git remote set-url origin git@github.com:USERNAME/REPOSITORY_NAME.git

Verify new remote URL:

# git remote -v

origin git@github.com:USERNAME/REPOSITORY_NAME.git (fetch)
origin git@github.com:USERNAME/REPOSITORY_NAME.git (push)

Switching remote URLs from SSH to HTTPS:

# git remote -v

origin git@github.com:USERNAME/REPOSITORY_NAME.git (fetch)
origin git@github.com:USERNAME/REPOSITORY_NAME.git (push)

# git remote set-url origin https://github.com/USERNAME/REPOSITORY_NAME.git

Verify new remote URL:

# git remote -v

origin https://github.com/USERNAME/REPOSITORY_NAME.git (fetch)
origin https://github.com/USERNAME/REPOSITORY_NAME.git (push)

If you set the remote URLs to HTTPS instead of SSH, the next time you git fetch, git pull, or git push to the remote repository, you'll be asked for your GitHub username and password:


No comments: