Skip to content

Custom / OCI Distribution

The Custom provider is HarborGuard's escape hatch for any registry that implements the OCI Distribution Spec but isn't one of the recognized vendors. CNCF Distribution (the registry formerly known as registry:2), Zot, BoltDB-backed home labs, and any vendor's "OCI-compatible" registry all fall here.

When to pick Custom

Use Custom when none of the following apply:

  • The hostname matches an auto-detected provider (ECR, GAR, ACR, GHCR, Docker Hub, GitLab, JFrog, Quay).
  • It's Harbor or Nexus — pick those explicitly to get provider-specific catalog hints.

If a typed provider exists for your registry, prefer it. Custom is a generic OCI client; it doesn't know about provider-specific REST APIs (Docker Hub's /v2/repositories, ACR's tag filters, etc.) and falls back to the standard /v2/_catalog + /v2/<repo>/tags/list.

Auth options

The wizard's credential form for Custom takes a generic Username + Password / Token pair, which gets sent through the standard Docker Registry v2 auth flow:

  1. GET /v2/ — if it returns 200, no auth needed.
  2. If it returns 401 with a WWW-Authenticate: Bearer realm="..." header, HarborGuard's test-connection helper exchanges credentials at the realm and retries with the bearer token.
  3. If the challenge is WWW-Authenticate: Basic, HarborGuard sends Basic auth on every request.

Anonymous registries: leave the credentials blank.

Add the registry

  1. Registries → Connect Registry.
  2. Registry URLregistry.internal.example.com (or with port :5000, :8080, etc.).
  3. Wizard does not show "Detected" — fall through to Custom.
  4. Optional: enable Allow HTTP / insecure if you're connecting to a plain-HTTP registry. The toggle is hidden once the URL starts with https://.
  5. Optional credentials.
  6. Save.

What HarborGuard expects from the registry

Required endpoints (Distribution Spec v1):

  • GET /v2/ — base probe.
  • GET /v2/_catalog — list of repositories. Some registries restrict this; if it returns 401/403, HarborGuard cannot enumerate. You can still scan known images by pushing scan requests via the API.
  • GET /v2/<repo>/tags/list — tags per repo.
  • GET /v2/<repo>/manifests/<reference> — manifest fetch (during scan).
  • GET /v2/<repo>/blobs/<digest> — layer fetch (during scan).

Push-event sync

Generic Distribution does not have a single webhook standard. CNCF Distribution can be configured with a notifications block in config.yml to POST events to a URL — wire it to https://<your-harborguard-host>/api/webhooks/oci. Other servers (Zot, etc.) have their own mechanisms; consult their docs.

If the registry has no webhook, leave the schedule on daily or trigger from CI.

Common pitfalls

  • _catalog is a privilege. Many self-hosted Distribution deployments restrict /v2/_catalog to admins. HarborGuard will report "0 repositories synced" even when individual images are scannable. Workaround: scan-by-name from your CI pipeline.
  • Plain HTTP. The "Allow HTTP / insecure" toggle is intentionally hidden when the URL is https:// — switching from HTTPS to HTTP requires recreating the registry.
  • Trailing slashes. HarborGuard normalizes https://reg.example.com/ to https://reg.example.com server-side, but external systems comparing URLs (e.g., webhook payloads) may not. Always store the canonical form.
  • Self-signed TLS. Cloud-mode connections will reject untrusted CAs. Use a sensor or install a publicly trusted certificate.
  • Pagination. A Distribution server returning very large catalogs uses Link headers for pagination. HarborGuard follows them; a registry that drops the Link header on page 2 will appear to have a smaller catalog than reality.

Troubleshooting

SymptomLikely cause
Test passes, sync returns 0 repos/v2/_catalog is restricted; scan by-image-name instead
/v2/ returns 200 but pulls 401Per-repo permissions differ from the base probe
TLS handshake error in cloud modeSelf-signed cert; deploy a sensor
Tags listed but manifests failManifest media-type unsupported (very rare; older registries) — file an issue with the registry vendor
Insecure toggle missingURL starts with https://; clear the URL and re-enter without scheme

On this page