Environment: Ubuntu 24.04 LTS + DigitalOcean Droplet + GitHub + Frappe/ERPNext
Objective
Securely configure SSH authentication between your DigitalOcean droplet and GitHub so that you can clone, pull, and push private repositories without entering your GitHub username/password.
- Why use a separate SSH key?
- Architecture
- Generate SSH Key
- Verify Generated Keys
- Configure SSH Agent
- Add Public Key to GitHub
- Configure SSH Client
- Test GitHub Authentication
- Clone Private Repository
- Existing Repository Migration
- Using Multiple GitHub Accounts
- SSH Configuration Explained
- File Permissions
- Common Mistakes
- Troubleshooting
- Security Best Practices
- Revoking a Compromised Key
- Useful Commands
- Final Production Checklist
Although you can copy your laptop's SSH key to the DigitalOcean server, it is not recommended.
Laptop
│
├── id_ed25519
│
Copy Same Key
│
DigitalOcean
│
└── id_ed25519
If either machine is compromised, the attacker gains access to GitHub from both systems.
Each machine should have its own SSH key.
Laptop
│
└── github_ed25519
Desktop
│
└── github_ed25519
DigitalOcean
│
└── github_ed25519
GitHub
│
├── Laptop Key
├── Desktop Key
└── DigitalOcean Key
Benefits
- Independent revocation
- Better auditing
- Better security
- Industry standard
GitHub
+-----------------------+
| SSH Public Keys |
|-----------------------|
| Laptop |
| Desktop |
| DigitalOcean |
+-----------------------+
▲
│ SSH
│
+----------------------+
| DigitalOcean Droplet |
+----------------------+
~/.ssh/
github_ed25519
github_ed25519.pub
config
Connect to the droplet.
Run
mkdir -p ~/.ssh
chmod 700 ~/.sshGenerate a new ED25519 key.
ssh-keygen -t ed25519 -C "github" -f ~/.ssh/github_ed25519Explanation
| Option | Description |
|---|---|
| -t ed25519 | Recommended algorithm |
| -C | Comment |
| -f | File name |
When asked
Enter passphrase:
Production recommendation
Choose a passphrase.
If the server performs unattended deployment, you may leave it blank.
Generated files
~/.ssh/
github_ed25519
github_ed25519.pub
Private key
~/.ssh/github_ed25519
Public key
~/.ssh/github_ed25519.pub
Display the public key
cat ~/.ssh/github_ed25519.pubExample output
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBY.... github
Notice it begins with
ssh-ed25519
This is exactly what GitHub expects.
Never display or upload
cat ~/.ssh/github_ed25519It starts with
-----BEGIN OPENSSH PRIVATE KEY-----
Never upload this file.
Start agent
eval "$(ssh-agent -s)"Add key
ssh-add ~/.ssh/github_ed25519Verify
ssh-add -lExpected
256 SHA256:....
Display the public key
cat ~/.ssh/github_ed25519.pubCopy the entire line.
Open GitHub
Settings
↓
SSH and GPG Keys
↓
New SSH Key
Fill
Title
DigitalOcean - Avian Production
Key Type
Authentication Key
Key
Paste the output of
cat ~/.ssh/github_ed25519.pubClick
Add SSH Key
Create configuration
nano ~/.ssh/configAdd
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_ed25519
IdentitiesOnly yes
Save.
Permissions
chmod 600 ~/.ssh/configRun
ssh -T git@github.comFirst connection
The authenticity of host 'github.com' can't be established.
Type
yes
Expected
Hi <username>!
You've successfully authenticated...
Example
git clone git@github.com:username/private-repo.gitExample
git clone git@github.com:sanjay-kumar001/avian.gitIf already cloned using HTTPS
Check remote
git remote -vExample
https://github.com/user/project.git
Change to SSH
git remote set-url origin git@github.com:user/project.gitVerify
git remote -vShould become
git@github.com:user/project.git
Example
~/.ssh/
github_personal
github_work
github_client
SSH config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/github_personal
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/github_work
Clone
git@github-work:company/project.git
Host github.com
Alias.
HostName github.com
Real server.
User git
GitHub always uses
git
Never your GitHub username.
IdentityFile
Private key.
IdentitiesOnly yes
Forces SSH to use only this key.
Recommended.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/github_ed25519
chmod 644 ~/.ssh/github_ed25519.pub
chmod 600 ~/.ssh/config
Verify
ls -la ~/.sshExample
drwx------ .ssh
-rw------- github_ed25519
-rw-r--r-- github_ed25519.pub
-rw------- config
Wrong
-----BEGIN OPENSSH PRIVATE KEY-----
Correct
ssh-ed25519 AAAA....
ssh-add ~/.ssh/github_ed25519
chmod 600
Wrong
https://github.com/...
Correct
git@github.com:...
Always
git
Never
sanjay
Permission denied (publickey)
Check
ssh-add -lCheck
cat ~/.ssh/configVerbose debugging
ssh -vT git@github.comVery verbose
ssh -vvvT git@github.comCheck remote
git remote -v✔ One key per machine
✔ Never share private keys
✔ Backup private key securely
✔ Use ED25519
✔ Use descriptive filenames
✔ Revoke unused keys
✔ Use SSH instead of HTTPS
✔ Restrict permissions
✔ Regularly audit GitHub SSH keys
GitHub
Settings
↓
SSH and GPG Keys
↓
Delete
Delete only the compromised key.
Laptop continues working.
Generate
ssh-keygen -t ed25519 -C "github" -f ~/.ssh/github_ed25519View public key
cat ~/.ssh/github_ed25519.pubStart agent
eval "$(ssh-agent -s)"Add key
ssh-add ~/.ssh/github_ed25519List keys
ssh-add -lTest GitHub
ssh -T git@github.comVerbose test
ssh -vvvT git@github.comClone
git clone git@github.com:username/repository.gitCurrent remote
git remote -vSwitch HTTPS to SSH
git remote set-url origin git@github.com:user/repository.git- Ubuntu updated
.sshdirectory exists- ED25519 key generated
- Public key uploaded to GitHub
- Private key remains only on the droplet
- SSH agent running
- SSH config created
- Correct permissions applied
ssh -T git@github.comsucceeds- Repository uses SSH remote URL
- Clone, pull, and push operations verified
For a production DigitalOcean server hosting your Frappe/ERPNext applications:
- Generate a new ED25519 SSH key on the droplet.
- Use a descriptive filename such as
~/.ssh/github_ed25519. - Upload only the contents of
github_ed25519.pubto GitHub as an Authentication Key. - Configure
~/.ssh/configto use this key forgithub.com. - Verify with
ssh -T git@github.com. - Use SSH URLs (
git@github.com:owner/repo.git) for cloning and repository remotes. - Keep the droplet's SSH key separate from your laptop's key so access can be revoked independently if the server is ever compromised.