Usage

On this page
Navigation

Command reference for installing, updating, and uninstalling the SignalForge lab, plus a full CLI reference for every script and Make target in the repo.

Prerequisites: Docker 24+, k3d v5+, kubectl v1.28+, helm v3.14+, Python 3.9+. Azure CLI 2.50+ is only needed if you use the optional AKV credential-fetch script — not required for a normal install/update as long as .env is already populated.


Install (first-time deploy)

./deploy-local.sh

Creates the k3d cluster (otel-lab), builds all 4 Docker images, and applies manifests in dependency order (infra/ → datastores/ → monitoring/ → app/ → post/). Cloud mode installs the Helm monitoring chart; local mode uses the bespoke collector unless --with-helm is supplied. Cold run: 5–15 min.

In monitoring.mode: cloud (the default), Grafana Cloud credentials come from the .env file named by monitoring.grafana_cloud.use_env in conf.yml — deploy-local.sh sources it directly, no extra step needed as long as .env is already populated. Fetching from Azure Key Vault is a separate, optional, manual path for when you need to (re)populate .env — see Rotate Grafana Cloud credentials below. It is not part of the install flow.

Verify the install:

./scripts/debug.sh      # mode-aware triage: pod state, Alloy exporter counters, remote-write probe
make validate            # curl-based smoke test of all endpoints

Update

Pick the command that matches what changed — no need to rebuild or recreate anything you didn’t touch.

What changedCommand
App code (src/*)./deploy-local.sh (rebuilds images + reapplies manifests)
K8s manifests / conf.yml only, images unchanged./deploy-local.sh --skip-build
Nothing but need to reassert current state./deploy-local.sh --skip-cluster --skip-build (<1 min)
Grafana Cloud credentialssee below
Local-mode Helm monitoring chart./deploy-local.sh --with-helm
Using a non-default config file./deploy-local.sh -c <path-to-conf.yml>

deploy-local.sh is idempotent — re-running any variant is safe and is the local-lab recovery path (reapply the last-known-good conf.yml / manifests). It is not the CI/CD rollback mechanism: an enabled GitHub Environment deployment restores the previous complete immutable four-image digest set and its runtime ConfigMaps. See Immutable CI/CD Promotion.

Rotate Grafana Cloud credentials

Optional and manual — only needed if .env is missing or its Grafana Cloud values are stale. Everyday installs/updates don’t need this; deploy-local.sh already reads .env directly.

./scripts/fetch-grafana-cloud-conf-from-akv.sh --dry-run   # preview diff against AKV
./scripts/fetch-grafana-cloud-conf-from-akv.sh             # pull + write into .env in place (+ .env.bak)
./deploy-local.sh --skip-cluster --skip-build              # re-apply, no rebuild needed

Auth: existing az login session, or export ARM_CLIENT_ID + ARM_CLIENT_SECRET in the shell (no .env loading for this script itself — it writes .env, it doesn’t read from it for auth).

Push updated SLO rules (cloud mode)

./scripts/push-slo-rules-to-mimir.sh --dry-run   # mimirtool rules diff, read-only
./scripts/push-slo-rules-to-mimir.sh             # load k8s/monitoring/slo-rules.yaml into the Ruler API

mode=local needs no manual step — deploy-local.sh loads the same rules file automatically.


Uninstall

./deploy-local.sh --teardown       # deletes the entire k3d cluster (all namespaces, all state)

For a lighter-weight reset that keeps the cluster and datastores but drops the app namespace:

make teardown                      # deletes only the otel-lab namespace

There is no in-place “uninstall just the monitoring chart” path — re-run ./deploy-local.sh --skip-cluster --skip-build after flipping monitoring.mode or editing conf.yml to change what gets installed on the next apply.


CLI Reference

deploy-local.sh

The sole deploy path. Reads every knob from conf.yml.

FlagEffect
(none)Full deploy: cluster + builds + manifests + Helm
--skip-clusterReuse the current k3d cluster / kube context (guarded — refuses to run against the wrong context)
--skip-buildReuse images already loaded into the cluster
--with-helmLocal mode only: also install grafana/k8s-monitoring. No-op in cloud mode (already mandatory there)
--teardownDelete the k3d cluster and exit
-c, --config <path>Use a config file other than ./conf.yml
-h, --helpPrint usage

scripts/

ScriptPurpose
debug.shMode-aware triage — pod state, Alloy exporter counters, remote-write reachability probe, alloy-receiver endpoint check
fetch-grafana-cloud-conf-from-akv.sh [--dry-run|--print|--no-backup]Optional/manual. Pulls Grafana Cloud credentials from Azure Key Vault, writes them into the .env file named by conf.yml’s monitoring.grafana_cloud.use_env (preserving comments, .bak backup by default). --dry-run previews the diff; --print emits a YAML block for manual paste (legacy)
push-slo-rules-to-mimir.sh [--dry-run]Loads k8s/monitoring/slo-rules.yaml into Grafana Cloud Mimir’s Ruler API via mimirtool. Cloud mode only
smoke-test-conf-updater.shOffline regression test for the .env in-place updater used by the AKV fetch script — no cluster required

Makefile (legacy / secondary — prefer deploy-local.sh for deploy)

TargetDescription
make cluster-upCreate the k3d cluster with port mappings
make cluster-downDelete the k3d cluster
make buildBuild all 4 Docker images locally
make importBuild + import images into k3d
make teardownDelete the otel-lab namespace (cluster stays up)
make testRun the k6 load test Job
make validateSmoke-test all endpoints with curl
make logsStream logs from all app pods
make test-unitRun all unit test suites (.NET + Python + frontend)
make secrets-fetch-akvLegacy — writes the Grafana Cloud K8s Secret directly from AKV, bypassing deploy-local.sh
make secrets-applyLegacy — applies credentials from .env
make secrets-showPrint stored Secret values (API key redacted)

make deploy / deploy-cloud / deploy-local / full are retired — they print a redirect to ./deploy-local.sh and exit non-zero.

Kustomize

kubectl kustomize k8s/base                  # render full stack
# Inspect topology only; CD adds immutable image digests and protected runtime configuration.
kubectl kustomize k8s/overlays/prod
kubectl apply -k k8s/overlays/dev           # apply dev overlay

Health check / triage

./scripts/debug.sh                # mode-aware: pod state, Alloy exporter counters, remote-write probe
make validate                     # curl-based smoke test of all endpoints

Endpoints

URLServiceNotes
http://localhost:8080Angular SPA + gateway-apialways available
https://signal-forge.local:8443Same, TLSneeds security.tls.enabled: true + /etc/hosts entry
http://localhost:15672RabbitMQ mgmt (guest/guest)always available
http://localhost:16686Jaegerlocal mode only
http://localhost:3000Grafana (admin/admin)local mode only
http://localhost:9090Prometheuslocal mode only
Alloy pipeline UIkubectl -n monitoring port-forward svc/grafana-k8s-alloy-receiver 12345 → http://localhost:12345cloud mode