Site: Planekeeper Docs — Monitor software versions across your stack. Planekeeper tracks releases, gathers version data, and alerts on drift.
Section: Recipes > Access private repositories and registries
Source: https://docs.planekeeper.com/recipes/private-repo-access/
Title: Access private repositories and registries
Author: Planekeeper
Description: Configure SSH keys, HTTPS tokens, and registry credentials for accessing private Git repositories and container registries.
Word count: 1220
Reading time: 6 min

Contents:
- [Prerequisites](#prerequisites)
- [Credential types](#credential-types)
- [SSH key authentication](#ssh-key-authentication)
  - [Step 1: Generate an SSH key pair](#step-1-generate-an-ssh-key-pair)
  - [Step 2: Add the public key to your Git host](#step-2-add-the-public-key-to-your-git-host)
  - [Step 3: Configure the agent](#step-3-configure-the-agent)
  - [Step 4: Create a scrape job with the credential](#step-4-create-a-scrape-job-with-the-credential)
- [HTTPS personal access token](#https-personal-access-token)
  - [Step 1: Create a personal access token](#step-1-create-a-personal-access-token)
  - [Step 2: Configure the agent](#step-2-configure-the-agent)
  - [Step 3: Create a scrape job with the credential](#step-3-create-a-scrape-job-with-the-credential)
- [OCI registry credentials](#oci-registry-credentials)
  - [Step 1: Create a registry access token](#step-1-create-a-registry-access-token)
  - [Step 2: Configure the agent](#step-2-configure-the-agent)
  - [Step 3: Create a gather job with the credential](#step-3-create-a-gather-job-with-the-credential)
- [Multiple credentials](#multiple-credentials)
- [Credential-aware job assignment](#credential-aware-job-assignment)
- [Security best practices](#security-best-practices)

***

# Access private repositories and registries


Scrape jobs that target private Git repositories and gather jobs that pull from private container registries need credentials. Planekeeper agents support three credential types: SSH keys, HTTPS personal access tokens (PATs), and OCI registry credentials.

All credentials are configured in the agent's `config.yaml` file and never leave the agent. The API server only sees credential **names** — secret values stay local.

---

## Prerequisites

- A running Planekeeper instance with at least one agent
- Access to create deploy keys, personal access tokens, or registry tokens for your platform

---

## Credential types

| Type | Config value | Used by | Use case |
|------|-------------|---------|----------|
| SSH key | `ssh_key` | Scrape jobs | Private Git repos via SSH (`git@github.com:...`) |
| HTTPS PAT | `https_pat` | Scrape jobs | Private Git repos via HTTPS (`https://github.com/...`) |
| Registry | `registry_basic` | Gather jobs | Private OCI registries (Docker Hub, GHCR, Quay.io, etc.) |

---

## SSH key authentication

SSH keys are the recommended method for private Git repositories. Use deploy keys scoped to a single repository for maximum security.

### Step 1: Generate an SSH key pair

Generate a dedicated key pair for the agent. Do not reuse personal SSH keys.

```bash title="Generate a new SSH key"
ssh-keygen -t ed25519 -f planekeeper-deploy -C "planekeeper-agent" -N ""
```

This creates two files:

- `planekeeper-deploy` (private key)
- `planekeeper-deploy.pub` (public key)

### Step 2: Add the public key to your Git host

**GitHub**

    1. Go to your repository's **Settings** > **Deploy keys**
    2. Click **Add deploy key**
    3. Paste the contents of `planekeeper-deploy.pub`
    4. Leave **Allow write access** unchecked (read-only is sufficient)
    5. Click **Add key**

**GitLab**

    1. Go to your project's **Settings** > **Repository** > **Deploy keys**
    2. Click **Add key**
    3. Paste the contents of `planekeeper-deploy.pub`
    4. Set permissions to **Read**
    5. Click **Add key**

**Bitbucket**

    1. Go to your repository's **Settings** > **Access keys**
    2. Click **Add key**
    3. Paste the contents of `planekeeper-deploy.pub`
    4. Label it `planekeeper-agent`
    5. Click **Add SSH key**

### Step 3: Configure the agent

Add the credential to the agent's `config.yaml` file. You can provide the key as a file path or inline.

**File-based (recommended)**

    ```yaml title="config.yaml"
    agent:
      credentials:
        my-github-ssh:
          type: ssh_key
          private_key_file: /ssh/planekeeper-deploy
          passphrase: ""  # optional, for encrypted keys
    ```

    Mount the private key file into the agent's Docker container:

    ```yaml title="docker-compose.yml (agent service)"
    volumes:
      - ./keys/planekeeper-deploy:/ssh/planekeeper-deploy:ro
    ```

**Inline**

    ```yaml title="config.yaml"
    agent:
      credentials:
        my-github-ssh:
          type: ssh_key
          private_key: |
            -----BEGIN OPENSSH PRIVATE KEY-----
            ...key content...
            -----END OPENSSH PRIVATE KEY-----
          passphrase: ""  # optional, for encrypted keys
    ```

> **warning:** 
**File permissions**

The private key file must have restricted permissions. Set permissions to `600` (owner read/write only) on the host before mounting.


> **info:** 
`private_key_file` and `private_key` are mutually exclusive. Use one or the other, not both.


### Step 4: Create a scrape job with the credential

1. Navigate to **Scrape Jobs** in the sidebar
2. Click **Create Scrape Job**
3. Fill in the fields:

| Field | Value |
|-------|-------|
| Repository URL | `git@github.com:myorg/private-repo.git` |
| Credential Name | `my-github-ssh` |
| Target File | `Chart.yaml` |
| Parser Type | `yq` |
| Parse Expression | `.version` |

4. Click **Create**

> **info:** 
**SSH URL format**

Use the SSH URL format (`git@github.com:...`) when using SSH key credentials. HTTPS URLs require HTTPS PAT credentials.


---

## HTTPS personal access token

HTTPS PATs work with any Git hosting platform and are simpler to configure, but they typically grant broader access than deploy keys.

### Step 1: Create a personal access token

**GitHub**

    1. Go to **Settings** > **Developer settings** > **Personal access tokens** > **Fine-grained tokens**
    2. Click **Generate new token**
    3. Set **Repository access** to **Only select repositories** and choose your repo
    4. Under **Permissions**, set **Contents** to **Read-only**
    5. Click **Generate token** and copy the value

**GitLab**

    1. Go to **Preferences** > **Access Tokens**
    2. Create a new token with `read_repository` scope
    3. Copy the token value

**Bitbucket**

    1. Go to **Personal settings** > **App passwords**
    2. Create a new app password with **Repositories: Read** permission
    3. Copy the password

### Step 2: Configure the agent

Add the credential to the agent's `config.yaml`:

```yaml title="config.yaml"
agent:
  credentials:
    github-pat:
      type: https_pat
      token: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Planekeeper uses `git` as the username automatically when cloning with a PAT. This works with GitHub, GitLab, Bitbucket, and most other Git hosting platforms.

### Step 3: Create a scrape job with the credential

1. Navigate to **Scrape Jobs** in the sidebar
2. Click **Create Scrape Job**
3. Fill in the fields:

| Field | Value |
|-------|-------|
| Repository URL | `https://github.com/myorg/private-repo.git` |
| Credential Name | `github-pat` |
| Target File | `package.json` |
| Parser Type | `jq` |
| Parse Expression | `.version` |

4. Click **Create**

> **info:** 
**HTTPS URL format**

Use the HTTPS URL format (`https://github.com/...`) when using HTTPS PAT credentials. SSH URLs require SSH key credentials.


---

## OCI registry credentials

Registry credentials authenticate gather jobs that fetch tags from private OCI container registries such as Docker Hub, GitHub Container Registry (GHCR), and Quay.io.

### Step 1: Create a registry access token

**Docker Hub**

    1. Go to **Account Settings** > **Security** > **Access Tokens**
    2. Click **New Access Token**
    3. Set permissions to **Read-only**
    4. Copy the token

**GitHub Container Registry (GHCR)**

    1. Go to **Settings** > **Developer settings** > **Personal access tokens**
    2. Create a token with `read:packages` scope
    3. Copy the token

**Quay.io**

    1. Go to your repository's **Settings** > **Robot Accounts**
    2. Create a robot account with **Read** permission
    3. Copy the username and token

### Step 2: Configure the agent

Add the credential to the agent's `config.yaml`:

**Docker Hub**

    ```yaml title="config.yaml"
    agent:
      credentials:
        dockerhub:
          type: registry_basic
          username: myuser
          password: dckr_pat_xxxxxxxxxxxx
    ```

**GHCR**

    ```yaml title="config.yaml"
    agent:
      credentials:
        ghcr:
          type: registry_basic
          username: github-username
          password: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ```

**Quay.io**

    ```yaml title="config.yaml"
    agent:
      credentials:
        quay:
          type: registry_basic
          username: orgname+robotname
          password: ROBOT_TOKEN_VALUE
    ```

### Step 3: Create a gather job with the credential

1. Navigate to **Gather Jobs** in the sidebar
2. Click **Create Gather Job**
3. Fill in the fields:

| Field | Value |
|-------|-------|
| Source Type | `oci_registry` |
| Artifact Name | `ghcr.io/myorg/private-image` |
| Credential Name | `ghcr` |

4. Click **Create**

---

## Multiple credentials

You can define multiple credentials of different types in the same config file:

```yaml title="config.yaml"
agent:
  credentials:
    github-ssh:
      type: ssh_key
      private_key_file: /ssh/id_ed25519
    gitlab-pat:
      type: https_pat
      token: glpat-xxxxxxxxxxxxxxxxxxxx
    dockerhub:
      type: registry_basic
      username: myuser
      password: dckr_pat_xxxxxxxxxxxx
    ghcr:
      type: registry_basic
      username: github-username
      password: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Each credential is referenced by its name (the map key) when creating scrape or gather jobs.

---

## Credential-aware job assignment

When a job requires a credential, Planekeeper only assigns it to agents that have declared that credential. Agents report their available credential names during the heartbeat process — secret values are never sent to the server.

If no agent has the required credential, the job remains in "pending" status until a capable agent connects.

> **success:** 
**Check agent capabilities**

If a job is stuck in "pending" status, verify that at least one agent has the required credential configured and is actively connected. Check the dashboard for agent status.


---

## Security best practices

**Use read-only credentials.** Agents only need to clone repositories or pull image tags, not push. Always use the most restrictive permission level available.

**Use deploy keys over personal tokens for Git.** Deploy keys are scoped to a single repository. Personal tokens often grant access to all repositories the user can access.

**Rotate credentials regularly.** Set calendar reminders to rotate SSH keys, PATs, and registry tokens. When you rotate, update the agent config and restart the agent.

**Mount secrets as read-only.** When using Docker volumes, add `:ro` to prevent the container from modifying key files or config.

**Keep config.yaml secure.** The `config.yaml` file contains secrets in plain text. Restrict file permissions and avoid committing it to version control. Consider using Docker secrets or a mounted volume from a secrets manager.

**Credentials never leave the agent.** The API server only sees credential names, not values. All authenticated Git clones and registry pulls happen locally on the agent.


---

## Related

- Next: [Manual Version Tracking](https://docs.planekeeper.com/recipes/manual-version-tracking/page.md) — Track deployed software versions manually without agents, and set up the full monitoring pipeline end-to-end.
- Section: [Recipes](https://docs.planekeeper.com/recipes/index.md)
