Evaluate Brokkr Locally
This page gets you from zero to a working Brokkr deployment fast, so you can decide whether it fits your needs. It offers two paths — pick one:
- Path A — Fastest look — one command builds the stack from source and bundles its own Kubernetes (k3s); nothing to install but Docker.
- Path B — Realistic evaluation — Helm installs the published images onto a local cluster you bring yourself (kind or k3d); no source build.
Both paths end with an agent reconciling a real Kubernetes resource onto a cluster.
Along the way you will meet Brokkr’s five nouns — generator, agent, stack, deployment object, and target. You can follow either path without knowing them, since every command below says what it is doing, but if you would rather have the model first, read Core Concepts — it takes a few minutes and makes the rest of the book easier to navigate.
Path A — Fastest look (angreal local up)
Section titled “Path A — Fastest look (angreal local up)”This path builds Brokkr from source and runs the full broker + agent + k3s + local registry stack in Docker. It is the quickest way to a working playground, building container images from the repo.
Prerequisites
Section titled “Prerequisites”Install the tools in Prerequisites: To evaluate with angreal local up.
The first angreal local up compiles the broker and agent from source — usually 5–15 minutes depending on your machine and Docker cache. Docker streams the build output to your terminal as it works, so you can watch it make progress (subsequent runs are much faster once layers are cached).
1. Clone and start the stack
Section titled “1. Clone and start the stack”One command brings up every backing service.
git clone https://github.com/colliery-io/brokkr.gitcd brokkrangreal local upThis starts the brokkr-dev Docker Compose project: PostgreSQL, a local container registry, the broker, a k3s cluster (with Tekton + Shipwright), a pre-created agent, and a couple of demo containers. The first run builds images from your working tree, so give it a few minutes.
When it finishes, the command prints the URLs (the broker API and the operator console on http://localhost:3000), the dev admin PAK, and the path of the dev agent’s key. The stack has already created an agent named brokkr-integration-test-agent (cluster brokkr-dev-integration-cluster) and started an agent container for it. A second angreal local up keeps that agent, its PAK and its registrations.
If
angreal local upfails: make sure Docker is running and you have enough free disk for the source build, and that ports3000,3001,5050,5433,6443,8474and18090aren’t already in use (angreal local upnames the service that could not bind; for the webhook catcher, setBROKKR_DEV_WEBHOOK_PORTto a free port). To start clean, runangreal local down --hard(removes volumes) and try again. The same stack is documented in more depth in Local Development Environment.
2. Set your admin key and confirm the broker is up
Section titled “2. Set your admin key and confirm the broker is up”The dev broker runs with the default configuration, so the publicly known dev admin PAK (Prefixed API Key) works against it — fine for this throwaway environment, never for production.
export ADMIN_PAK="brokkr_BR3rVsDa_GK3QN7CDUzYc6iKgMkJ98M2WSimM5t6U8"
# The brokkr CLI reads its connection from these two variablesexport BROKKR_BROKER_URL=http://localhost:3000export BROKKR_PAK=$ADMIN_PAK
# Confirm the broker is healthycurl http://localhost:3000/healthz3. See your agent
Section titled “3. See your agent”List registered agents — the pre-created agent should already be there.
brokkr agent listYou should see brokkr-integration-test-agent. A freshly registered agent starts with status INACTIVE. While it is INACTIVE, the agent does not ask the broker for deployment objects. The agent checks its own status: the broker does not stop the work (see Agent Status Is Not an Access Control). Until you mark it ACTIVE, the agent log says so on each poll. Activate it:
# Activate the agent so it will pull and reconcile deployment objectsbrokkr agent activate brokkr-integration-test-agentThe output should say that the agent is ACTIVE, meaning the agent will pull and reconcile what you target to it.
The same step with curl
curl -s http://localhost:3000/api/v1/agents \ -H "Authorization: Bearer $ADMIN_PAK" | jq '.[] | {id, name, cluster_name, status}'
export AGENT_ID=$(curl -s http://localhost:3000/api/v1/agents \ -H "Authorization: Bearer $ADMIN_PAK" \ | jq -r '.[] | select(.name=="brokkr-integration-test-agent") | .id')
curl -s -X PUT http://localhost:3000/api/v1/agents/$AGENT_ID \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"status": "ACTIVE"}' | jq '{name, status}'4. Deploy something and watch it reconcile
Section titled “4. Deploy something and watch it reconcile”Create a stack, target your agent to it, and push a namespace. Stacks are owned by a generator; the broker creates an admin-generator at first startup.
# Look up the admin generator and create a stack owned by itGEN_ID=$(curl -s http://localhost:3000/api/v1/generators \ -H "Authorization: Bearer $ADMIN_PAK" \ | jq -r '.[] | select(.name=="admin-generator") | .id')
STACK_ID=$(curl -s -X POST http://localhost:3000/api/v1/stacks \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d "{\"name\": \"evaluate\", \"description\": \"Evaluation stack\", \"generator_id\": \"$GEN_ID\"}" \ | jq -r '.id')
# Register the agent with the admin-generator. An agent must be registered with a# generator before any stack that generator owns can be targeted at it — without# this, the next command fails with agent_not_registered. Give each one by name.brokkr register --agent brokkr-integration-test-agent --generator admin-generator
# Now target the stack at the agent so the agent receives the deployment.brokkr stack target evaluate brokkr-integration-test-agent
# Push a deployment object (a single namespace)curl -s -X POST "http://localhost:3000/api/v1/stacks/$STACK_ID/deployment-objects" \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"yaml_content": "apiVersion: v1\nkind: Namespace\nmetadata:\n name: brokkr-evaluate", "is_deletion_marker": false}'The register and target steps with curl
curl -s -X POST http://localhost:3000/api/v1/generators/$GEN_ID/register \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d "{\"agent_id\": \"$AGENT_ID\"}"
# The body `agent_id` must match the agent id in the path. The broker rejects a mismatch with 400.curl -s -X POST http://localhost:3000/api/v1/agents/$AGENT_ID/targets \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d "{\"agent_id\": \"$AGENT_ID\", \"stack_id\": \"$STACK_ID\"}"The agent polls the broker on its next cycle and applies the namespace — allow one full poll cycle (about 10 seconds in this stack). Point kubectl at the bundled k3s cluster (its host kubeconfig is written to /tmp/brokkr-keys/) and verify:
export KUBECONFIG=/tmp/brokkr-keys/kubeconfig.local.yaml
# Visible result: the namespace your agent reconciled onto the clusterkubectl get namespace brokkr-evaluateOnce brokkr-evaluate shows up, you have seen the full loop: an API call to the broker, an agent picking it up, and a real resource on a cluster.
Optional: look at the demo UI
Section titled “Optional: look at the demo UI”The stack also serves a demo admin UI at http://localhost:3001 (from examples/ui-slim) — a demonstration of what a consumer could build on the API, not a supported product. Open it for a visual feel, but drive your actual evaluation through the API or the brokkr CLI.
Tear down
Section titled “Tear down”angreal local down # stop the stackangreal local down --hard # stop and remove volumesPath B — Realistic evaluation (Helm on a local cluster)
Section titled “Path B — Realistic evaluation (Helm on a local cluster)”This path installs the published images with Helm onto a local Kubernetes cluster — no source build. It mirrors a real install closely enough to evaluate operational behavior.
Prerequisites
Section titled “Prerequisites”Install the tools in Prerequisites: To evaluate or install with Helm. You create the local cluster in the next step.
1. Create a local cluster
Section titled “1. Create a local cluster”Use whichever tool you have. For example, with kind:
kind create cluster --name brokkr-evalOr with k3d:
k3d cluster create brokkr-evalConfirm kubectl is pointed at it:
kubectl cluster-info2. Install the broker
Section titled “2. Install the broker”Install the broker chart with bundled PostgreSQL. The chart pulls the published brokkr-broker image.
Warning: This evaluation install does not set an admin PAK hash. Thus the broker uses the publicly known development admin PAK. Anyone who can reach this broker can use that PAK as admin. Use this install only on a local cluster that nobody else can reach. Do not expose the broker with an Ingress, a LoadBalancer, or a port-forward on a shared host. A restart does not replace the development PAK. For any other install, follow Installing Brokkr, which sets your own hash before the first startup.
helm install brokkr-broker oci://ghcr.io/colliery-io/charts/brokkr-broker \ --set postgresql.enabled=true \ --wait
# Verify the broker is runningkubectl get pods -l app.kubernetes.io/name=brokkr-broker3. Reach the broker and set your admin key
Section titled “3. Reach the broker and set your admin key”Port-forward the broker, then export the publicly known development admin PAK. It works because the install in step 2 set no hash. It is acceptable only for this throwaway evaluation cluster, never for production.
This port-forward must stay running for every remaining step — leave it in this shell (or its own terminal) until teardown.
kubectl port-forward svc/brokkr-broker 3000:3000 &
export ADMIN_PAK="brokkr_BR3rVsDa_GK3QN7CDUzYc6iKgMkJ98M2WSimM5t6U8"
# The brokkr CLI reads its connection from these two variablesexport BROKKR_BROKER_URL=http://localhost:3000export BROKKR_PAK=$ADMIN_PAK
# Confirm the broker answerscurl http://localhost:3000/api/v1/agents -H "Authorization: Bearer $ADMIN_PAK"4. Create an agent and capture its PAK
Section titled “4. Create an agent and capture its PAK”The agent authenticates to the broker with its own one-time PAK.
export AGENT_PAK=$(curl -s -X POST http://localhost:3000/api/v1/agents \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"name": "eval-agent", "cluster_name": "evaluation"}' \ | jq -r '.initial_pak')
echo "$AGENT_PAK" # shown only once5. Install the agent
Section titled “5. Install the agent”Install the agent chart with the PAK from the previous step. The broker.agentName and broker.clusterName values must exactly match the agent you created in step 4 (eval-agent / evaluation) — at startup the agent looks up its own registration by that pair, and a mismatch leaves the pod crashlooping with “Agent not found”.
Warning: the default agent install changes the whole cluster. With the chart defaults, a pre-install hook Job installs Tekton Pipelines and Shipwright Build cluster-wide. The Job runs under a ServiceAccount with a
cluster-adminClusterRoleBinding.helm uninstalldoes not remove Tekton or Shipwright. This evaluation does not use build work orders, so the command below setsshipwright.enabled=false. To try builds, remove that line. If Tekton and Shipwright are already in the cluster, use--set shipwright.install.tekton=false --set shipwright.install.shipwright=falseinstead. For the full list of effects, see What a Default Install Does to Your Cluster.
helm install brokkr-agent oci://ghcr.io/colliery-io/charts/brokkr-agent \ --set broker.url=http://brokkr-broker:3000 \ --set broker.pak="$AGENT_PAK" \ --set broker.agentName=eval-agent \ --set broker.clusterName=evaluation \ --set shipwright.enabled=false \ --wait
# Visible result: the agent pod is Running and the agent has registeredkubectl get pods -l app.kubernetes.io/name=brokkr-agentcurl -s http://localhost:3000/api/v1/agents \ -H "Authorization: Bearer $ADMIN_PAK" | jq '.[] | {name, cluster_name, status}'When the agent pod is Running and eval-agent appears in the broker’s agent list, the broker and agent are talking. The agent registers as INACTIVE; you activate it in the next step before deploying.
Pre-register at creation (optional): This walkthrough registers the agent with the admin-generator as a separate step below. You can instead register at creation time by passing
generator_idstoPOST /agents(e.g.-d '{"name": "eval-agent", "cluster_name": "evaluation", "generator_ids": ["'$GEN_ID'"]}') or--set broker.generatorIds={$GEN_ID}on the agenthelm install— then the separate register call is unnecessary. Every agent is always auto-registered with the system generator for fleet-wide stacks regardless. See Registering an Agent with a Generator.
6. Deploy a test resource and watch it reconcile
Section titled “6. Deploy a test resource and watch it reconcile”Create a stack, target the agent, and push a namespace through the broker.
# Activate the agent so it will pull and reconcile deployment objectsbrokkr agent activate eval-agent
GEN_ID=$(curl -s http://localhost:3000/api/v1/generators \ -H "Authorization: Bearer $ADMIN_PAK" \ | jq -r '.[] | select(.name=="admin-generator") | .id')
STACK_ID=$(curl -s -X POST http://localhost:3000/api/v1/stacks \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d "{\"name\": \"evaluate\", \"description\": \"Evaluation stack\", \"generator_id\": \"$GEN_ID\"}" \ | jq -r '.id')
# Register the agent with the admin-generator before targeting it. Targeting a stack# at an agent that is not registered with the stack's generator fails with agent_not_registered.brokkr register --agent eval-agent --generator admin-generator
brokkr stack target evaluate eval-agent
curl -s -X POST "http://localhost:3000/api/v1/stacks/$STACK_ID/deployment-objects" \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"yaml_content": "apiVersion: v1\nkind: Namespace\nmetadata:\n name: brokkr-evaluate", "is_deletion_marker": false}'The activate, register and target steps with curl
export AGENT_ID=$(curl -s http://localhost:3000/api/v1/agents \ -H "Authorization: Bearer $ADMIN_PAK" \ | jq -r '.[] | select(.name=="eval-agent") | .id')
curl -s -X PUT http://localhost:3000/api/v1/agents/$AGENT_ID \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d '{"status": "ACTIVE"}' | jq '{name, status}'
curl -s -X POST http://localhost:3000/api/v1/generators/$GEN_ID/register \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d "{\"agent_id\": \"$AGENT_ID\"}"
# The body `agent_id` must match the agent id in the path. The broker rejects a mismatch with 400.curl -s -X POST http://localhost:3000/api/v1/agents/$AGENT_ID/targets \ -H "Authorization: Bearer $ADMIN_PAK" \ -H "Content-Type: application/json" \ -d "{\"agent_id\": \"$AGENT_ID\", \"stack_id\": \"$STACK_ID\"}"After the agent’s next poll, the namespace appears on your cluster — allow one full poll cycle (the chart’s default polling interval is 30 seconds):
# Visible result: the namespace your agent reconciledkubectl get namespace brokkr-evaluateTear down
Section titled “Tear down”# Stop the port-forward first (or just close the shell it runs in)kill %1 2>/dev/null
helm uninstall brokkr-agenthelm uninstall brokkr-brokerkind delete cluster --name brokkr-eval # or: k3d cluster delete brokkr-evalNext steps
Section titled “Next steps”Once you have seen Brokkr work, go deeper:
- Deploy Your First Application — a fuller guided tutorial of the deployment workflow.
- Submitting a Folder of Manifests (CLI) — apply a whole directory of manifests with one idempotent
brokkrcommand instead of curling each object. With the admin PAK, add--generator <name>to say which generator owns the stack. - Monitoring Your Agent Fleet — see which agents are connected, healthy, and keeping up.
- Monitoring Deployment Health — watch what your agents are reconciling and surface failures.
- Installing Brokkr — the full, production-aware Helm install with values files, real PAKs, and a hardening checklist.