Cluster Patterns
Four common ways to use hyve, from a laptop to a fully pipeline-driven setup. They combine: a typical path is to create a host cluster once (pattern 3 or 4), then create everything else through it (pattern 1 or 2 in cluster mode).
| Locally | Through a pipeline | |
|---|---|---|
| Clusters | 1. Clusters locally | 2. Clusters through pipelines |
| Host clusters (running hyve itself) | 3. Host clusters locally | 4. Host clusters through pipelines |
A host cluster is a cluster that runs hyve’s own controller + API (cluster mode). Every other cluster is just a cluster hyve manages.
1. Creating clusters locally
Local mode — a directory on your machine
No server needed. Hyve reads and writes plain YAML in a context directory and provisions from your machine with your own credentials.
hyve context create my-infra --path ~/repos/my-infrahyve module add github.com/cbridges1/hyve-civo-moduleexport CIVO_TOKEN=... # whatever the module needs
hyve cluster create dev --template civo --set node_count=2 # writes clusters/dev.yamlhyve reconcile # provisions ithyve cluster auth dev # merges its kubeconfigkubectl get nodes
# Optional: if the directory is a git checkout, commit the result yourselfgit add clusters cluster-state && git commit -m "Add dev" && git pushDelete by marking it and reconciling again: hyve cluster delete dev && hyve reconcile.
Cluster mode — against a hyve-api server
When a host cluster already runs hyve, the CLI talks to its API and the controller does the provisioning.
hyve context login --api-url https://hyve.example.comhyve organization use acme # which organization (if you're in several)hyve environment use staging # which environment new clusters land inhyve cluster create dev --file clusters/dev.yamlhyve cluster logs dev # watch the controller create ithyve cluster auth devThe web console at the same URL does the same thing.
2. Creating clusters through pipelines
Local mode — GitOps from a state repository
The state repository holds clusters/, templates/, workflows/, and a hyve.yaml with reconcile.mode: cicd (so a local hyve reconcile only validates). The pipeline provisions with hyve reconcile --path . and then commits the results back itself — hyve never commits or pushes.
This workflow_dispatch pipeline creates or deletes a cluster from a template on demand:
name: Cluster lifecycleon: workflow_dispatch: inputs: action: { type: choice, options: [create, delete], required: true } cluster: { type: string, required: true } template: { type: string, required: false } params: { type: string, required: false, description: "KEY=VALUE, one per line" }
concurrency: { group: hyve-reconcile, cancel-in-progress: false }
jobs: lifecycle: runs-on: ubuntu-latest permissions: { contents: write } steps: - uses: actions/checkout@v4
- uses: actions/setup-go@v5 with: go-version: "1.26"
- name: Install hyve run: | go install github.com/cbridges1/hyve@latest echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
- name: Register a context for this checkout run: hyve context create ci --path .
- name: Create or mark for deletion run: | if [ "${{ inputs.action }}" = create ]; then args="" while IFS= read -r kv; do [ -n "$kv" ] && args="$args --set $kv"; done <<< "${{ inputs.params }}" hyve cluster create "${{ inputs.cluster }}" --template "${{ inputs.template }}" $args else hyve cluster delete "${{ inputs.cluster }}" fi
- name: Reconcile env: CIVO_TOKEN: ${{ secrets.CIVO_TOKEN }} # whatever your modules and workflows need run: hyve reconcile --path .
- name: Commit and push state if: always() run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add -A clusters cluster-state git diff --cached --quiet || { git commit -m "hyve: ${{ inputs.action }} ${{ inputs.cluster }}" && git push; }For continuous GitOps instead, trigger the same reconcile + commit steps on push to clusters/** and on a schedule (drift correction and expiresAt cleanup). See CI/CD.
Cluster mode — a pipeline that talks to hyve-api
The pipeline doesn’t provision anything itself — it hands definitions to hyve-api and the host’s controller does the rest. Create a dedicated account for it once:
kubectl -n hyve-system exec deploy/hyve-api -- \ hyve cluster-config api create-user ci-bot --role admin --namespace acme --password "$CI_PASSWORD" - name: Push new cluster definitions to hyve-api env: HYVE_CI_PASSWORD: ${{ secrets.HYVE_CI_PASSWORD }} run: | hyve context login --api-url https://hyve.example.com --org acme \ --username ci-bot --password "$HYVE_CI_PASSWORD" hyve migrate --dir . --write --env production # creates anything not there yet3. Creating host clusters locally
For development — k3d on your machine
From a hyve checkout, two tasks give you a local host cluster running your working copy of hyve, with the API and web console at http://hyve-api.127.0.0.1.nip.io:
task cluster:local # k3d cluster with host ports 80/443 mapped to its ingresstask install:local # build the image, import it, apply CRDs, helm install, ingresskubectl exec -n hyve-system deploy/hyve-api -- \ hyve cluster-config api create-user admin --role superadmin --namespace hyve-systemhyve context login --api-url http://hyve-api.127.0.0.1.nip.ioSet HYVE_INSTALL_MULTI_TENANT=true before install:local to serve several organizations from it.
For real — provision it with hyve, then install hyve on it
Use local mode to create the cluster, then install the chart onto it:
# 1. Provision the host like any other clusterhyve context use my-infrahyve cluster create home --template unraid-k3shyve reconcilehyve cluster auth home
# 2. Install hyve onto it (from a hyve checkout)kubectl --context home apply -f deploy/helm/hyve/crds/helm upgrade --install hyve deploy/helm/hyve --kube-context home \ --namespace hyve-system --create-namespace \ --set image.repository=ghcr.io/cbridges1/hyve --set image.tag=<version> \ --set api.publicBaseURL=https://hyve.example.com \ --set api.multiTenant.enabled=true
# 3. Expose hyve-api (Service hyve-api, port 80) — Ingress, LoadBalancer, or a tunnel# — then create the first superadmin and log inkubectl --context home -n hyve-system exec deploy/hyve-api -- \ hyve cluster-config api create-user admin --role superadmin --namespace hyve-systemhyve context login --api-url https://hyve.example.com
# 4. Optional: hand your local definitions over to the new hosthyve migrate to-cluster --to-cluster home --writeMark the host’s own definition with spec.access.method: primary so hyve knows it’s the host (see The host cluster). Because it keeps its real spec.driver, it’s still authenticated to through that driver like any other cluster.
4. Creating host clusters through pipelines
Put the hyve install into the host’s template, as an afterCreate workflow, so the pipeline in pattern 2 creates a working host with no manual steps:
apiVersion: hyve.io/v1alpha1kind: Templatemetadata: name: hyve-hostspec: driver: source: github.com/cbridges1/hyve-unraid-k3s-module version: latest params: ip_address: 192.168.50.100 access: method: primary # marks clusters from this template as the host workflows: afterCreate: - name: install-hyveapiVersion: hyve.io/v1alpha1kind: Workflowmetadata: name: install-hyvespec: description: Install hyve's controller + API onto a freshly created host cluster. requirements: tools: - name: kubectl - name: helm - name: git secrets: - name: HYVE_ADMIN_PASSWORD required: true description: Password for the first superadmin account jobs: - name: install steps: - name: chart-and-crds script: | set -e rm -rf /tmp/hyve-src git clone --depth 1 https://github.com/cbridges1/hyve.git /tmp/hyve-src kubectl apply -f /tmp/hyve-src/deploy/helm/hyve/crds/ helm upgrade --install hyve /tmp/hyve-src/deploy/helm/hyve \ --namespace hyve-system --create-namespace \ --set image.repository=ghcr.io/cbridges1/hyve --set image.tag=latest \ --set api.publicBaseURL=https://hyve.example.com \ --set api.multiTenant.enabled=true \ --wait --timeout 5m - name: first-superadmin dependsOn: ["chart-and-crds"] script: | kubectl -n hyve-system exec deploy/hyve-api -- \ hyve cluster-config api create-user admin --role superadmin \ --namespace hyve-system --password "$HYVE_ADMIN_PASSWORD"Then dispatch the lifecycle pipeline with action: create, template: hyve-host, and HYVE_ADMIN_PASSWORD (plus the module’s own credentials) in the reconcile step’s env:. Expose hyve-api the same way as in pattern 3 — a tunnel resource can go straight into the template’s spec.resources, ordered after whatever installs the tunnel operator.