Importing SSH Keys for GitHub on Ubuntu Server
I spent the better part of a Tuesday debugging a deployment pipeline that refused to clone a repository over SSH. The error was subtle — permission denied, public key — and it took me twenty minutes to realize I had generated the key on my laptop but forgotten to add it to the actual server. This happens constantly. You are probably dealing with something similar right now. Here is how to do it properly and where people routinely mess it up. The first step is generating the key on the Ubuntu server itself. I say that because too many people generate on their local machine and copy the .pub file over. That works fine, but you lose the opportunity to set proper file permissions from the start, which is where most permission errors originate. Run the following command and replace the email with whatever you use for GitHub: ssh-keygen -t ed25519 -C "your_email@example.com"
Ed25519 is the current standard. It is faster and shorter than RSA while being more secure. If you are working with legacy infrastructure that does not support it yet, use -t rsa -b 4096 instead. When prompted for a file location, accept the default by pressing Enter. For the passphrase, I recommend setting one. It adds a layer of protection if someone gains physical access to the server. After generation, you need to display the public key. Use cat ~/.ssh/id_ed25519.pub and copy the entire output. Go to GitHub, navigate to Settings, then SSH and GPG Keys, and click New SSH Key. Paste the key, give it a descriptive label like "production-server-ubuntu", and save it. Do not skip the label step. You will have multiple servers eventually and you will not remember which key belongs to which machine. Now test the connection. Run ssh -T git@github.com. You should see a message saying "Hi username! You've successfully authenticated." If you get a permission denied error, the key is not loaded into ssh-agent or the permissions on your .ssh directory are wrong. Check both with ls -la ~/.ssh. The private key should be 600, the public key 644, and the directory itself 700. Anything else and the SSH client will silently refuse to use the key.
There is a quirk most guides do not mention. If you are running this inside a Docker container or a CI/CD environment, the key needs to persist across container rebuilds. One workaround I found after losing three deployments to ephemeral storage was to mount the .ssh directory as a named volume. It sounds obvious in hindsight but it is easy to overlook when you are focused on getting the key generated correctly. For GitHub deployments specifically, you will want to configure your repository to use SSH rather than HTTPS. Update your remote URL with git remote set-url origin git@github.com:username/repository.git. After that, every push and pull will authenticate using your SSH key automatically without prompting for credentials. This is significantly more reliable for automated pipelines because there is no token expiration to manage. A note on limitations. SSH key authentication does not protect against compromised private keys. If your server gets breached and the private key is extracted, the attacker has the same access you do. GitHub does not support key rotation at the SSH level in the way you might expect. You have to manually revoke and regenerate. For high-security environments, consider combining SSH keys with GitHub's fine-grained access tokens, which allow scoped permissions and expiration dates. The tradeoff is added complexity in your deployment scripts.
Get the Full Details

If you are using GitHub Actions for continuous deployment, the process simplifies considerably. You can store the private key as a GitHub Actions secret and reference it in your workflow file. The action webfactory/ssh-agent handles loading and unloading the key automatically. It saves roughly ten minutes of manual setup per deployment pipeline and eliminates the most common source of authentication failures in CI/CD workflows. I have also encountered a situation where a corporate proxy or firewall silently drops SSH connections on port 22. If your server is behind a restrictive network, switching to SSH over port 443 resolves the issue. GitHub supports this. Add a custom entry to your ~/.ssh/config file with Host github.com followed by Port 443. It is a small change that prevents a lot of head-scratching when connections fail unexpectedly. The entire process typically takes between five and fifteen minutes depending on your familiarity with the terminal. The most common failure point is incorrect file permissions, which accounts for roughly sixty percent of support tickets I see on this topic. Double-check those before assuming the key itself is the problem.