Skip to Content
InstallationLocal development

Local development

This guide brings the full TruStacks platform up on a local Kubernetes cluster from source: k3d running on your laptop, Gitea as the in-cluster Git server, ArgoCD watching a sample platform repo, Zot as the OCI registry for signed policy bundles, the Control Plane, the Runner, and the UI.

The intended audience is contributors with trustacks-mvp repository access who want to build TruStacks from source and iterate on it. For evaluators and workshop attendees, the quickstart is the right path; it pulls signed images from ghcr.io/trustacks/* and doesn’t need repository access.

Scoped to contributor development. The procedure on this page builds images locally and runs against the source tree. Customer production installation is moving to the Cluster Operator (post-Beta); for production deploys today, see the cluster install guide.

What gets installed

After bring-up, the following services are running in your k3d cluster, all reachable via Traefik on *.localtest.me:8080:

ServiceURLPurpose
UIhttp://ui.localtest.me:8080Chat-first product surface
Control Planehttp://cp.localtest.me:8080API + audit + SSE event stream
Runnerhttp://runner.localtest.me:8080/healthzThe agent crew lives here
Giteahttp://gitea.localtest.me:8080In-cluster Git server (replaces GitHub for local)
Argo CDhttp://argocd.localtest.me:8080GitOps controller watching the platform repo
Zothttp://zot.localtest.me:8080/v2/OCI registry for signed policy bundles

localtest.me resolves to 127.0.0.1 automatically. No /etc/hosts edits required.

Prerequisites

You need a Mac or Linux box with Docker and a small set of CLIs.

Required tools

On macOS, install with Homebrew:

brew install --cask docker # Docker Desktop, then start it brew install k3d helm kubectl uv node opa oras

Minimum versions:

  • k3d ≥ 5.8
  • helm ≥ 3.14
  • kubectl (latest)
  • uv (Python toolchain manager)
  • node ≥ 20 + npm
  • opa ≥ 1.x (Open Policy Agent CLI; runs Rego tests + builds bundles)
  • oras ≥ 1.3 (pushes the policy bundle to the in-cluster Zot registry)

On Linux, install the equivalents through your package manager or each project’s release binaries.

Anthropic API key

The Runner needs an Anthropic API key to talk to Claude. Get one at console.anthropic.com. OpenRouter is supported as a BYO escape hatch; both providers route to Claude Sonnet 4.5+.

Source

Clone the TruStacks repository (you need access to github.com/TruStacks/trustacks-mvp while it is in private Beta).

git clone https://github.com/TruStacks/trustacks-mvp.git cd trustacks-mvp

Bring-up

The full bring-up takes four commands plus one verification step.

1. Configure your environment

cp .env.example .env # edit .env, set ANTHROPIC_API_KEY=<your-key>

The Runner will not start without an Anthropic key. If .env is missing or ANTHROPIC_API_KEY is empty, make up fails at the secrets step. The cluster is still up after that failure; rerun make secrets once the key is set to recover.

2. Install language dependencies

make install

Installs Python virtualenvs via uv for the Control Plane and Runner, plus node_modules for the UI.

3. Bring up the cluster

make up

This is the slow one. It creates the k3d cluster, installs Traefik as the ingress, deploys Gitea + ArgoCD + Zot, then deploys the Control Plane, the Runner, and the UI. The last step applies your Anthropic key to the Runner’s Secret.

Verify with make doctor if any step looks wrong.

4. Seed the demo data

make seed

make seed is the single demo-bootstrap command. It is idempotent; you can re-run it any time. Order of operations:

  1. Apply the cosign public key as a ConfigMap so the Runner’s init container can verify policy bundles before extract.
  2. Build and push the constitution bundle: opa build -b policy/constitution, push to Zot via oras, sign with cosign. The Runner’s init container pulls the bundle, runs cosign verify, and extracts only on a clean verify.
  3. Seed Gitea with the seven demo repositories: four polyglot service samples (sample-app for FastAPI, sample-app-spring-boot for Spring Boot, sample-app-dotnet for .NET, sample-app-go for Go) plus the platform and overlay infra repos.
  4. Provision deploy keys: per-repo SSH ed25519 keys, registered with Gitea and applied as labeled K8s Secrets the Runner’s init container picks up dynamically. Plus a Gitea API token for opening PRs.
  5. Seed connection profiles in the Control Plane for each seeded repo.
  6. Apply the ArgoCD root: an Application that watches argocd/*.yaml in the platform repo. Anything the DevOps Engineer ships into argocd/ becomes a child Application after merge.
  7. Roll the Runner so its init containers pick up the new deploy keys and the freshly-signed bundle.

5. Confirm everything is reachable

make urls

Prints the URL + credentials table for every service, including the live ArgoCD admin password.

Run your first analysis

The platform delivers two flows: the Code Reviewer (repo discovery to structured analysis) and the DevOps Engineer (analysis + Environment Profile to a PR opened against the platform repo).

Code Reviewer

cd runner && uv sync # one-time uv run trustacks review sample-app-gitea # streams events live

Event sequence: started → cloned → tool_call / tool_result / finding ×N → done. The terminal done event’s payload is the final RepositoryAnalysis. The CLI prints the analysis ID at the top. Copy it for the next step.

DevOps Engineer

A Proposal is built from a specific prior Analysis. Pass the analysis ID:

uv run trustacks plan <analysis-id> # opens a PR on platform uv run trustacks plan <analysis-id> --dry-run # preview, no PR

trustacks plan chains six stages:

  1. Clone the customer’s app repo at the analysis-time ref.
  2. Emit a stale_analysis warning if HEAD has moved.
  3. Clone the overlay repo and load the Environment Profile.
  4. Run the DevOps Engineer agent. It emits a CI workflow, a Helm chart, and an ArgoCD Application.
  5. OPA policy gate. The Runner shells opa eval against the OCI-pulled constitution. On allow, continue. On deny, emit policy_check with violations and short-circuit (no PR, no done).
  6. Push to a trustacks/<id> branch on the platform repo and open the PR via Gitea’s API.

--dry-run swaps the writer step for dry_run_skipped. The proposal is rendered locally and in the UI, but no branch is pushed.

Watch it in the UI

Open http://ui.localtest.me:8080. The sidebar surfaces Activity / Applications / Services / Gaps / Rules / Settings. Click into your service and you will see the analyses and proposals tabs, with the live event log mirroring what the CLI streamed. Proposals show:

  • A green ✓ policy clean line, or a red ✗ policy deny with rule IDs.
  • A green Pull request opened banner with the PR URL on success.
  • An amber Dry run banner if the writer was skipped.

Connect your own repo

Once the demo loop is closed, you can connect a real repository through the UI’s + Connect repo wizard. The wizard supports two providers:

  • Gitea path · for already-existing repos on the in-cluster Gitea. Generates an ed25519 keypair, registers the public key, applies the Secret, registers the connection profile, and rolls the Runner.
  • GitHub path · for repos on github.com. Fetches the App install URL from the Control Plane, redirects you to GitHub, and after you install the TruStacks App on a repo, redirects back with the installation ID. Requires one-time operator setup of the TruStacks GitHub App. Until that is done, the wizard’s GitHub branch shows an amber “ask your admin” state.

GitLab and Azure DevOps providers ship post-Beta.

Common operations

Tear down

make down

Deletes the k3d cluster entirely. Re-running make up then make seed brings everything back.

Rotate the LLM key

Two paths. Prefer the UI when the Control Plane is up:

  • UI path · open http://ui.localtest.me:8080/#/settings/llm. Paste the new key, confirm, save. The Control Plane runs a live ping against the provider, rewrites the trustacks-runner-llm Secret, and rolls the Runner.
  • .env + make path · for fresh-cluster bootstrap before the Control Plane is up. Update ANTHROPIC_API_KEY in .env, then make secrets.

Re-seed after a roll

A few things are stored ephemerally in the local cluster.

  • The Control Plane’s SQLite is in an emptyDir. A CP pod restart wipes proposals, analyses, and connection profiles. Re-run make seed.
  • Gitea has persistence.enabled=false. Any helm upgrade against the Gitea release wipes its database. make seed is idempotent; roll the Runner once afterward so the new Secrets are mounted.
  • Zot also runs without persistence. make seed re-pushes the constitution. The Runner falls back to the image-baked bundle (/etc/trustacks/policy/) if Zot is unreachable, so the cluster stays functional during a Zot wipe.

Re-seed after a policy update

After editing rules under policy/constitution/, re-run make seed or just make policy-bundle to push the freshly-built bundle to Zot. Otherwise the Runner keeps verifying and extracting the previously-tagged bundle.

Troubleshooting

make up fails at the secrets step

ANTHROPIC_API_KEY is missing or empty in .env. The cluster is still up; set the key and run make secrets.

git@gitea-ssh: Permission denied after a Gitea wipe

The deploy keys in Gitea are out of sync with the Secrets in trustacks-system. Re-run make seed, then roll the Runner.

UI /rules page is empty

The constitution bundle has not been pushed to Zot yet (the page reads its rule inventory from inside the bundle). Run make policy-bundle or the full make seed.

Policy check denies your first proposal

This is the system working as designed. The constitution rejected your proposal. The policy_check event payload includes the rule IDs that denied. See the constitution reference for what each rule checks.

Where to go next

Last updated on