How to Set Up SSH Keys for GitHub and Servers

Secure Shell keys, commonly called SSH keys, give developers and administrators a safer and more convenient way to authenticate with GitHub, cloud instances, virtual private servers, and internal machines. Instead of typing a password for every connection, a person proves identity by using a private key stored on the local computer and a matching public key installed on the remote service. When configured correctly, SSH keys improve security, simplify workflows, and reduce the risk of password-based attacks.

TLDR: SSH keys work as a secure pair: a private key kept on the local machine and a public key added to GitHub or a server. A developer generates the key pair, protects it with a passphrase, adds the public key to the target account or server, and tests the connection. For best results, each person should use strong modern key types, restrict private key permissions, and rotate or remove old keys when access is no longer needed.

What SSH Keys Are and Why They Matter

An SSH key pair contains two linked files. The private key must remain secret and should never be shared, copied into chat, committed to Git, or uploaded to a public location. The public key can be safely shared with services such as GitHub or placed inside a server’s authorized_keys file.

When a connection begins, the remote system checks whether the public key is allowed. The local machine then proves it has the matching private key without actually sending that private key over the network. This makes SSH authentication more resistant to interception than ordinary password logins.

SSH keys are especially useful for GitHub because they allow a developer to clone, pull, and push repositories without repeatedly entering account credentials. They are also essential for server administration, automated deployments, CI/CD systems, and secure remote maintenance.

Choosing the Right Key Type

Modern systems commonly support several SSH key algorithms. For most current use cases, Ed25519 is a strong and efficient choice. It creates compact keys, performs quickly, and is widely supported by GitHub and many Linux servers.

If compatibility with older systems is required, RSA may still be used, but it should be generated with a larger size, such as 4096 bits. However, when the environment supports it, Ed25519 is usually preferred.

  • Recommended for modern systems: ed25519
  • Fallback for older systems: rsa with 4096 bits
  • Not recommended: outdated or weak key types that are no longer accepted by modern platforms

Checking for Existing SSH Keys

Before creating a new key, a developer may check whether an SSH key already exists on the local machine. On macOS, Linux, or Windows with Git Bash, the following command lists common SSH key files:

ls -al ~/.ssh

Common file names include:

  • id_ed25519 and id_ed25519.pub
  • id_rsa and id_rsa.pub
  • Custom names such as github_ed25519 or production_server

The file ending in .pub is the public key. The file without .pub is the private key. If an existing private key is still in use, it should not be overwritten accidentally.

Generating a New SSH Key

To create a new Ed25519 key, the user can run:

ssh-keygen -t ed25519 -C "user@example.com"

The email comment helps identify the key later, especially when it is added to GitHub or reviewed on a server. During generation, the command asks where to save the key. The default location is often acceptable for a primary key:

/home/username/.ssh/id_ed25519

On macOS, the path may look like:

/Users/username/.ssh/id_ed25519

On Windows with Git Bash, it commonly appears as:

/c/Users/username/.ssh/id_ed25519

When prompted for a passphrase, a strong passphrase should be used. A passphrase protects the private key if the device or file is stolen. Although leaving it empty may be convenient for some automated systems, personal keys should normally be protected.

If RSA is required for compatibility, the command can be:

ssh-keygen -t rsa -b 4096 -C "user@example.com"

Starting the SSH Agent and Adding the Key

The SSH agent stores decrypted private keys in memory during a login session. This allows a developer to enter the passphrase once instead of every time a Git or SSH command runs.

On many Linux and macOS systems, the agent can be started with:

eval "$(ssh-agent -s)"

Then the private key can be added:

ssh-add ~/.ssh/id_ed25519

If the key has a different file name, that name should be used instead:

ssh-add ~/.ssh/github_ed25519

On macOS, users may store the passphrase in the system keychain depending on SSH version and configuration. On Windows, Git Bash, OpenSSH for Windows, or a credential manager may handle key loading differently, but the principle remains the same: the private key must be available to the SSH client when authentication occurs.

Adding an SSH Key to GitHub

To use SSH with GitHub, the public key must be copied and added to the GitHub account. The public key can be displayed with:

cat ~/.ssh/id_ed25519.pub

The entire output should be copied. It usually begins with ssh-ed25519 and ends with the identifying comment, such as an email address. The private key file should never be copied into GitHub.

Inside GitHub, the user would typically open account settings, find SSH and GPG keys, choose New SSH key, enter a descriptive title, and paste the public key. A useful title might include the device name, such as Work Laptop or Home Desktop.

After the key is added, the connection can be tested:

ssh -T git@github.com

The first connection may show a host authenticity prompt. If the host fingerprint is correct, it can be accepted. A successful response usually confirms authentication and mentions that shell access is not provided, which is normal for GitHub.

Using SSH URLs for Git Repositories

GitHub repositories can be accessed using either HTTPS or SSH URLs. For SSH authentication, the remote URL should look similar to:

git@github.com:owner/repository.git

To clone a repository with SSH, the developer can run:

git clone git@github.com:owner/repository.git

For an existing repository that still uses HTTPS, the remote can be changed:

git remote set-url origin git@github.com:owner/repository.git

The current remote URL can be checked with:

git remote -v

Once the SSH key and remote URL are configured correctly, Git operations such as pull, fetch, and push should authenticate through SSH.

Adding an SSH Key to a Server

For a Linux server, the public key must be placed in the target user’s ~/.ssh/authorized_keys file. If password login is currently allowed, the easiest method is often:

ssh-copy-id username@server_ip

This command copies the public key to the server and sets up the required file. If ssh-copy-id is unavailable, the key can be added manually. The administrator logs into the server, creates the SSH directory, sets permissions, and appends the public key:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

The public key is pasted as a single line inside authorized_keys. Line breaks inside the key can cause authentication failure, so the full key must remain intact.

After installation, the connection can be tested from the local machine:

ssh username@server_ip

If the key file has a custom name, the -i option can be used:

ssh -i ~/.ssh/production_server username@server_ip

Configuring Multiple SSH Keys

Many professionals use more than one SSH key. For example, one key may be used for GitHub, another for a staging server, and another for production infrastructure. This separation limits damage if one key must be revoked.

The SSH client configuration file, located at ~/.ssh/config, can simplify multiple identities:

Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/github_ed25519
  IdentitiesOnly yes

Host production
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/production_server
  IdentitiesOnly yes

With this configuration, GitHub uses the specified GitHub key, while the production server can be reached with:

ssh production

This approach improves clarity and prevents the SSH client from offering too many keys during authentication.

Improving Server Security After Keys Work

Once key-based login has been tested successfully, the server administrator may choose to reduce password-based risks. On many Linux servers, SSH daemon settings are stored in:

/etc/ssh/sshd_config

Common hardening options include disabling root login and disabling password authentication. The exact settings depend on the environment, but they may look like:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Before disabling password authentication, at least one working SSH key login should be confirmed in a separate terminal session. Otherwise, the administrator could lock everyone out of the server.

After changes are made, the SSH service usually needs to be reloaded or restarted:

sudo systemctl reload ssh

On some distributions, the service may be named sshd instead of ssh.

Best Practices for SSH Key Management

  • Protect the private key: It should remain only on trusted devices and should never be emailed, pasted into tickets, or stored in repositories.
  • Use a passphrase: A passphrase adds protection if the private key file is exposed.
  • Create separate keys for separate purposes: GitHub, personal servers, work servers, and automation can each have dedicated keys.
  • Remove unused keys: Old laptops, former employees, retired servers, and abandoned automation accounts should have their keys revoked.
  • Check permissions: SSH is strict about file permissions. Private keys should usually be readable only by the owner.
  • Back up carefully: If a private key is backed up, the backup must be encrypted and protected.
  • Review access regularly: Periodic audits help ensure that only authorized keys remain active.

Common Troubleshooting Tips

If SSH authentication fails, the cause is often a small configuration issue. The user can run a verbose connection test to see more detail:

ssh -vT git@github.com

For a server, the command may be:

ssh -v username@server_ip

Common problems include incorrect file permissions, the wrong public key on the remote system, an SSH agent that has not loaded the key, or a repository still using an HTTPS remote. On servers, the authorized_keys file must belong to the correct user and must not be writable by other users.

FAQ

What is the difference between a public key and a private key?

The private key stays on the local machine and must be kept secret. The public key is shared with GitHub or placed on a server to allow authentication.

Can the same SSH key be used for GitHub and servers?

It can be used, but it is usually better to create separate keys for different services. Separate keys make access easier to manage and revoke.

What happens if a private key is lost?

If the private key is lost and no backup exists, it cannot be recovered from the public key. A new key pair must be generated, and the new public key must be added to GitHub or the server.

What should happen if a private key is exposed?

The exposed key should be removed immediately from GitHub, servers, and any other system where it was authorized. A new key pair should then be generated and installed.

Why does GitHub say authentication succeeded but shell access is not provided?

That message is normal. GitHub allows SSH authentication for Git operations, but it does not provide an interactive shell account.

Why is SSH asking for a password even after the key was added?

The SSH client may not be using the correct key, the public key may not be installed correctly, or the remote URL may still use HTTPS. Checking ssh-add -l, git remote -v, and verbose SSH output can help identify the problem.

Is it safe to store an SSH key without a passphrase?

For personal and administrative use, a passphrase is strongly recommended. Passphrase-free keys are sometimes used for automation, but they should be restricted, carefully stored, and limited to the minimum permissions required.