Build the mental model
A GitHub account is a more attractive target than most, because it often controls the source code, deployment pipelines, and secrets of everything a person or company has built. Losing control of it can mean a lot more than losing personal data.
Two-factor authentication matters more here than on an average account for exactly that reason: a stolen password alone should never be enough to push code, merge a pull request, or read a private repository. Enabling 2FA everywhere closes the single most common account-takeover path.
SSH keys replace password authentication with a cryptographic key pair: a private key that never leaves your machine, and a public key you register with GitHub. When you push or pull over SSH, GitHub verifies you hold the matching private key without a password ever crossing the network.
Personal access tokens serve a similar purpose for HTTPS-based Git operations and the API, replacing your password with a scoped, expiring credential. A good token grants only the specific permissions a task needs, expires automatically, and can be revoked instantly without touching your password or any other token.
Never share a private key or an unexpired token
Treat both exactly like a password: never commit them to a repository, paste them in chat, or send them by email. If one is ever exposed, revoke or regenerate it immediately — assume it is already compromised.
SSH KEY PAIR: LOCAL PRIVATE KEY, REMOTE PUBLIC KEY
--------------------------------------------------
YOUR COMPUTER GITHUB.COM
id_ed25519 (private key)
stays here, never shared
id_ed25519.pub
id_ed25519.pub ----- upload -------> (public key)
(safe to share) stored on your account
git push ---- SSH handshake proves you hold ----> accepted
the matching private keyConnect it to a real scenario
The command shown here, ssh-keygen -t ed25519 -C "you@example.com", was actually run in a throwaway directory to produce the real output below; the generated key pair was deleted immediately afterward and was never registered anywhere.
It generates a modern Ed25519 key pair, a private key file and a matching .pub public key file, and prints a fingerprint plus a randomart image derived from the key. Every real run produces a different fingerprint and randomart, since the key itself is freshly random each time — don't expect your own output to match this example exactly, only its shape.
Register the public key
Copy the .pub file's contents, paste it into Settings > SSH and GPG keys > New SSH key on GitHub's website; GitHub stores only the public half.
Create a personal access token
Settings > Developer settings, choose a token type, select an expiration date and the minimum scopes the task needs, then generate it.
Store it once
GitHub shows the token exactly once; treat it like a password and store it in a secret manager, not in a text file or a script.
Never share a private key or an unexpired token
Treat both exactly like a password: never commit them to a repository, paste them in chat, or send them by email. If one is ever exposed, revoke or regenerate it immediately — assume it is already compromised.
GitHub Account Security Checklist
Try the working example
# Run in a throwaway directory only, never your real ~/.ssh
mkdir -p /tmp/ssh-demo && cd /tmp/ssh-demo
ssh-keygen -t ed25519 -C "you@example.com" -f ./id_ed25519 -N ""
ls -la
cat id_ed25519.pub
# cleanup -- this demo key is never registered anywhere
rm -f id_ed25519 id_ed25519.pubssh-keygen printed:
Generating public/private ed25519 key pair.
Your identification has been saved in ./id_ed25519
Your public key has been saved in ./id_ed25519.pub
The key fingerprint is:
SHA256:1pxNKgx8T7W/2wwRxANs0iSaWsp2srYYIPyhR7GA1uM you@example.com
The key's randomart image is:
+--[ED25519 256]--+
| .++o. |
|. . . o.o+oo |
|.o + o = .oo .. |
|o o +. B = = . . |
|...E * S * . o |
| .+... = . o |
| . o. o o |
| . + . = |
| . . . o|
+----[SHA256]-----+
The .pub file's contents:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGuo8yCutlQdHAWl6oARWtZ+xYlJ2jxBhpXpgAE0Ekv0 you@example.com
The fingerprint, randomart, and key string above are real output from one actual run and will be different every time this command runs, since the key is freshly random. Everything past this point -- pasting the public key into GitHub, creating a token -- happens on GitHub's website and has no terminal output to capture.5-minute try-it
Generate a real SSH key pair in a throwaway directory with ssh-keygen -t ed25519 -C "your-email@example.com" -f ./test_key, inspect both files, then delete them. Separately, on your actual GitHub account, enable 2FA if it isn't already on, and create one personal access token scoped to only what a single task needs with a 7-day expiration, then revoke it once you're done.
One important caution
Pasting a private key or a raw token into a chat message, ticket, or committed file — even in a private repo — should be treated as an immediate compromise requiring revocation.
Creating a single token with broad, permanent access out of convenience instead of a short-lived, narrowly scoped one for each task defeats the entire point of tokens over passwords.
GitHub Docs - Managing your personal access tokens — Git & GitHub