Deploy a GitHub Project Without a Password Using a Per-Repository Deploy Key

Deploying a GitHub project to a server should be secure, repeatable, and easy to manage.

A common mistake is using a personal GitHub password or a personal SSH key directly on the server. That works, but it is not ideal because the server may get access to more repositories than it needs.

A better approach is to use a per-repository deploy key.

In this tutorial, you will learn how to deploy a GitHub repository without using a password by creating a dedicated SSH deploy key for a single repository.

What Is a Deploy Key?

A deploy key is an SSH key that is attached to one GitHub repository.

It allows a server to access that repository over SSH.

Deploy keys are useful because:

  • They avoid password-based authentication
  • They can be limited to one repository
  • They are safer than using your personal SSH key
  • They work well for production servers
  • They can be read-only or read-write

For deployment, read-only access is usually enough.

What We Are Going to Do

We will:

  1. Create a new SSH key on the server
  2. Add the public key to a GitHub repository as a deploy key
  3. Configure SSH to use that key only for that repository
  4. Test the GitHub SSH connection
  5. Clone the repository without entering a password

Prerequisites

Before starting, make sure you have:

  • A Linux server or local machine with SSH access
  • Git installed
  • Access to the GitHub repository settings
  • Permission to add deploy keys to the repository

You can check if Git is installed by running:

git --version

If Git is not installed, install it using your system package manager.

For Ubuntu or Debian:

sudo apt update
sudo apt install git -y

Step 1: Create the SSH Directory

SSH keys are usually stored inside the ~/.ssh directory.

Create the directory if it does not already exist:

mkdir -p ~/.ssh
chmod 700 ~/.ssh

The chmod 700 command makes sure only your current user can access the SSH directory.

This is important because SSH refuses to use keys if permissions are too open.

Step 2: Generate a New SSH Deploy Key

Now generate a new SSH key.

Use a clear file name that describes the project, but avoid using sensitive or private names in shared documentation.

Example:

ssh-keygen -t ed25519 \
  -f ~/.ssh/project_deploy_key \
  -C "project deploy key"

Let us break this command down:

  • ssh-keygen creates a new SSH key
  • -t ed25519 uses the Ed25519 key type, which is modern and secure
  • -f ~/.ssh/project_deploy_key sets the file name for the private key
  • -C "project deploy key" adds a label so the key is easier to identify later

When prompted for a passphrase, you can press Enter to leave it empty if this key will be used by an automated deployment process.

For interactive use, adding a passphrase is more secure.

After the command finishes, you should have two files:

~/.ssh/project_deploy_key
~/.ssh/project_deploy_key.pub

The private key is:

~/.ssh/project_deploy_key

The public key is:

~/.ssh/project_deploy_key.pub

Never share the private key.

Step 3: Display the Public Key

Next, print the public key:

cat ~/.ssh/project_deploy_key.pub

Copy the full output.

It will look similar to this:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExamplePublicKeyValue project deploy key

You will paste this public key into GitHub.

Step 4: Add the Public Key to GitHub as a Deploy Key

Open your repository on GitHub.

Then go to:

Repository → Settings → Deploy keys → Add deploy key

Add a title such as:

Production Server Deploy Key

Paste the public key into the key field.

You will also see an option called Allow write access.

For most deployments, leave this unchecked.

Use read-only access when the server only needs to clone or pull code.

Enable write access only when the server must push changes back to the repository.

Step 5: Configure SSH to Use This Deploy Key

Now configure SSH so it knows which key to use for this repository.

Open or append to your SSH config file:

cat >> ~/.ssh/config <<'EOF'

Host github-project
  HostName github.com
  User git
  IdentityFile ~/.ssh/project_deploy_key
  IdentitiesOnly yes
EOF

This creates a custom SSH host called:

github-project

Let us understand each line:

Host github-project

This is an alias. Instead of connecting directly to github.com, you will use github-project.

HostName github.com

This tells SSH that the real server is GitHub.

User git

GitHub SSH connections always use the git user.

IdentityFile ~/.ssh/project_deploy_key

This tells SSH to use your deploy key.

IdentitiesOnly yes

This forces SSH to use only the key listed in IdentityFile.

This is useful when your machine has many SSH keys.

Step 6: Fix SSH File Permissions

SSH is strict about file permissions.

Run:

chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/project_deploy_key
chmod 644 ~/.ssh/project_deploy_key.pub

These permissions mean:

  • 600 for private files: only the current user can read and write
  • 644 for the public key: others can read it, but only the owner can edit it

Step 7: Test the GitHub SSH Connection

Test the connection using your SSH alias:

ssh -T git@github-project

If everything is configured correctly, GitHub should respond with a message similar to:

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

This message is good.

It means SSH authentication worked.

GitHub does not provide shell access, so that part is expected.

Step 8: Clone the Repository Without a Password

Now clone the repository using the custom SSH host.

The usual GitHub SSH clone URL looks like this:

git@github.com:owner/repository.git

Replace github.com with your SSH alias:

git clone git@github-project:owner/repository.git

Example format:

git clone git@github-project:your-org/your-repository.git

Because SSH is configured to use the deploy key, Git should clone the repository without asking for a GitHub password.

Step 9: Pull Updates During Deployment

After the repository has been cloned, future deployments can pull the latest code:

cd your-repository
git pull origin main

If your default branch is named master, use:

git pull origin master

You can check your current branch with:

git branch

Example Complete Command Flow

Here is the complete flow using generic names:

mkdir -p ~/.ssh
chmod 700 ~/.ssh

ssh-keygen -t ed25519 \
  -f ~/.ssh/project_deploy_key \
  -C "project deploy key"

cat ~/.ssh/project_deploy_key.pub

After copying the public key into GitHub as a deploy key, configure SSH:

cat >> ~/.ssh/config <<'EOF'

Host github-project
  HostName github.com
  User git
  IdentityFile ~/.ssh/project_deploy_key
  IdentitiesOnly yes
EOF

chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/project_deploy_key
chmod 644 ~/.ssh/project_deploy_key.pub

Test the connection:

ssh -T git@github-project

Clone the repository:

git clone git@github-project:owner/repository.git

Why Use a Custom SSH Host Alias?

The custom host alias is the key part of this setup.

Instead of using:

git@github.com:owner/repository.git

You use:

git@github-project:owner/repository.git

This lets SSH match the Host github-project block in your config file.

That block tells SSH exactly which private key to use.

This is very helpful when one server deploys multiple GitHub repositories.

For example:

Host github-project-a
  HostName github.com
  User git
  IdentityFile ~/.ssh/project_a_deploy_key
  IdentitiesOnly yes

Host github-project-b
  HostName github.com
  User git
  IdentityFile ~/.ssh/project_b_deploy_key
  IdentitiesOnly yes

Then you can clone each repository with its own key:

git clone git@github-project-a:owner/project-a.git
git clone git@github-project-b:owner/project-b.git

This keeps access separated and easier to manage.

Common Problems and Fixes

Permission Denied Public Key

Error:

Permission denied (publickey).

Possible causes:

  • The public key was not added to GitHub
  • The wrong private key is being used
  • The SSH config alias is incorrect
  • File permissions are too open
  • The repository path is wrong

Try testing with verbose SSH output:

ssh -vT git@github-project

This shows which key SSH is trying to use.

Repository Not Found

Error:

Repository not found.

Possible causes:

  • The deploy key was added to a different repository
  • The repository owner or name is incorrect
  • The repository is private and the deploy key does not have access
  • You are using the wrong SSH alias

Check the clone URL carefully:

git clone git@github-project:owner/repository.git

Bad Permissions

Error:

Bad permissions

Fix the permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/project_deploy_key
chmod 644 ~/.ssh/project_deploy_key.pub

Git Still Uses the Wrong Key

If your machine has many SSH keys, make sure this line exists:

IdentitiesOnly yes

This tells SSH not to try every available key.

Key Considerations

  • Use one deploy key per repository
  • Do not reuse your personal SSH key for deployments
  • Keep the private key secret
  • Use read-only deploy keys unless write access is required
  • Use clear SSH host aliases for each project
  • Keep file permissions strict
  • Remove old deploy keys when a server is retired
  • Avoid putting real repository names, usernames, or private paths in public documentation

Recommendations

For a secure deployment setup:

  1. Create a dedicated SSH key for each repository.
  2. Add only the public key to GitHub.
  3. Store the private key only on the server that needs deployment access.
  4. Use an SSH config alias to control which key is used.
  5. Keep deploy keys read-only unless pushing from the server is required.
  6. Regularly review deploy keys in GitHub repository settings.
  7. Remove deploy keys that are no longer used.

Conclusion

Using a per-repository deploy key is a simple and secure way to deploy a GitHub project without using a password.

Instead of giving your server broad access through a personal account, you give it limited access to one repository.

The main steps are:

  • Generate an SSH key
  • Add the public key as a GitHub deploy key
  • Configure SSH with a custom host alias
  • Clone the repository using that alias

This setup is clean, secure, and works well for production deployments.