> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# State Store Systems

> Explains using OCI registries as unified state stores for GitOps, hosting images, Helm charts, manifests, and policies with examples and best practices.

A State Store System is the canonical source for the desired state of your system: configurations, application manifests, and infrastructure definitions. In GitOps workflows this authoritative state is most commonly a Git repository because Git provides provenance, immutability, branching, and pull requests for collaborative change management.

However, Git is not the only option. OCI (Open Container Initiative) registries can act as a unified state store for many artifact types used in Kubernetes ecosystems — container images, Helm charts, plain manifests, overlays, policy bundles, and more — letting you reuse the same registry, authentication, and access controls across those artifact types.

Why use OCI as a state store?

* Consolidates multiple artifact types into a single registry.
* Reuses existing authentication/authorization and lifecycle tooling.
* Enables GitOps operators (Flux, Argo CD) to pull artifacts from registries that support OCI artifacts.

OCI defines standards for container image formats and runtimes. The OCI Artifact model extends container images so registries can store arbitrary artifact types (images, Helm charts, manifest bundles, policies) as first-class artifacts.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/GVEyjNcGG4U_6mB_/images/Prep-Course-GitOps-Certified-Associate-CGOA/Tooling/State-Store-Systems/oci-artifacts-registry-diagram-explanation.jpg?fit=max&auto=format&n=GVEyjNcGG4U_6mB_&q=85&s=2d205d0c30dbb446c32ce536f1b3f1bb" alt="The image explains OCI Artifacts, showing how various data types like images, Helm charts, and Kubernetes manifests are stored and distributed using OCI registries. It includes a diagram illustrating the structure of a registry with different artifact versions." width="1920" height="1080" data-path="images/Prep-Course-GitOps-Certified-Associate-CGOA/Tooling/State-Store-Systems/oci-artifacts-registry-diagram-explanation.jpg" />
</Frame>

A single OCI registry can host multiple repositories; each repository can contain multiple artifacts and versions. Common OCI registry providers include GitHub Container Registry, Docker Hub, Azure Container Registry, and Google Artifact Registry.

Table: Typical storage locations vs. OCI as a consolidated option

|                   Resource type | Typical storage                                                    | OCI alternative                                        |
| ------------------------------: | ------------------------------------------------------------------ | ------------------------------------------------------ |
|                Container images | Container registries (e.g., [Docker Hub](https://hub.docker.com/)) | OCI registry repository (image manifests)              |
|                     Helm charts | Chart repositories or registries                                   | Helm charts stored as OCI artifacts                    |
| Kubernetes manifests / overlays | Git repositories (manifests, kustomize overlays)                   | Manifest bundles pushed as OCI artifacts (Flux/others) |
|      Policy bundles (e.g., OPA) | Policy stores / Git                                                | Policies packaged and stored as OCI artifacts          |

Callouts

<Callout icon="lightbulb" color="#1CB2FE">
  Using a single OCI registry for multiple artifact types simplifies access management: you can reuse the same credentials, RBAC rules, and audit trails for images, charts, and other artifacts.
</Callout>

<Callout icon="warning" color="#FF6B6B">
  Do not embed long-lived credentials in scripts. Prefer short-lived tokens, OIDC-based flows, or CI/CD secret managers. Always revoke or rotate Personal Access Tokens (PATs) used for registry access.
</Callout>

Below are practical examples showing how to push images, Helm charts, and plain Kubernetes manifests into an OCI-compliant registry. The examples use GitHub Container Registry (`ghcr.io`) but the commands and concepts apply to other OCI registries (Docker Hub, Azure Container Registry, Google Artifact Registry).

## Pushing container images to an OCI registry

Steps:

1. Authenticate to the registry (use a Personal Access Token or other secure credentials).
2. Tag the local image using the registry repository name.
3. Push the tagged image.

Example (replace `<<GITHUB_PERSONAL_ACCESS_TOKEN>>` with your token):

```bash theme={null}
# Log in (one-time per host/session)
$ docker login ghcr.io \
  --username sidd-harth \
  --password <<GITHUB_PERSONAL_ACCESS_TOKEN>>
Login Succeeded

# Confirm the local image (example: nginx)
$ docker images nginx
REPOSITORY   TAG       IMAGE ID    CREATED        SIZE
nginx        latest    8873639     8 days ago     142MB

# Tag the local image with your registry path and version
$ docker tag nginx ghcr.io/sidd-harth/nginx:1.1.0

# Push the image to the OCI registry
$ docker push ghcr.io/sidd-harth/nginx:1.1.0
6cffb086835: Pushed
2d75b87993c: Pushed
ec43a899918: Pushed
sha256:a4a4a4d...: digest: sha256:a4a4a4d... size: 1570
```

Once pushed, Kubernetes workloads (or other consumers) can pull the image using the `ghcr.io/sidd-harth/nginx:1.1.0` reference provided they have access.

## Pushing Helm charts to an OCI registry

Modern Helm supports saving and pushing charts as OCI artifacts. Typical flow:

1. Create or have a chart (e.g., `helm create app1`).
2. Package the chart as a `.tgz`.
3. Login to the registry with Helm.
4. Save/push the chart as an OCI artifact.

Example (replace `<<GITHUB_PERSONAL_ACCESS_TOKEN>>` with your token):

```bash theme={null}
# Create a chart scaffold
$ helm create app1
Creating app1

# Package the chart to a tgz
$ helm package app1
Successfully packaged chart and saved it to: ./app1-1.0.0.tgz

# Login to the registry using Helm
$ helm registry login ghcr.io \
  --username sidd-harth \
  --password <<GITHUB_PERSONAL_ACCESS_TOKEN>>
Login Succeeded

# Save and push the chart as an OCI artifact (Helm >=3.7+)
$ helm chart save ./app1-1.0.0.tgz ghcr.io/sidd-harth/app1:1.0.0
$ helm chart push ghcr.io/sidd-harth/app1:1.0.0
Pushed: ghcr.io/sidd-harth/app1:1.0.0
Digest: sha256:81de917eaf38356b1145bdde2984dc2fdf14...
```

After pushing, consumers can pull the chart directly from the OCI registry using Helm's OCI registry support.

## Publishing plain Kubernetes manifests to an OCI registry (using Flux)

You can package a directory of Kubernetes manifests and push it as an OCI artifact. Flux provides `flux push artifact` to create a manifest bundle and push it to an OCI registry; a GitOps operator can then reference that bundle.

Example using Flux (replace `<<GITHUB_PERSONAL_ACCESS_TOKEN>>` with your token):

```bash theme={null}
# Ensure Docker login (if your registry requires it)
$ docker login ghcr.io \
  --username sidd-harth \
  --password <<GITHUB_PERSONAL_ACCESS_TOKEN>>
Login Succeeded

# Example manifests tree
$ tree nginx/
nginx/
└── manifests
    ├── deployment.yaml
    └── service.yaml

# Push manifests as an OCI artifact with Flux
$ flux push artifact oci://ghcr.io/sidd-harth/nginx-2:$(git rev-parse --short HEAD) \
  --path="./nginx/manifests/" \
  --source="$(git config --get remote.origin.url)" \
  --revision="$(git branch --show-current)/$(git rev-parse HEAD)"
pushing to ghcr.io/sidd-harth/nginx-2:1b31558
artifact successfully pushed to ghcr.io/sidd-harth/nginx-2@sha256:235b486df4a38f0151...
```

Once the manifest bundle is published, configure your GitOps operator (e.g., Flux or Argo CD) to reference the OCI artifact location and reconciliation will apply those manifests to your cluster.

## How GitOps operators consume OCI artifacts

* Argo CD and Flux both support pulling from OCI registries:
  * Argo CD: supports OCI images and some extensions for OCI-based applications.
  * Flux: has first-class support for `Kustomization`/`HelmRepository` using `oci://` sources and `flux push artifact`.
* Typical operator flow: fetch OCI artifact → verify digest/revision → render/apply manifests or charts → report status.

## Registry examples and links

| Provider                                                                                                                                               | Notes                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- |
| [GitHub Container Registry (ghcr.io)](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) | Supports OCI artifacts and fine-grained permissions |
| [Docker Hub](https://hub.docker.com/)                                                                                                                  | Popular image registry with OCI support             |
| [Azure Container Registry](https://learn.microsoft.com/en-us/azure/container-registry/)                                                                | Enterprise-grade registry with RBAC and ACR Tasks   |
| [Google Artifact Registry](https://cloud.google.com/artifact-registry)                                                                                 | Supports multiple artifact formats including OCI    |

## Best practices

* Consolidate related artifacts under predictable repository paths (e.g., `ghcr.io/<org>/<app>`).
* Use image and artifact digests (sha256) in production manifests to guarantee immutability.
* Use short-lived credentials or OIDC where possible; avoid embedding PATs in long-lived scripts.
* Apply RBAC and least privilege on the registry to limit artifact access.

## References

* [Open Container Initiative (OCI)](https://opencontainers.org/)
* [Helm documentation](https://helm.sh/)
* [FluxCD documentation](https://fluxcd.io/)
* [Argo CD documentation](https://argo-cd.readthedocs.io/en/stable/)

That's all for this lesson.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/gitops-certified-associate-cgoa/module/24630e6a-9f49-42d1-abd0-75bafc02ce01/lesson/f1ba2352-52cb-4d07-868d-026818023a60" />
</CardGroup>
