Learning objectives
After reading this article you will be able to:
- Understand how a public and private key pair authenticates you
- Generate an Ed25519 key with a passphrase on Linux, macOS or Windows
- Add the key to GitHub, test the connection and avoid leaks
On this page
SSH (Secure Shell) is the protocol you use to log in to servers and to run git push without typing a username and password every time. Instead of a password, it can authenticate you with a pair of cryptographic keys.
This model is safer than a password for a simple reason: the secret never travels over the network.
How does an SSH key work?#
You generate two mathematically linked files:
- Private key (for example
id_ed25519): stays only on your machine. It is the secret. - Public key (
id_ed25519.pub): can be copied anywhere. It lives on the server or in your GitHub account.
When you connect, the server sends a challenge. Your SSH client signs the challenge with the private key, and the server checks the signature with the public key. If it matches, you are in. The private key itself is never sent.
Someone who holds only the public key cannot pretend to be you. Someone who holds the private key can, so treat it with the same care as a bank password.
How do you generate an SSH key?#
The command is the same on Linux, macOS and Windows (PowerShell or Git Bash):
ssh-keygen -t ed25519 -C "you@example.com"-t ed25519picks the key type.-Cadds a comment (use the email of your GitHub account).
The program asks where to save the key: press Enter to accept the default (~/.ssh/id_ed25519). Then it asks for a passphrase. Set one. It encrypts the private key file: if someone copies the file, they still need the phrase.
At the end there are two files in ~/.ssh/: id_ed25519 (private) and id_ed25519.pub (public).
Which key type should you use?#
In most cases, Ed25519. It is the type GitHub's documentation uses by default in its examples.
If the system or an older server does not accept Ed25519, use RSA with 4096 bits:
ssh-keygen -t rsa -b 4096 -C "you@example.com"How do you use ssh-agent to avoid typing the passphrase every time?#
ssh-agent keeps the unlocked key in memory for the session.
On Linux and macOS:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519On macOS, to store the passphrase in the Keychain, run ssh-add --apple-use-keychain ~/.ssh/id_ed25519 and create the file ~/.ssh/config with:
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519On Windows, open PowerShell as administrator and enable the service:
Get-Service -Name ssh-agent | Set-Service -StartupType Manual
Start-Service ssh-agentThen, in a terminal without administrator rights:
ssh-add c:/Users/YOU/.ssh/id_ed25519How do you add the public key to GitHub?#
- Copy the contents of the
.pubfile, with no extra spaces or line breaks:- macOS:
pbcopy < ~/.ssh/id_ed25519.pub - Windows (PowerShell):
cat ~/.ssh/id_ed25519.pub | clip - Linux:
cat ~/.ssh/id_ed25519.puband copy the output.
- macOS:
- On GitHub, click your profile picture, then Settings.
- In the sidebar, under Access, open SSH and GPG keys.
- Click New SSH key, give it a title (for example "personal laptop"), choose the Authentication type and paste the key.
- Click Add SSH key. GitHub may ask you to confirm your identity.
On your own servers, the equivalent step is to append the public key line to the ~/.ssh/authorized_keys file of the user on the server.
How do you test that it worked?#
ssh -T git@github.comOn the first connection, SSH shows a fingerprint and asks Are you sure you want to continue connecting (yes/no)?. Compare the fingerprint with GitHub's official fingerprints page before typing yes. If everything is right, the reply is:
Hi YOU! You've successfully authenticated, but GitHub does not provide shell access.The message mentions "no shell access" because GitHub only accepts Git commands. The command exits with code 1, and that is expected.
To clone over SSH, use a URL in the form git@github.com:user/repository.git.
What are the most common errors?#
Permission denied (publickey): the server did not recognize any key. Check that the public key is added to the right account, that the private key was added to the agent (ssh-add -l lists loaded keys) and that the remote URL uses git@github.com:, not https://.
Windows does not use the key loaded in the agent: Git may be using a different SSH binary, not the system one. Force Git to use the Windows client, where the agent holds the key:
git config --global core.sshCommand "C:/Windows/System32/OpenSSH/ssh.exe"Bad configuration option: usekeychain on macOS: add IgnoreUnknown UseKeychain to the same Host block in ~/.ssh/config.
How do you protect your private key?#
- Never push the private key to a repository, chat or ticket. If that happens, treat it as leaked: remove the matching public key from GitHub and generate a new pair. The guide on an API key exposed on GitHub follows the same revocation logic.
- Use a passphrase and one key per machine. That way, losing a laptop invalidates only one key.
- Give each key a clear title on GitHub and delete the ones you no longer use.
- For automation such as deploying with GitHub Actions, prefer credentials stored as secrets, never your personal key.
- Go through the security checklist for shipping a bot, site or API.
How to do this on Square Cloud#
On Square Cloud you do not need an SSH key to deploy. The deploy options are a ZIP upload in the dashboard, the CLI, GitHub (a push deploys, through the official GitHub Action or a webhook) and the VS Code extension. The CLI logs in by approving a code in the browser or, in CI, reads the key from the SQUARECLOUD_API_KEY variable.
Outbound connections on port 22 are not allowed, so the application cannot open SSH to another server or clone a repository over git@. To reach a private repository, use HTTPS with a token. Keep that token, and any other secret, in the application's environment variables (set in the dashboard, API, CLI or VS Code), never in the code or the ZIP. A change applies on the next restart, with no rebuild.
See how to set them up in environment variables on Square Cloud.
Infrastructure
L3/L4/L7 DDoS mitigation and a WAF on every plan
FAQs
What is the difference between a public key and a private key?
The public key can be shared and lives on the server or on GitHub. The private key never leaves your machine: it proves you own the public one.
Ed25519 or RSA: which should I pick?
Ed25519 is the type GitHub's documentation uses by default in its examples. Use 4096-bit RSA only if the system does not accept Ed25519.
Do I need a passphrase on my key?
It is recommended. It protects the private key file if someone copies it off your computer, and ssh-agent remembers it so you do not type it on every use.
I lost my private key. What now?
There is no way to recover it. Generate a new pair, add the new public key and remove the old one from GitHub or the server.
More in Security
See all 10 articles- My app was hacked: what to do nowIf your app was hacked, contain access, rotate every secret and preserve the logs before cleaning up. See the right order, how to find the cause and how to recover.
- Security checklist for deploying a bot, site or APIA security checklist before you deploy a bot, site or API: secrets in environment variables, dependencies, HTTPS, headers, least privilege and logs.
- How to protect your app from DDoS attacksTo protect against DDoS, combine edge mitigation (CDN and WAF) with rate limiting, timeouts and caching in your app. Step-by-step guide with working code.
- API key exposed on GitHub: how to revoke and prevent itPushed an API key to GitHub? Revoke it first, then clean the history and rotate the value. Here are the steps and how to stop it from happening again.