monedula-gitops docs menu
Get started with the CLI
Install monedula-gitops, point it at a local Kafka cluster, and create your first topic with producer and consumer access, from diff to verify.
On this page
The local stack authenticates clients with SASL/SCRAM-SHA-512 and protects Schema Registry with HTTP basic auth, the same authentication paths a real deployment uses.
What you need
- Docker with the Compose plugin. Check with
docker compose version. - Go 1.26 or newer, to build the CLI. Check with
go version. - Git and a bash shell. The commands on this page use bash syntax.
1. Get the quickstart files
Clone the repository and change into the CLI quickstart directory:
git clone https://github.com/monedula-dev/monedula-gitops.git
cd monedula-gitops/quickstart/cli
Run every command in this tutorial from this directory. It contains:
quickstart/cli/
docker-compose.yml # Kafka (SCRAM) + kafka-init + Schema Registry
.env.example # credentials/endpoints (copy to .env)
clusters/dev.yaml # KafkaCluster "local" (env-based secret refs)
manifests/
payments-orders.yaml # KafkaTopic payments.orders (+ access + AVRO schema)
billing-access.yaml # KafkaAccessPolicy billing-access
schemas/orders-value.avsc # AVRO value schema (referenced by the topic)
2. Configure the credentials
Copy the example environment file:
cp .env.example .env
The defaults in .env work as they are:
KAFKA_BOOTSTRAP=localhost:9092
KAFKA_USERNAME=admin
KAFKA_PASSWORD=admin-secret
SCHEMA_REGISTRY_URL=http://localhost:8081
SR_USERNAME=sr
SR_PASSWORD=sr-secret
KAFKA_USERNAME and KAFKA_PASSWORD are the SCRAM-SHA-512 super-user, and SR_USERNAME and SR_PASSWORD the Schema Registry basic-auth user.
The CLI connects as the super-user so that it bypasses ACL enforcement: a principal without super-user rights can lock itself out once apply creates a topic’s ACLs, as Connect to a secured Kafka cluster explains.
3. Start Kafka and Schema Registry
docker compose up -d
Wait for the services to become healthy:
docker compose ps
The kafka-init container creates the SCRAM users and must finish before Kafka accepts those credentials. Schema Registry starts only after kafka-init succeeds and Kafka is healthy. Follow their logs until things settle:
docker compose logs -f kafka-init schema-registry
kafka-init should exit 0, and schema-registry should log that it is listening on 0.0.0.0:8081. Press Ctrl-C to stop following the logs.
4. Load the credentials into your shell
clusters/dev.yaml tells the CLI to read the credentials from environment variables. Load .env into the current shell:
set -a; source .env; set +a
Run the remaining steps in this same shell.
5. Build the CLI
Build the binary from the cloned source:
go build -o ../../bin/monedula-gitops ../../cmd/monedula-gitops
Put the bin directory on your PATH for this shell and check that the binary runs:
export PATH="$PWD/../../bin:$PATH"
monedula-gitops version
A build from source reports its version as dev.
6. Read the manifests
The cluster config, clusters/dev.yaml, says where Kafka and Schema Registry are and which environment variables hold the credentials:
apiVersion: gitops.monedula.dev/v1alpha1
kind: KafkaCluster
metadata:
name: local
spec:
bootstrapServers: localhost:9092
auth:
mechanism: SCRAM-SHA-512
scram:
username:
valueFrom:
env: KAFKA_USERNAME
password:
valueFrom:
env: KAFKA_PASSWORD
schemaRegistry:
endpoint: http://localhost:8081
auth:
type: basic
username:
valueFrom:
env: SR_USERNAME
password:
valueFrom:
env: SR_PASSWORD
The topic manifest, manifests/payments-orders.yaml, declares the topic, its configuration, its access and its schema:
apiVersion: gitops.monedula.dev/v1alpha1
kind: KafkaTopic
metadata:
name: orders
namespace: payments
spec:
clusterRef:
name: local
topicName: payments.orders
partitions: 6
config:
retention.ms: "604800000"
access:
producers:
- principal: "User:svc-checkout"
operations:
- Write
consumers:
- principal: "User:svc-fraud"
group: fraud-orders
topicOperations:
- Read
groupOperations:
- Read
schema:
format: AVRO
compatibility: BACKWARD
valueSchema:
valueFrom:
file: ./schemas/orders-value.avsc
reconciliation:
mode: Enforce
deletionPolicy: Orphan
clusterRef.name: local points at the KafkaCluster named local in clusters/dev.yaml. The access block becomes Kafka ACLs that let User:svc-checkout write to the topic and User:svc-fraud read it with the consumer group fraud-orders. The schema file path is resolved relative to the manifest.
The third file, manifests/billing-access.yaml, is a KafkaAccessPolicy. It grants User:svc-billing Read, Write and Describe on every topic whose name starts with the prefix billing., which a topic’s access block cannot express.
7. Validate the manifests
monedula-gitops validate -f manifests --cluster-config-file clusters/dev.yaml
validate parses the manifests, resolves the referenced Avro schema file and checks that every clusterRef names a cluster in the config, without contacting Kafka. It reports the resources as valid and exits 0.
8. Preview the changes
monedula-gitops apply -f manifests --cluster-config-file clusters/dev.yaml --dry-run
--dry-run lists the planned operations without changing anything: create operations for the topic, the schema and the ACLs.
9. Apply
monedula-gitops apply -f manifests --cluster-config-file clusters/dev.yaml
This creates the payments.orders topic, registers its Avro value schema and creates the ACLs.
10. Verify and diff
Check that the live cluster now matches the manifests:
monedula-gitops verify -f manifests --cluster-config-file clusters/dev.yaml
verify reports no drift and exits 0. On drift it would exit 1, which makes it a CI check.
Then show the difference between the live state and the manifests:
monedula-gitops diff -f manifests --cluster-config-file clusters/dev.yaml
Right after a clean apply, diff shows no pending operations. diff exits 0 with or without drift and 2 on error, so use verify when the exit code should reflect drift.
11. Look at the result in Kafka
The broker container has the Kafka tools and a client config with the SASL/SCRAM settings. Describe the topic that apply created:
docker compose exec kafka kafka-topics \
--bootstrap-server localhost:9092 \
--command-config /etc/kafka/secrets/client.properties \
--describe --topic payments.orders
List the ACLs:
docker compose exec kafka kafka-acls \
--bootstrap-server localhost:9092 \
--command-config /etc/kafka/secrets/client.properties --list
The topic has 6 partitions, and the ACL list contains the grants for User:svc-checkout, User:svc-fraud and User:svc-billing from your two manifests.
12. Import the cluster back into manifests
import cluster works in the other direction: it reads the live cluster and writes manifests. It never changes Kafka.
monedula-gitops import cluster --cluster-config-file clusters/dev.yaml --output-dir ./imported
ls -R ./imported
The KafkaTopic and KafkaAccessPolicy manifests under ./imported mirror what you applied. Import an existing Kafka cluster uses this to bring an existing cluster under management.
13. Try a change that needs approval
A partition increase cannot be undone, so apply holds it back until you approve it.
-
In
manifests/payments-orders.yaml, changepartitions: 6topartitions: 12. -
Apply without approval:
monedula-gitops apply -f manifests --cluster-config-file clusters/dev.yamlThe partition increase is reported as
Blockedand the command exits 3: the plan is sound, it waits for your approval, and nothing changes. -
Apply again with the approval flag:
monedula-gitops apply -f manifests --cluster-config-file clusters/dev.yaml --allow-destructiveThis time the topic grows to 12 partitions.
Change the file back to partitions: 6 before you run the tutorial again on a fresh stack.
14. Clean up
Stop the stack and remove its volumes:
docker compose down -v
Next steps
- Get started with the operator runs the same model inside Kubernetes.
- Topic-centric access explains what the
accessblock compiles to. - Safety gates covers approvals, pruning and deletion.