GitHub SSH on a VPS (Reliable Deploy Access)
How to set up a stable SSH-based Git connection on a VPS for pull-based deployments.
Category: On-Premises & Private Cloud
The first time I tried git pull on the VPS to ship an update, GitHub slammed the door:
Invalid username or token. Password authentication is not supported
Pasting a personal access token onto the server worked once but felt wrong — tokens expire, end up in shell history, and bind the deploy to a single human account. An SSH Deploy Key fixes all three in one move.
This is the setup I settled on for every pull-based deploy since.
Create a dedicated SSH key on the VPS
A key that lives only on this VPS, labelled so I can identify it in the GitHub UI later:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "vps-website" -f ~/.ssh/id_ed25519 -N ""
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
cat ~/.ssh/id_ed25519.pub
Ed25519 over RSA because it’s shorter, faster, and GitHub has supported it for years now. Copy the printed public key for the next step.
Add the key as a Deploy Key
In the repository on GitHub:
SettingsDeploy keysAdd deploy key
I keep it read-only unless the VPS actually needs to push — which for pull-based deploys it never does. A read-only deploy key is strictly less dangerous than a PAT: it’s scoped to a single repository, can’t be used to escalate elsewhere, and doesn’t expire.
Trust GitHub host keys
Pre-seeding known_hosts avoids the interactive “Are you sure?” prompt during the first git clone in a non-interactive deploy script:
ssh-keyscan github.com >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
Test SSH access
ssh -T git@github.com
A friendly “Hi <repo>! You’ve successfully authenticated…” message means the key is live. If it fails here, fix it before touching the repo remote.
Switch the repository remote from HTTPS to SSH
cd /opt/website
git remote set-url origin git@github.com:adrian-altner/website.git
git remote -v
git fetch
git pull
From this point on, deploys don’t involve any interactive authentication at all.
Optional: explicit SSH config
For multi-key hosts or anywhere I want strict “use only this key for this host” behaviour:
# ~/.ssh/config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
chmod 600 ~/.ssh/config
IdentitiesOnly yes is the important one — it stops ssh from offering every key the agent knows about before trying the right one, which is what usually causes “too many authentication failures” errors on machines with more than a couple of keys.
Quick troubleshooting
Permission denied (publickey)— the key isn’t attached to the right repo, or to the right account. Double-check under the repository’s Deploy keys, not your personal SSH keys.Repository not found— usually a typo in the remote URL, or the deploy key is attached to a different repo than you think.Host key verification failed—known_hostsis missing the GitHub entry. Re-runssh-keyscan github.com >> ~/.ssh/known_hosts.
What to take away
- Deploy Keys are scoped, non-expiring, and read-only by default — a better fit for servers than PATs.
- Ed25519 keys are the sensible default in 2026; RSA buys you nothing here.
- Pre-seed
known_hostsso non-interactive deploys don’t prompt. IdentitiesOnly yessaves hours of debugging on hosts with multiple SSH identities.- Deployments should depend on machine identity, not a password a human types.