At some point, most developers hit this wall:
You’re logged into a server, you run:
git clone git@github.com:your-org/your-repo.git
…and Git responds with:
Permission denied (publickey).
fatal: Could not read from remote repository.
You know the repo exists.
You know you have access.
So what gives?
This post walks through why this happens, and how to fix it cleanly and securely, without leaking credentials or cutting corners.
The Core Problem (In Plain English)
GitHub doesn’t care who you are.
It cares which SSH key you’re presenting.
When you run git clone from a server:
- GitHub sees an SSH key
- It checks whether that key is authorized
- If it doesn’t recognize it → access denied
That’s it. No magic.
Step 1: Understand What Machine You’re On
There are three identities involved:
- Your laptop (already authenticated with GitHub)
- Your server (a completely different machine)
-
A Linux user on that server (e.g.
app,bot, ordeploy)
Even if:
- the repo is yours
- your laptop has access
- you’re “the same person”
👉 The server has its own identity.
You must explicitly grant it access.
Step 2: Generate an SSH Key on the Server
Log into the server as the user that will run the project:
ssh app@your-server-ip
Then generate a new SSH key:
ssh-keygen -t ed25519 -C "app-server-repo-access"
When prompted:
- Press Enter to accept the default location
- Leave the passphrase empty (recommended for non-interactive servers)
This creates:
~/.ssh/id_ed25519 (private key)
~/.ssh/id_ed25519.pub (public key)
Step 3: Copy the Public Key
Display the public key:
cat ~/.ssh/id_ed25519.pub
You’ll see a single line starting with:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
Copy the entire line.
Step 4: Add the Key to GitHub (Deploy Key Method)
This is the recommended approach for servers.
In GitHub:
- Open the repository
- Go to Settings
- Click Deploy keys
- Click Add deploy key
- Give it a name (e.g.
app-server) - Paste the public key
- Enable write access only if the server needs to push
- Save
This key now:
- works only for this repo
- cannot access anything else
- is safe to revoke anytime
Step 5: Test SSH Connectivity
Back on the server:
ssh -T git@github.com
If successful, you’ll see something like:
Hi! You've successfully authenticated, but GitHub does not provide shell access.
That’s a good thing.
Step 6: Clone the Repository
Now retry:
git clone git@github.com:your-org/your-repo.git
This time, it should work without errors.
Common Pitfall: “But I Can Clone From My Laptop”
That’s expected.
Your laptop:
- has its own SSH key
- already registered with GitHub
Your server:
- is a different machine
- needs its own key
SSH access is machine-based, not user-based.
Alternative: HTTPS (When It Makes Sense)
If the repo is public, you can always do:
git clone https://github.com/your-org/your-repo.git
For private repos, HTTPS requires:
- a GitHub token
- storing credentials on the server
For long-running services, SSH deploy keys are cleaner and safer.
Why This Setup Is Best Practice
Using deploy keys means:
- no shared credentials
- no copying laptop keys to servers
- repo-scoped access
- easy rotation and revocation
This is how CI systems, deployment bots, and production servers are meant to work.
Final Takeaway
If git clone fails on a server, it’s almost never a Git issue.
It’s an identity issue.
Once you understand that:
Servers authenticate themselves to GitHub using SSH keys,
the fix becomes straightforward, secure, and repeatable.
Happy deploying 🚀
Top comments (0)