---
title: "Registry"
description: "Store container images, Helm charts, models and files in your project, push them from CI without a stored password, and run only digests Frazer scanned and signed on push."
url: https://frazer.ai/docs/registry
index: https://frazer.ai/docs/llms.txt
tokens: 4359
---

> For agents: this page is indexed at https://frazer.ai/docs/llms.txt, and every page at https://frazer.ai/llms.txt. Copy commands from this file exactly.

# Registry

Frazer Registry stores container images, Helm charts, models and versioned files in your project, inside your Frazer cloud. CI pushes with a short-lived token instead of a stored password, Frazer scans every push and signs the digest with your project’s key, and your clusters run only signed digests. Servers pull from their peers and a cache at their site first, on your own servers and on the Frazer fleet alike.

Product overview: [Registry](https://frazer.ai/registry).

## How it works

Every project has a registry at `registry.frazer.ai/<project>`, with repositories inside it. A push lands in a repository by digest. Frazer scans it, signs it with the project’s key, and attaches the signature, the SBOM and the provenance to the digest as OCI referrers. When a cluster rolls the digest out, admission checks the signature, and the version records where it runs.

```text
registry.frazer.ai/acme-production/apps/checkout-api:v1.42.0
registry.frazer.ai/acme-production/apps/checkout-api@sha256:51ab…e09
```

The global name answers from your organization’s home region. Each region also has its own name, such as `registry.us-virginia1.frazer.ai`, and each project a private name, `registry.<project>.internal`, for pulls from inside the project’s network without a public address.

A server pulls an image from its peers first, then from the cache at its site, then from the region. A site keeps pulling cached images when the region cannot be reached.

-   **Repository**: a set of images or packages with one format, one mode and one settings page.
-   **Image**: a named set of versions inside a repository, such as `checkout-api`.
-   **Version**: one digest, with its tags, size, who pushed it, scan results, signatures and where it runs.
-   **Tag**: a name for a version. Tags that match an immutable rule never move; digests never do.
-   **Referrer**: an artifact attached to a digest: a signature, an SBOM, provenance or a vulnerability report.
-   **Repository template**: settings applied to repositories created on push, by an import or by a remote. A template is shared with other projects like any shared resource.

### Formats

| Format | Holds | Clients |
| --- | --- | --- |
| Docker and OCI | Images and multi-architecture indexes, with signatures, SBOMs, provenance and VEX as referrers | docker, podman, buildx, crane, oras |
| Helm | Charts as OCI artifacts | `helm push oci://` |
| Model | Model weights as OCI artifacts (ModelKit, ModelPack), exported from the model catalog or pushed by you | `kit`, oras, `frazer ai models export --oci` |
| Generic | Versioned, immutable files: binaries, datasets, build outputs | oras, `frazer registry files push` |
| npm, PyPI, Go modules | Packages with the same access, cleanup and scanning | npm, pnpm, yarn, pip, uv, `GOPROXY` |

### Modes

| Mode | What it does |
| --- | --- |
| **Standard** | You push to it. |
| **Remote** | A pull-through cache of an upstream: Docker Hub, GHCR, Quay, registry.k8s.io, NVIDIA NGC, any OCI registry, and npmjs, PyPI and proxy.golang.org for packages. The first pull caches; later pulls come from the cache, also when the upstream is down or returns 429. |
| **Virtual** | One read endpoint over ordered repositories, such as `apps`, then `base-images`, then `dockerhub`. For packages, it also stops dependency confusion. |

### Git and URL dependencies

Frazer CI, devboxes and agent sandboxes install git and remote-URL dependencies only from your organization’s source allowlist: a repository URL with a commit, or a URL with a digest. A branch or a tag never qualifies. On day one Frazer suggests the list from your lockfiles. A blocked source fails before the install with `source_not_allowlisted` and the command to propose it: `frazer packages sources allow --source <source> --plan`.

## Push your first image

1.  Create a repository.
    
    ### CLI
    
    ```sh
    frazer registry repositories create apps --format docker \
      --immutable 'v*,release-*' --dry-run
    ```
    
    Read the plan, then run the command again without `--dry-run` to create the repository.
    
    ### Console
    
    Open **Engineering › Registry** in your project and choose **Create repository**. Pick the format and the mode, review the settings and apply.
    
2.  Let Docker sign in with your Frazer identity.
    
    ```sh
    frazer auth configure-docker
    ```
    
    Docker now takes a Frazer token that lasts at most an hour. Nothing is written to a password file.
    
3.  Build, tag and push.
    
    ```sh
    docker build -t registry.frazer.ai/acme-production/apps/checkout-api:v1.42.0 .
    docker push registry.frazer.ai/acme-production/apps/checkout-api:v1.42.0
    ```
    
4.  Look at the version. The scan result and the signature appear on it once the scan finishes.
    
    ```sh
    frazer registry images list apps/checkout-api
    frazer registry images describe apps/checkout-api@sha256:51ab…
    ```
    
    In the console, the image page lists every version by digest with its tags, findings, signature, SBOM and where it runs.
    

## Push from GitHub Actions without a password

CI never holds a registry password. A GitHub Actions job presents its OIDC token to Frazer’s token exchange; a condition on the token’s `repository`, `ref` and `job_workflow_ref` claims maps the job to a service account such as `ci-release`, and the exchange returns a 15-minute token that may push only to the repositories you named.

1.  In the project, set up workload identity federation for GitHub Actions and map it to a service account that may push to `apps`. See [IAM](https://frazer.ai/docs/iam).
    
2.  Give the job permission to request an OIDC token, and push with the Frazer CLI’s credential helper:
    
    ```yaml title=".github/workflows/release.yml"
    permissions:
      contents: read
      id-token: write # lets the job ask GitHub for an OIDC token
    jobs:
      release:
        runs-on: frazer-16c-release
        steps:
          - uses: actions/checkout@v5
          - run: curl -fsSL frazer.ai/install | sh
          - run: frazer auth configure-docker
          - run: >-
              docker buildx build --push --sbom=true --provenance=mode=max
              -t registry.frazer.ai/acme-production/apps/checkout-api:${{ github.ref_name }} .
    ```
    
    Any GitHub Actions runner works; `frazer-16c-release` is a [GitHub runners](https://frazer.ai/docs/runners/github) release lane.
    
3.  Write the new digest into your environment repository, so your cluster rolls it out. See [Environments and GitOps](https://frazer.ai/docs/gitops#roll-out-a-new-image-from-ci).
    

Clusters, serverless services and devboxes pull with their own tokens, valid for at most an hour and renewed for them. No registry credential is ever stored in Git.

## Cache an upstream registry

A remote repository caches every image you pull through it. When the upstream is down or rate-limits you, cached copies keep serving and only new tags wait.

```sh
frazer registry repositories create dockerhub --format docker \
  --mode remote --upstream docker.io --credential dockerhub-pull
```

`dockerhub-pull` names the upstream credential, which is kept in Frazer Secrets. A remote repository’s settings add the **Pull budget** (how many pulls the upstream allows), the **Tag refresh** interval (1 hour by default) and how long cached images are kept.

To give clients one address for everything, create a **virtual** repository in the console that reads `apps`, then `base-images`, then `dockerhub`, in that order.

## Keep, clean up and recover versions

Each repository has one settings page. The defaults keep what matters and remove what nobody uses:

| Setting | Default |
| --- | --- |
| Immutable tags | `v*` and `release-*`; `main-*` and `pr-*` stay mutable. In production projects, every tag except `latest`\-like exclusions. |
| Keep | In use in any cluster, service, box or agent (locked on); `v*` and `release-*` tags; the 20 most recent tagged versions per image |
| Delete | Untagged versions older than 14 days |
| Dry run | On: every policy runs as a dry run first |
| Deletion guard | A run that would delete more than 20 % of a repository’s versions, or anything pulled in the last 14 days, stops and asks |
| Recovery | Deleted versions can be restored for 30 days |

Keep rules win over delete rules, and nothing that runs is ever deleted. See what a policy would do, and bring a version back:

```sh
frazer registry cleanup dry-run apps
frazer registry versions restore apps/checkout-api@sha256:e5c2…
```

## Scanning and signing

-   **Scan on push**: every push is scanned for vulnerabilities. Versions in use, or pulled in the last 30 days, are scanned again every day. A new Critical on a running digest becomes a [Security Center](https://frazer.ai/docs/security-center) finding with the path to the workload.
-   **Deploy policy**: new rollouts of a digest with a fixable Critical are blocked. This is on by default and blocks in production projects.
-   **Signed on push**: Frazer signs every digest with the project’s key (`sign-<project>`), in cosign format, and attaches the signature as a referrer. The signature records who pushed, the repository, and the commit and workflow from CI.
-   **Webhooks**: each push and each finished scan reaches your [webhooks](https://frazer.ai/docs/webhooks) as `frazer.image.pushed.v1` and `frazer.image.scan.completed.v1`.
-   **Admission**: clusters and serverless runtimes admit only digests signed by the project’s key or another signer you accept, such as an organization key. Production projects enforce it.

> **Note:** A version imported from another registry before signing shows as unsigned, and production refuses it until it carries a signature you accept. Add its original signer to the repository’s accepted signers, or rebuild and push it.

## Charts, models and files

Push a Helm chart as an OCI artifact:

```sh
helm push checkout-api-1.4.0.tgz oci://registry.frazer.ai/acme-production/charts
```

Models move between the model catalog and the registry as OCI artifacts: `frazer ai models export --oci` writes a model from the catalog into a Model repository, signed like any image, and a ModelKit or ModelPack artifact you push can be imported into the catalog. See [AI and GPUs](https://frazer.ai/docs/ai).

Push a versioned file to a Generic repository:

```sh
frazer registry files push generic/tools ./bin/zctl --version 1.4.0
```

## Import from another registry

The import wizard copies the images and charts you already have, digest for digest, with their referrers. Open **Engineering › Registry** and choose **Import**:

1.  **Source**: the registry, a read-only credential, the region and filters. Sources include Docker Hub, GHCR, Quay, Harbor and the registries of other clouds.
2.  **Select**: the repositories to bring and the Frazer repository each maps to; name conflicts are flagged.
3.  **Dry run**: a plan, item by item: copy, skip (identical), conflict or too large, with bytes and the source’s egress estimate.
4.  **Import**: progress per item, then a report. Each digest and checksum is verified.

The source is only read. The credential is kept in Frazer Secrets and **deleted when the import closes**. While the import is open, for up to 30 days, you can re-run deltas as you cut over; nothing keeps syncing after it closes.

## Access and audit

-   **People**: project roles apply to the registry, and a repository can add its own bindings: **Registry reader**, **Registry writer** and **Repo admin**.
-   **CI**: a service account mapped from the CI job’s OIDC token, with a 15-minute token that can push only to the repositories it names.
-   **Clusters, serverless and devboxes**: their own pull tokens, valid for at most an hour and renewed for them.
-   **Agents**: read through the `registry` MCP toolset. Pushing stays with CI.

Frazer logs every token with the repository and workflow that asked for it (`registry.tokens.create`), every push with its digest (`registry.versions.push`), every pull with the real principal, and every cleanup run and restore. The signature itself records who pushed, from which commit and workflow.

## Limits and quotas

| Setting | Default |
| --- | --- |
| Repositories per project | 100 |
| Storage per project | 5 TiB |
| Storage per repository | Inherits the project quota; warns at 80 % of a cap you set |
| CI push token | 15 minutes, named repositories only |
| People’s and clusters’ tokens | At most 1 hour |
| Recovery window | 30 days |
| Running imports | 5 per organization |
| Import delta window | 30 days |

Bytes are reserved before an upload is accepted, and a layer counts once per project, however many images share it.

## Pricing

Registry storage counts toward an allowance for every server you bring, pooled across your billing account; above it you pay the Frazer Storage rate. Pulls, scans, signatures and replication inside Frazer have no charge, and an import has no Frazer fee (the source bills its own egress, shown in the dry run). When a budget cap is reached, storage keeps serving and nothing is deleted.

| Registry | On your servers | On the Frazer fleet |
| --- | --- | --- |
| Price | 50 GB per server included | Then $0.012 / GiB-month · no scan or signing fee |

Every line, with the estimator: [pricing](https://frazer.ai/pricing#lines).

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| CI’s push is denied | The CI token may push only to the repositories its service account names, or the OIDC claims do not match the federation condition. | Check the repository, ref and workflow in the condition, and the repositories bound to the service account. |
| A push to an existing tag is refused | The tag matches an immutable rule, such as `v*`. | Push a new tag. Digests never move, and immutable tags never do either. |
| A rollout is blocked at admission | The digest is not signed by an accepted signer, or it has a fixable Critical and the deploy policy blocks it. | Run `frazer registry images describe` on the digest to see its signature and findings; rebuild on a fixed base image. |
| A push fails on storage | The project’s storage quota would be passed. The API reports `QUOTA_EXCEEDED`. | Run `frazer registry cleanup dry-run`, delete what you do not need, or request a higher quota from the link in the error. |
| A cleanup run stopped and asks for confirmation | The deletion guard: more than 20 % of the versions, or something pulled in the last 14 days. | Review the dry run, then confirm it, or change the policy. |
| A version was deleted by mistake | A cleanup policy removed it. | `frazer registry versions restore <repo>/<image>@<digest>` within 30 days. |
| New tags from Docker Hub do not arrive | The upstream rate-limits you or is down; cached tags keep serving. | Check the repository’s pull budget and tag refresh interval. |

## Reference

### CLI

| Command | What it does |
| --- | --- |
| `frazer auth configure-docker` | Install a Docker credential helper that signs in to Frazer Registry with a short-lived Frazer token. |
| `frazer registry repositories create` | Create a repository with its format, mode, immutable tags and, for a remote repository, its upstream and credential. |
| `frazer registry images list` | List an image's versions with their tags, scan results and signatures. |
| `frazer registry images describe` | Show one version by digest, its referrers and where it runs. |
| `frazer registry cleanup dry-run` | Show what a repository's cleanup policies would delete and why each version is kept. |
| `frazer registry versions restore` | Restore a deleted version within 30 days. |
| `frazer registry files push` | Push a versioned, immutable file to a Generic repository. |
| `frazer import start` | Start an import from another registry; with --dry-run, show the plan item by item. |
| `frazer import apply` | Apply an import's plan. |

All of them: [CLI reference](https://frazer.ai/docs/cli).

### MCP tools

| Tool | What it does |
| --- | --- |
| `registry` | Read repositories, images, versions, scan results and where each digest runs. Pushing stays with CI. |

All of them: [MCP tools reference](https://frazer.ai/docs/mcp).

### Events

| Event type | When it is sent |
| --- | --- |
| `frazer.image.pushed.v1` | A version was pushed to a repository. |
| `frazer.image.scan.completed.v1` | A version's vulnerability scan finished. |

All of them: [Events reference](https://frazer.ai/docs/webhooks).

## Related

-   [Environments and GitOps](https://frazer.ai/docs/gitops): roll a pushed digest out to a cluster.
-   [Secrets](https://frazer.ai/docs/secrets): where upstream and import credentials live.
-   [Kubernetes](https://frazer.ai/docs/kubernetes): clusters that admit only signed digests.
-   [GitHub runners](https://frazer.ai/docs/runners/github): CI that pushes with its own OIDC token.
-   [Security Center](https://frazer.ai/docs/security-center): findings for running images.
-   [Registry product page](https://frazer.ai/registry)

## Pages in Build and ship

- [Overview](https://frazer.ai/docs/source.md)
- [GitHub runners](https://frazer.ai/docs/runners/github.md)
- [Cache](https://frazer.ai/docs/cache.md)
- [Registry](https://frazer.ai/docs/registry.md) (this page)
- [Environments and GitOps](https://frazer.ai/docs/gitops.md)
- [Overview](https://frazer.ai/docs/previews.md)
