Private Registries

What you'll accomplish: Add private registries, configure auth tokens, and use scoped packages to prevent name collisions.

Multi-registry configuration

[catalog]
verify_signatures = true
default_publish_registry = "internal"

[[catalog.registries]]
name = "internal"
url = "https://packages.internal.company.com"
priority = 1
auth_token_env = "INTERNAL_REGISTRY_TOKEN"
enabled = true
require_signatures = true   # default: true (fail closed) — set false only for a
                             # registry explicitly known not to sign packages

[[catalog.registries]]
name = "hoziron"
url = "https://catalog.hoziron.com"
priority = 100
enabled = true

The built-in hoziron registry entry (https://catalog.hoziron.com, priority 100) is the config default — it's always present unless you explicitly remove it.

Resolution order

Non-scoped packages are queried in priority order (lowest number first). First registry with the package wins.

Scoped packages

@scope/name syntax pins a package to a specific registry:

# Only queries the "internal" registry
hoziron-cli catalog install @internal/proprietary-claims-tool

Configure scope mappings

[catalog.scopes]
internal = "https://packages.internal.company.com"
hoziron = "https://catalog.hoziron.com"

Scope rules:

  • Scope names: lowercase alphanumeric + hyphens
  • Must be mapped in [catalog.scopes] — error if unknown scope
  • Bypasses priority-order resolution entirely
  • Prevents name collisions between registries

Auth tokens

Store registry auth tokens as environment variables:

export INTERNAL_REGISTRY_TOKEN="your-token-here"

Reference in config:

auth_token_env = "INTERNAL_REGISTRY_TOKEN"

Testing registries

# Test all configured registries
hoziron-cli catalog registry test

# Test a specific registry
hoziron-cli catalog registry test internal

# List configured registries
hoziron-cli catalog registry list

Registry management lives under hoziron-cli catalog registry <subcommand>add, list, update, remove, test, bootstrap. add/update/remove/bootstrap require catalog:manage (Admin/Operator); list/test require only catalog:read.

Bootstrapping a fresh private registry

A brand-new registry has no API keys, so its own POST /keys endpoint allows exactly one unauthenticated request — the first key. hoziron-cli catalog registry bootstrap wraps this for a registry already added to your config:

hoziron-cli catalog registry add internal --name internal --url https://packages.internal.company.com --priority 1
hoziron-cli catalog registry bootstrap internal --key-name admin --role admin

This calls the registry's POST /keys directly (bypassing the main daemon) and prints the key once — save it and reference it via auth_token_env. Every subsequent key on that registry requires an authenticated admin key.

Registry-side auth posture (operating a registry, not just consuming one)

Everything above is the client side — how a consumer authenticates against a registry someone else runs. If you're the one operating the registry, it has its own independent [auth] config controlling what it requires:

[auth]
mode = "local"                    # disabled | local | oidc
download_requires_auth = true     # requires auth on downloads even if mode = "disabled"
read_requires_auth = false        # requires auth on search/package-info reads too
allow_insecure_no_auth = false    # explicit opt-out for intentionally-open dev registries

mode = "disabled" is refused at boot if the registry is bound to a network-reachable address, unless allow_insecure_no_auth is set — this is a deliberate posture gate, not an oversight. download_requires_auth/read_requires_auth are structural per-route gates (Issue #667): they apply independent of mode, so you can require auth on downloads specifically even on an otherwise-open registry. See reference/api/registry.md for the full field reference, and reference/api/registry.md#s3-compatible-storage-backend if you're storing package archives in S3/R2/MinIO instead of the local filesystem.

Publishing to a private registry

# Explicit target
hoziron-cli package publish ./my-package/ --registry internal

# Or use default_publish_registry
hoziron-cli package publish ./my-package/

Next steps


Related: