Skip to main content

Deploy Keys

Deploy keys are SSH keys scoped to a single repository. They grant either read-only or read-write access without requiring a personal user account or API token. This makes them ideal for CI/CD pipelines, deployment scripts, and automated systems that need to interact with exactly one repository.

Why Use Deploy Keys

Personal SSH keys and API tokens are tied to a user account and grant access to every repository that user can see. Deploy keys solve several problems with that model:
  • Least privilege: A deploy key grants access to a single repository. If the key is compromised, the blast radius is limited to that one repository.
  • No user account required: Automated systems do not need their own JJHub user account. A deploy key is registered directly on the repository.
  • Auditable: Deploy key usage is logged alongside other repository access events, making it clear which automated system performed an action.
  • Independent lifecycle: Deploy keys can be rotated or revoked without affecting any user’s access to the platform.

Use Cases

CI/CD Pipelines

A CI runner needs to clone a repository, run tests, and report results. A read-only deploy key lets it clone without exposing write access:

Deployment Scripts

A deployment script needs to pull the latest code onto a production server. A read-only deploy key keeps the server from being able to push changes back:

Automated Pushes

Some automation needs to push changes — for example, a bot that updates dependency versions. A read-write deploy key grants the necessary access:
Without --read-only, the key has read-write access by default.

Read-Only Mirrors

If you maintain a mirror of a repository on another server, a read-only deploy key lets the mirror pull updates without being able to modify the source:

Managing Deploy Keys via CLI

Add a Deploy Key

List Deploy Keys

Example output:

Delete a Deploy Key

The positional argument is the deploy key ID, which you can find from jjhub repo deploy-key list.

Managing Deploy Keys via API

List Deploy Keys

Response:

Get a Deploy Key

Returns a single deploy key object.

Add a Deploy Key

Response (201 Created):
Error cases:
  • 400 — Missing required fields (title, key)
  • 401 — Not authenticated
  • 403 — Insufficient permissions (requires admin or owner access to the repository)
  • 409 — Key already exists on this repository
  • 422 — Invalid SSH public key format

Delete a Deploy Key

Returns 204 No Content on success.

Read-Only vs Read-Write

Read-only deploy keys can clone and pull from the repository but cannot push changes. Read-write deploy keys can do both. Recommendation: Always use read-only keys unless the automated system genuinely needs to push changes. This follows the principle of least privilege and limits the impact of a compromised key.

Security Best Practices

  1. Use read-only keys by default. Only grant write access when the automation truly needs to push changes.
  2. Generate dedicated key pairs. Do not reuse your personal SSH key as a deploy key. Generate a new key pair for each automated system.
  3. Rotate keys regularly. Delete and recreate deploy keys periodically, especially for long-running infrastructure.
  4. Use meaningful titles. Give each deploy key a descriptive title (e.g., “CI Runner - GitHub Actions”, “Prod Deploy Server”) so you can identify what each key is used for when auditing access.
  5. Revoke unused keys immediately. When a CI pipeline is decommissioned or a deployment server is retired, delete the corresponding deploy key right away.
  6. Protect the private key. Store the private key securely on the system that needs it. Use file permissions (chmod 600) and avoid committing private keys to any repository.
  7. One key per system. Do not share a single deploy key across multiple CI runners or servers. If one system is compromised, you want to revoke only that system’s key without disrupting others.

Deploy Keys vs Other Authentication Methods

Deploy keys are the right choice when an automated system needs access to exactly one repository and you want to avoid creating a dedicated user account or sharing a personal token.

API Reference