Home / Alt manpages / gh-repo-deploy-key-add(1)

  • gh-repo-deploy-key-add(1)
  • User command
  • linux

Add a GitHub Deploy Key with gh, Then Verify and Revoke It

You will create a dedicated Ed25519 SSH key, add its public half to one GitHub repository with gh repo deploy-key add, check that GitHub recorded the intended access mode, and have the command needed to remove it later. The examples use GitHub CLI 2.87.3, installed on the machine used for this guide.

Allow about 10 minutes. You need an authenticated gh session with permission to administer the target repository, OpenSSH's ssh-keygen, and the repository name in OWNER/REPO form. No elevated privileges are required. Keep the private key on the machine that will use it, and never paste it into the command or upload it to GitHub.

1. Choose the repository and key location

Replace the two obvious placeholders below before running the commands. A deploy key belongs to one repository, so use a separate key for each repository that needs machine access. A descriptive filename makes it harder to select the wrong key later.

REPO="example-owner/example-repo"
KEY="$HOME/.ssh/example-repo-deploy"
gh auth status
printf '%s\n' "$REPO" "$KEY"

The first command reports the accounts and hosts known to GitHub CLI. The final command only prints your choices. Stop here if the authenticated account, repository, or key path is not what you expect.

Checkpoint: the target is correct

  • REPO names the intended repository, such as acme/widget.
  • KEY does not point at an existing private key you still need.
  • The authenticated GitHub account can manage deploy keys on that repository.

2. Generate a dedicated public and private key

This changes local state by creating two files. The private key has no passphrase in this unattended example, which is convenient for a service but increases the importance of filesystem permissions and host security. If a person will use the key interactively, omit -N "" and enter a passphrase when prompted.

ssh-keygen -t ed25519 -C "example-repo deploy key" -N "" -f "$KEY"
chmod 600 "$KEY"
ls -l "$KEY" "$KEY.pub"

Accept no overwrite prompt unless you have deliberately checked the existing file. Expected output includes a new private key at the value of KEY and a public key at the same path with .pub appended. The public file is the one that will be sent to GitHub.

If you chose the wrong path, remove only the newly created pair after checking it carefully: rm -- "$KEY" "$KEY.pub". Do not use a wildcard in that recovery command.

3. Add the public key as read-only

Read-only is the safer default for checkout, deployment or monitoring. The command accepts the public key file as its positional argument. Pass --repo explicitly so it cannot accidentally use a different repository inferred from the current directory.

gh repo deploy-key add "$KEY.pub" \
  --repo "$REPO" \
  --title "example-repo deployment"

On success, GitHub CLI returns a success message and the key becomes available to that repository. The installed command also accepts the short forms -R for --repo and -t for --title. There is no confirmation prompt in the documented usage, so review the repository and public key path before pressing Enter.

4. Verify the title, key and access mode

List the repository's deploy keys and request fields that make the result unambiguous. The list command supports JSON output and the fields below.

gh repo deploy-key list \
  --repo "$REPO" \
  --json id,title,key,readOnly

Find the entry titled example-repo deployment. Its readOnly value should be true, and its key value should begin with the same Ed25519 public-key material shown by this command:

cut -d ' ' -f 1-2 -- "$KEY.pub"

Do not treat a matching title alone as proof that the right key was installed. Titles are labels and can be reused. If the entry is missing, inspect the command's error, check authentication and repository spelling, then run the list command again.

5. Grant write access only when required

A read-only deploy key cannot push. If the service genuinely needs to push to this repository, add a separate key with write permission rather than broadening an existing key without review.

gh repo deploy-key add "$KEY.pub" \
  --repo "$REPO" \
  --title "example-repo deployment writer" \
  --allow-write

--allow-write is a security-sensitive change: anyone who obtains the private key may be able to alter the repository. Protect the host, restrict the private key to the service account, and prefer read-only access whenever the job only downloads code. Verify this second entry with the same list command and expect readOnly to be false.

6. Remove a key when the machine or job is retired

Deleting a deploy key is the recovery path for a lost host, a replaced job or an incorrect entry. Use the numeric id returned by the list command, not a title guessed from memory.

gh repo deploy-key delete KEY_ID --repo "$REPO"
gh repo deploy-key list --repo "$REPO" --json id,title,key,readOnly

Confirm that the deleted ID no longer appears. Then remove the local private and public files only if this machine no longer needs them: rm -- "$KEY" "$KEY.pub". The GitHub CLI manual warns that keys added by it are associated with the current authentication token; de-authorising that token or the GitHub CLI application also removes keys added through it. Plan for that dependency when designing an unattended deployment.

Done means

  • The intended repository and authenticated account were checked before the change.
  • The private key remains local, protected with mode 600, and the public key was the only file passed to gh.
  • The list output shows the expected title, key material and readOnly value.
  • Any write-enabled key has a documented need and a plan for rotation.
  • You recorded the deploy-key ID so it can be deleted without guessing.