Configure Credentials for Multiple Registries

Goal

Configure OCM to authenticate against multiple OCI registries — pinning explicit credentials for specific registries while using Docker config as a catch-all fallback.

You’ll end up with

  • An OCM config file that resolves credentials automatically for every ocm command
  • Explicit control over specific registry paths with Docker config covering the rest

Prerequisites

  • OCM CLI installed
  • Docker CLI installed and docker login run for any registries you want as fallback (creates ~/.docker/config.json)

Steps

  1. Identity by hostname only

    Create $HOME/.ocmconfig with an identity that matches any path on a hostname:

    type: generic.config.ocm.software/v1
    configurations:
      - type: credentials.config.ocm.software
        consumers:
          # Hostname-only identity
          - identities:
              - type: OCIRegistry
                hostname: ghcr.io  # No path = matches all paths
            credentials:
              - type: Credentials/v1
                properties:
                  username: my-user
                  password: ghp_your_token_here

    Identity: hostname: ghcr.io (no path)
    Matches: ghcr.io/any-org/any-repo, ghcr.io/foo/bar, etc. — all paths on this hostname.

  2. Identity by hostname + exact path

    Add an identity that matches a specific path on a hostname:

    type: generic.config.ocm.software/v1
    configurations:
      - type: credentials.config.ocm.software
        consumers:
          # ... other consumers
          # Hostname + exact path identity
          - identities:
              - type: OCIRegistry
                hostname: ghcr.io
                path: my-org/production  # Exact path match
            credentials:
              - type: Credentials/v1
                properties:
                  username: prod-user
                  password: ghp_production_token

    Identity: hostname: ghcr.io + path: my-org/production
    Matches: Only ghcr.io/my-org/production (exact match)
    Differs from step 1: The first consumer now matches only one specific path. The second consumer (hostname-only) catches everything else on ghcr.io.

  3. Identity by hostname + path pattern

    Add an identity that matches multiple paths using a glob pattern:

    type: generic.config.ocm.software/v1
    configurations:
      - type: credentials.config.ocm.software
        consumers:
          # ... other consumers
          # Hostname + path glob identity
          - identities:
              - type: OCIRegistry
                hostname: ghcr.io
                path: my-org/*  # Glob — matches one segment after my-org/
            credentials:
              - type: Credentials/v1
                properties:
                  username: org-user
                  password: ghp_org_token

    Identity: hostname: ghcr.io + path: my-org/*
    Matches: ghcr.io/my-org/staging, ghcr.io/my-org/dev, etc. — any single segment after my-org/
    Differs from step 2: Uses a glob pattern (*) instead of an exact path. More specific identities (like path: my-org/production) are checked first.

  4. Identity via Docker config (fallback)

    Add a repositories section to use Docker config for any registry not matched by consumers:

    type: generic.config.ocm.software/v1
    configurations:
      - type: credentials.config.ocm.software
        consumers:
        # ... other consumers
        # Docker config fallback
        repositories:
          - repository:
              type: DockerConfig/v1
              dockerConfigFile: "~/.docker/config.json"  # Fallback for unmatched registries

    Identity: Derived from the auths section in Docker config file (~/.docker/config.json)
    Matches: Any registry with credentials in Docker config that wasn’t matched by a consumer
    Differs from steps 1-3: This is a repository (not a consumer). OCM checks all consumers first, then falls back to repositories. Use this for registries you authenticate with docker login.

Complete Example Configuration

Here’s a complete configuration combining all identity types:

type: generic.config.ocm.software/v1
configurations:
  - type: credentials.config.ocm.software
    consumers:
      # Path glob: matches ghcr.io/my-org/staging, ghcr.io/my-org/dev, etc.
      - identities:
          - type: OCIRegistry
            hostname: ghcr.io
            path: my-org/*
        credentials:
          - type: Credentials/v1
            properties:
              username: org-user
              password: ghp_org_token
      # Exact path: matches only ghcr.io/my-org/production (takes precedence over glob)
      - identities:
          - type: OCIRegistry
            hostname: ghcr.io
            path: my-org/production
        credentials:
          - type: Credentials/v1
            properties:
              username: prod-user
              password: ghp_production_token
      # Hostname only: matches all other paths on ghcr.io
      - identities:
          - type: OCIRegistry
            hostname: ghcr.io
        credentials:
          - type: Credentials/v1
            properties:
              username: my-user
              password: ghp_your_token_here
    # Docker config: fallback for any registry not matched above
    repositories:
      - repository:
          type: DockerConfig/v1
          dockerConfigFile: "~/.docker/config.json"

Resolution order (see Credential Resolution Tutorial for details):

  1. ghcr.io/my-org/production → uses prod-user (exact path match)
  2. ghcr.io/my-org/staging → uses org-user (glob my-org/* match)
  3. ghcr.io/other-org/repo → uses my-user (hostname-only match)
  4. docker.io/library/nginx → uses Docker config (no consumer matched)

Troubleshooting

Use ocm --loglevel debug to enable debug logging. This shows which consumers are checked and how credentials are resolved.

Symptom: 401 Unauthorized for a registry with explicit credentials

Cause: The consumer identity doesn’t match the request. Common issues: mismatched path or hostname.

Fix: Check that hostname and path match the registry URL exactly. Remember that path: my-org does not match my-org/production.

Symptom: 401 Unauthorized for a registry that should use Docker fallback

Cause: Docker config doesn’t have credentials for that registry.

Fix: Run docker login <registry-hostname>, then retry the OCM command.