Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 36 additions & 56 deletions docs/getting-started/try-it-out/on-managed-kubernetes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -381,86 +381,66 @@ kubectl logs -n openchoreo-data-plane -l app=cluster-agent --tail=10

## Step 3: Setup Build Plane (Optional)

The Build Plane enables OpenChoreo's built-in CI capabilities. It runs Argo Workflows and hosts a container registry for your built images.
The Build Plane runs Argo Workflows to build container images from your source code. You need a container registry to store built images.

**Create Namespace**
<Tabs groupId="registry-type">
<TabItem value="ttl-sh" label="ttl.sh (Easiest)" default>

[ttl.sh](https://ttl.sh) is a free, anonymous registry. Images expire after 24 hours. No setup required.

```bash
kubectl create namespace openchoreo-build-plane --dry-run=client -o yaml | kubectl apply -f -
export REGISTRY_PREFIX=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-z0-9' | fold -w 8 | head -n 1)
echo "Your registry prefix: $REGISTRY_PREFIX"
```

**Configure TLS**
<CodeBlock language="bash">
{`helm upgrade --install openchoreo-build-plane ${versions.helmSource}/openchoreo-build-plane \\
--version ${versions.helmChart} \\
--namespace openchoreo-build-plane \\
--create-namespace \\
--set external-secrets.enabled=false \\
--set global.defaultResources.registry.host=ttl.sh \\
--set global.defaultResources.registry.repoPath=$REGISTRY_PREFIX \\
--set global.defaultResources.registry.tlsVerify=true`}
</CodeBlock>

```bash
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-http01
namespace: openchoreo-build-plane
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: tryout@openchoreo.dev
privateKeySecretRef:
name: letsencrypt-http01
solvers:
- http01:
gatewayHTTPRoute:
parentRefs:
- name: gateway-default
namespace: openchoreo-control-plane
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: registry-tls
namespace: openchoreo-build-plane
spec:
secretName: registry-tls
issuerRef:
name: letsencrypt-http01
kind: Issuer
dnsNames:
- "registry.${CP_DOMAIN}"
EOF
```
:::note
Images on ttl.sh expire after 24 hours. For production, use your cloud provider's registry (ECR, GCR, ACR). See [Container Registry Configuration](../../operations/container-registry-configuration.mdx).
:::

Wait for certificate:
</TabItem>
<TabItem value="cloud-registry" label="Cloud Provider Registry">

```bash
kubectl get certificate registry-tls -n openchoreo-build-plane -w
```
For production deployments, use your cloud provider's container registry:

- **AWS EKS**: Amazon ECR
- **GCP GKE**: Google Artifact Registry
- **Azure AKS**: Azure Container Registry

**Install**
See [Container Registry Configuration](../../operations/container-registry-configuration.mdx) for detailed setup instructions.

**Example with ECR:**

<CodeBlock language="bash">
{`helm upgrade --install openchoreo-build-plane ${versions.helmSource}/openchoreo-build-plane \\
--version ${versions.helmChart} \\
--namespace openchoreo-build-plane \\
--create-namespace \\
--set clusterAgent.enabled=true \\
--set global.baseDomain=\${CP_DOMAIN} \\
--set global.tls.enabled=true \\
--set global.tls.secretName=registry-tls \\
--set external-secrets.enabled=false`}
--set external-secrets.enabled=false \\
--set global.defaultResources.registry.host=123456789.dkr.ecr.us-east-1.amazonaws.com \\
--set global.defaultResources.registry.repoPath=openchoreo-builds \\
--set global.defaultResources.registry.tlsVerify=true`}
</CodeBlock>

This installs the build plane with these settings:

- `global.baseDomain`: used to construct the registry URL at `registry.<baseDomain>`.
- `global.tls.enabled` and `global.tls.secretName`: enables TLS for the registry using the Let's Encrypt certificate.
- `clusterAgent.enabled`: enables the cluster-agent for communication with the control plane.
</TabItem>
</Tabs>

This installs:

- `cluster-agent`: connects to the control plane to receive build instructions.
- `argo-workflows`: executes the actual build pipelines as Kubernetes workflows.
- `registry`: a container registry that stores your built images.
- Argo Workflows CRDs: Workflow, WorkflowTemplate, and other resources for defining build pipelines.

Like the data plane, the build plane could run in a completely separate cluster if you wanted to isolate your CI workloads.

For all available configuration options, see the [Build Plane Helm Reference](../../reference/helm/build-plane.mdx).

**Register with the Control Plane**
Expand Down
99 changes: 70 additions & 29 deletions docs/getting-started/try-it-out/on-self-hosted-kubernetes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -341,69 +341,110 @@ kubectl logs -n openchoreo-data-plane -l app=cluster-agent --tail=10

## Step 3: Setup Build Plane (Optional)

The Build Plane enables OpenChoreo's built-in CI capabilities. It runs Argo Workflows and hosts a container registry for your built images.
The Build Plane runs Argo Workflows to build container images from your source code. You need a container registry to store built images.

<Tabs groupId="cluster-type">
<TabItem value="k3d" label="k3d" default>

Install a container registry in your cluster:

```bash
helm repo add twuni https://helm.twun.io
helm repo update

helm install registry twuni/docker-registry \
--namespace openchoreo-build-plane \
--create-namespace \
--set persistence.enabled=true \
--set persistence.size=10Gi \
--set service.type=ClusterIP
```

Wait for the registry to be ready:

```bash
kubectl wait --for=condition=available deployment/registry-docker-registry -n openchoreo-build-plane --timeout=120s
```

<CodeBlock language="bash">
{`helm upgrade --install openchoreo-build-plane ${versions.helmSource}/openchoreo-build-plane \\
--version ${versions.helmChart} \\
--namespace openchoreo-build-plane \\
--create-namespace \\
--set external-secrets.enabled=false \\
--set global.defaultResources.registry.endpoint=host.k3d.internal:10082 \\
--set registry.service.type=LoadBalancer`}
--set global.defaultResources.registry.host=registry-docker-registry.openchoreo-build-plane.svc.cluster.local:5000 \\
--set global.defaultResources.registry.tlsVerify=false`}
</CodeBlock>

This installs the build plane with these settings:
</TabItem>
<TabItem value="existing" label="Existing Cluster">

- `global.defaultResources.registry.endpoint`: the address where built images are pushed and pulled. `host.k3d.internal` is a special hostname that k3d nodes can resolve to the host machine.
- `registry.service.type`: exposes the registry via LoadBalancer so it's accessible from outside the cluster.
Choose a registry option:

This installs:
<Tabs groupId="registry-type">
<TabItem value="ttl-sh" label="ttl.sh (Easiest)" default>

- `cluster-agent`: connects to the control plane to receive build instructions.
- `argo-workflows`: executes the actual build pipelines as Kubernetes workflows.
- `registry`: a container registry that stores your built images.
- Argo Workflows CRDs: Workflow, WorkflowTemplate, and other resources for defining build pipelines.
[ttl.sh](https://ttl.sh) is a free, anonymous registry. Images expire after 24 hours. No setup required.

For all available configuration options, see the [Build Plane Helm Reference](../../reference/helm/build-plane.mdx).
```bash
export REGISTRY_PREFIX=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-z0-9' | fold -w 8 | head -n 1)
echo "Your registry prefix: $REGISTRY_PREFIX"
```

<CodeBlock language="bash">
{`helm upgrade --install openchoreo-build-plane ${versions.helmSource}/openchoreo-build-plane \\
--version ${versions.helmChart} \\
--namespace openchoreo-build-plane \\
--create-namespace \\
--set external-secrets.enabled=false \\
--set global.defaultResources.registry.host=ttl.sh \\
--set global.defaultResources.registry.repoPath=$REGISTRY_PREFIX \\
--set global.defaultResources.registry.tlsVerify=true`}
</CodeBlock>

:::note
Images on ttl.sh expire after 24 hours. For persistent storage, use the host registry option or a cloud provider registry.
:::

</TabItem>
<TabItem value="existing" label="Existing Cluster">
<TabItem value="host-registry" label="Host Registry">

Run a registry on your host machine using Docker. This works well when your cluster can reach the host via `host.docker.internal`.

```bash
docker run -d --name registry -p 5050:5000 registry:3
```

:::note HTTP Registry Access
Configure your container runtime to allow this insecure registry. For Rancher Desktop, see [Configuring Private Registries](https://docs.rancherdesktop.io/how-to-guides/mirror-private-registry/).
:::

<CodeBlock language="bash">
{`helm upgrade --install openchoreo-build-plane ${versions.helmSource}/openchoreo-build-plane \\
--version ${versions.helmChart} \\
--namespace openchoreo-build-plane \\
--create-namespace \\
--set external-secrets.enabled=false \\
--set global.defaultResources.registry.endpoint=<REGISTRY_ENDPOINT> \\
--set registry.service.type=LoadBalancer \\
--set registry.service.port=10082`}
--set global.defaultResources.registry.host=host.docker.internal:5050 \\
--set global.defaultResources.registry.tlsVerify=false`}
</CodeBlock>

This installs the build plane with these settings:
:::tip
If `host.docker.internal` doesn't resolve in your cluster, use your machine's IP address instead.
:::

- `global.defaultResources.registry.endpoint`: the address where built images are pushed and pulled. This needs to be accessible from both the build pods (for pushing) and the kubelet (for pulling). Common values are `host.docker.internal:10082` or your node's IP address.
- `registry.service.type` and `registry.service.port`: exposes the registry via LoadBalancer.
</TabItem>
</Tabs>

</TabItem>
</Tabs>

This installs:

- `cluster-agent`: connects to the control plane to receive build instructions.
- `argo-workflows`: executes the actual build pipelines as Kubernetes workflows.
- `registry`: a container registry that stores your built images.
- Argo Workflows CRDs: Workflow, WorkflowTemplate, and other resources for defining build pipelines.

For all available configuration options, see the [Build Plane Helm Reference](../../reference/helm/build-plane.mdx).

:::note HTTP Registry Access
The Build Plane deploys an HTTP container registry. Container runtimes default to HTTPS for registries. If image pulls fail with "http: server gave HTTP response to HTTPS client", configure your container runtime to allow HTTP for this registry. For Rancher Desktop users, see [Configuring Private Registries](https://docs.rancherdesktop.io/how-to-guides/mirror-private-registry/).
:::

</TabItem>
</Tabs>
For all available configuration options, see the [Build Plane Helm Reference](../../reference/helm/build-plane.mdx). For production deployments, see [Container Registry Configuration](../../operations/container-registry-configuration.mdx).

**Register with the Control Plane**

Expand Down
104 changes: 104 additions & 0 deletions docs/operations/container-registry-configuration.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
title: Container Registry Configuration
description: Configure the Build Plane to push images to your container registry.
sidebar_position: 3
---

# Container Registry Configuration

The Build Plane requires a container registry to store built images. Both build pods (for pushing) and kubelets on the Data Plane (for pulling) need access to the registry.

## Configuration Parameters

| Parameter | Description | Required |
|-----------|-------------|----------|
| `global.defaultResources.registry.host` | Registry hostname | Yes |
| `global.defaultResources.registry.repoPath` | Path prefix for images | No |
| `global.defaultResources.registry.tlsVerify` | Verify TLS certificates | No (default: `false`) |

## Registry Providers

### Amazon ECR

See [Amazon ECR documentation](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html) for repository setup and IAM configuration.

```bash
helm upgrade --install openchoreo-build-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-build-plane \
--namespace openchoreo-build-plane \
--set global.defaultResources.registry.host=123456789.dkr.ecr.us-east-1.amazonaws.com \
--set global.defaultResources.registry.repoPath=openchoreo-builds \
--set global.defaultResources.registry.tlsVerify=true
```

### Google Artifact Registry

See [Artifact Registry documentation](https://cloud.google.com/artifact-registry/docs/docker/store-docker-container-images) for repository setup and authentication.

```bash
helm upgrade --install openchoreo-build-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-build-plane \
--namespace openchoreo-build-plane \
--set global.defaultResources.registry.host=us-central1-docker.pkg.dev/my-project/openchoreo-builds \
--set global.defaultResources.registry.tlsVerify=true
```

### Azure Container Registry

See [ACR documentation](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-get-started-azure-cli) for registry setup and AKS integration.

```bash
helm upgrade --install openchoreo-build-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-build-plane \
--namespace openchoreo-build-plane \
--set global.defaultResources.registry.host=myregistry.azurecr.io \
--set global.defaultResources.registry.tlsVerify=true
```

### GitHub Container Registry

See [GHCR documentation](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) for authentication setup.

```bash
helm upgrade --install openchoreo-build-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-build-plane \
--namespace openchoreo-build-plane \
--set global.defaultResources.registry.host=ghcr.io \
--set global.defaultResources.registry.repoPath=my-org/openchoreo \
--set global.defaultResources.registry.tlsVerify=true
```

### Docker Hub

See [Docker Hub documentation](https://docs.docker.com/docker-hub/repos/create/) for repository setup. Note the [rate limits](https://docs.docker.com/docker-hub/download-rate-limit/) for free accounts.

```bash
helm upgrade --install openchoreo-build-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-build-plane \
--namespace openchoreo-build-plane \
--set global.defaultResources.registry.host=docker.io \
--set global.defaultResources.registry.repoPath=your-username \
--set global.defaultResources.registry.tlsVerify=true
```

## Authentication

### Push Secret (Build Plane)

For registries requiring authentication, create a secret in the build plane namespace:

```bash
kubectl create secret docker-registry registry-push-secret \
--namespace openchoreo-build-plane \
--docker-server=REGISTRY_HOST \
--docker-username=USERNAME \
--docker-password=PASSWORD
```

### Pull Secret (Data Plane)

For pulling images from private registries, see [Deploy from a Private Registry](../use-cases/deploy-prebuilt-image.mdx#deploy-from-a-private-registry).

## Troubleshooting

| Symptom | Check |
|---------|-------|
| "unauthorized" error | Verify `registry-push-secret` exists and credentials are valid |
| `ImagePullBackOff` | Verify image exists and ImagePullSecret is configured |
| "x509: certificate signed by unknown authority" | Set `tlsVerify=false` or configure CA certificate |
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The troubleshooting advice for the "x509: certificate signed by unknown authority" error suggests setting tlsVerify=false, which disables TLS certificate verification for registry access. Using this workaround with external registries on untrusted networks allows man-in-the-middle attackers to impersonate the registry and serve malicious images that the platform will build and deploy. Prefer guidance that keeps tlsVerify=true and instructs operators to fix the certificate chain or configure the appropriate CA trust, reserving tlsVerify=false strictly for ephemeral local development.

Copilot uses AI. Check for mistakes.
| "connection refused" | Check network connectivity and firewall rules |
Loading
Loading