How to Manage Production Website Code with GitHub Using SSH Deploy Keys (Secure Step-by-Step Guide)

Hosting a website on your own server means you need a safe, repeatable way to get code onto it. Copying files by hand with FTP is slow and error-prone, and using passwords for Git is risky. A better approach is to keep your code in a private GitHub repository and let the server pull it using SSH key-based authentication.

In this guide you will learn how to create a dedicated SSH key for your server, add it to GitHub as a deploy key, clone your website code, and update the live site safely. I also cover the security practices every production server should follow.

What you will learn

  • Why SSH deploy keys are better than passwords
  • How to generate and secure a dedicated SSH key
  • How to add a deploy key to a private repository
  • How to clone and update your website code on the server
  • How to roll back a bad deployment
  • Security best practices for production environments

Prerequisites

  • A Linux server (for example Ubuntu) with SSH access
  • A web server such as Apache or Nginx
  • Git installed on the server (check with git --version)
  • A private GitHub repository containing your website code

What Is a Deploy Key?

A deploy key is an SSH public key that you attach to a single repository instead of your personal GitHub account. It is the safest choice for servers because:

  • It gives access to only one repository, not everything in your account
  • It is read-only by default, so a hacked server cannot change your code
  • It keeps working even if team members leave your organization

Note: GitHub does not allow the same deploy key on more than one repository. If you manage several sites, create one key per repository.

Step 1: Generate a Dedicated SSH Key

Log in to your server and create a new key:

ssh-keygen -t ed25519 -C "production-server" -f ~/.ssh/github_key

You will be asked for a passphrase. On an unattended server, many admins leave it empty so that deployments can run without manual input. If you do that, the file permissions in the next step become extremely important.

Two files are created:

  • ~/.ssh/github_key (private key)
  • ~/.ssh/github_key.pub (public key)

Step 2: Secure the Key Permissions

chmod 700 ~/.ssh
chmod 600 ~/.ssh/github_key
chmod 644 ~/.ssh/github_key.pub

SSH refuses to use a private key that other users can read, so this step is required, not optional.

Step 3: View the Public Key

cat ~/.ssh/github_key.pub

Copy the entire output. Only copy the .pub file, never the private key.

Step 4: Add the Deploy Key to GitHub

  1. Open your private repository on GitHub.
  2. Go to Settings → Deploy keys → Add deploy key.
  3. Enter a title such as "Production Server".
  4. Paste the public key.
  5. Leave Allow write access unchecked unless the server must push code. For most websites, read-only is the correct and safer choice.
  6. Click Add key.

Step 5: Tell SSH Which Key to Use

Because the key has a custom name, SSH will not find it automatically. Create a config file:

nano ~/.ssh/config

Add this:

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_key
    IdentitiesOnly yes

Then secure the file:

chmod 600 ~/.ssh/config

This is more reliable than using ssh-agent on a server, because the setting survives logouts and reboots.

Step 6: Test the Connection

ssh -T git@github.com

The first time, SSH asks whether you trust the host. Type yes. A successful result looks like this:

Hi username/private-repository! You've successfully authenticated, but GitHub does not provide shell access.

Seeing your repository name in the message confirms that the deploy key is working.

Step 7: Clone the Repository

cd /var/www/html
git clone git@github.com:username/private-repository.git projectcode

Your website code is now in:

/var/www/html/projectcode

Tip: If you get a "Permission denied" error when writing to /var/www/html, either run the command with sudo and then fix ownership, or clone into a folder you own and point your web server to it.

To give your web server user access to the files:

sudo chown -R www-data:www-data /var/www/html/projectcode

Use nginx or apache instead of www-data if that is the user your system runs.

Step 8: Deploy Updates Safely

The safest production workflow is simple: write and test code on your own computer, push it to GitHub, then pull it on the server. The server only downloads code. It never becomes the place where you edit files.

On your development machine:

git add .
git commit -m "Website update"
git push origin main

On the production server:

cd /var/www/html/projectcode
git pull origin main

Check what changed:

git log --oneline -5
git status

If Git complains about "dubious ownership" after you change file owners, run:

git config --global --add safe.directory /var/www/html/projectcode

Step 9: Roll Back a Bad Deployment

If a deployment breaks your site, go back to the last working version quickly.

Find the last good commit:

git log --oneline

Return to it:

git checkout <commit-id>

When the problem is fixed and a corrected commit is on GitHub, return to the latest code:

git checkout main
git pull origin main

Being able to roll back in seconds is one of the biggest benefits of using Git for deployment.

Recommended Production Workflow

The best practice is to move code through stages instead of editing the live server directly:

Developer → Private GitHub Repository → Staging Server (testing) → Production Server

This way, every change is tested before real visitors see it.

Protect Sensitive Information

Never commit any of the following to your repository:

  • Passwords
  • API keys
  • Database credentials
  • SSL certificates and private keys
  • Private SSH keys
  • Secrets stored in .env files

Create a .gitignore file in the root of your project to block them:

.env
*.pem
*.key
id_rsa
id_ed25519

Important: .gitignore only protects files that are not yet tracked. If a secret was already committed, adding it to .gitignore is not enough. Change the secret immediately, because it remains in your Git history.

Security Best Practices

  • Use a private repository. Only authorized people should have access.
  • Use SSH authentication. Avoid passwords and personal access tokens on servers.
  • Use a dedicated deploy key. Do not use your personal GitHub key on a production server.
  • Keep access read-only. Enable write access only when truly required.
  • Follow least privilege. Give repository access only to people who need it.
  • Keep regular backups. Back up your files and database before major deployments.
  • Write clear commit messages. They make audits and rollbacks much easier.
  • Rotate keys when needed. Remove old deploy keys from GitHub if a server is retired or compromised.
  • Keep the server updated. Apply security patches and disable password login for SSH.

Troubleshooting Common Problems

1. Permission denied (publickey)

  • Confirm the public key was added under the repository's Deploy keys.
  • Check that the IdentityFile path in ~/.ssh/config is correct.
  • Run ssh -vT git@github.com and look at which key files SSH tries.

2. "WARNING: UNPROTECTED PRIVATE KEY FILE!"

Fix the permissions from Step 2.

3. "Repository not found"

Check the username and repository name. Also remember that a deploy key only works for the one repository it was added to.

4. "Key is already in use"

GitHub does not allow the same public key on more than one repository or account. Generate a new key for the new repository.

5. "remote: Write access to repository not granted"

Your deploy key is read-only. Either push from your development machine instead, or enable write access for the key if you really need it.

Quick Summary

  •  Generated a dedicated SSH key for the server
  •  Secured the key file permissions
  •  Added the public key as a deploy key on a private repository
  •  Configured SSH to use the key automatically
  •  Cloned the website code to the server
  •  Deployed updates with git pull and learned how to roll back

Conclusion

Managing your website code with a private GitHub repository and SSH deploy keys is secure, simple, and widely used in professional environments. Combined with read-only access, protected secrets, regular backups, and a test-before-production workflow, it gives you fast deployments and a clear history of every change. If this guide helped you, share it with a fellow developer or site owner, and leave a comment below if you get stuck on any step.

Note: All usernames, repository names, and paths in this tutorial are examples. Replace them with your own details.

Previous Post
No Comment
Add Comment
comment url