On-ramp: From Atmos

This is the on-ramp for OSS-first teams running Atmos with self-hosted CI. The hard constraint here is real: no SaaS dependencies. Terrantula respects it. The entire cattle wedge runs on free, self-hostable tooling — Terrantula's Apache 2.0 backend + Atmos + your own CI = full functionality at zero SaaS spend.

Terrantula treats Atmos as a peer substrate, not a thing to replace. Your Atmos stacks, your workflows, your S3 state, and your CI keep doing exactly what they do today.

Where you are now

your-atmos-repo/ ├── stacks/ # your Atmos stack manifests │ └── tenants/ ├── workflows/ # your Atmos workflow definitions └── (state in S3 — Atmos doesn't host state)

Atmos is your configuration layer; atmos terraform apply (driven by an Atmos workflow) executes the actual Terraform. State lives in your S3. What you lack is a fleet-wide view across stacks — placement decisions, capacity ceilings, and the relationships between tenants are scattered across manifests and runbooks.

What Terrantula adds

Terrantula is the fleet layer above Atmos — it composes with it rather than competing:

  • Visibility across stacks. A graph of every entity in the fleet, derived from your Atmos stack manifests, with the cells they're placed in and how they connect.
  • Placement and constraints. Typed entities with capacity ceilings and cardinality checks, enforced rather than remembered.
  • Atmos-native execution. When an Action fires, Terrantula uses the atmos-workflow trigger to invoke an Atmos workflow — through a runner you deploy.
Terrantula never runs

terraform apply — your Atmos runner does Terrantula's Actions modify your IaC by opening a pull request (a new stacks/tenants/<id>.yaml manifest) and/or by invoking an Atmos workflow. The actual atmos terraform apply runs on a customer-deployed runner— a Docker container or CI job you operate — against your own S3 state. Terrantula never executes Terraform itself and never hosts runners or state.

No SaaS dependency — by design

The Atmos substrate is served by a reference runner you deploy yourself. Terrantula's atmos-workflow trigger HTTP-POSTs a structured payload to your runner; the runner clones your Atmos repo, runs atmos workflow <name> -s <stack>, and POSTs back to Terrantula's callback. Nothing routes through a hosted service unless you choose the hosted option. Self-hosting is a first-class path, not a downgrade.

Step 1 — Get a view from your stack manifests

Start with pure visibility. The CLI ingests an Atmos stacks directory directly. Point import-atmos at the directory, tell it which entity type the stacks map to, and give it a name template built from stack vars:

terrantula import-atmos ./stacks/tenants \
  --entity-type Tenant \
  --name "{{ vars.customer_id }}"

Preview without writing anything with --plan:

terrantula import-atmos ./stacks/tenants \
  --entity-type Tenant \
  --name "{{ vars.customer_id }}" \
  --plan

If your Atmos repo uses a nested stack layout (subdirectories under stacks/), add --recursive to walk the tree:

terrantula import-atmos ./stacks \
  --entity-type Tenant \
  --name "{{ vars.customer_id }}" \
  --recursive

Then open the dashboard:

terrantula dashboard

In local mode this is entirely self-contained — an embedded SQLite database, nothing leaving your machine, no server and no signup. For the step-by-step walkthrough, follow the Quick Start.

Step 2 — Add orchestration with the Atmos runner (optional)

When you grow into a cattle problem, turn on Actions backed by the atmos-workflow trigger:

  1. Deploy the reference Atmos runner once — a Docker container (or CI job) that you operate inside your own infrastructure. This is the only setup step Atmos adds over the other substrates, and it keeps execution under your control.
  2. You fire an Action (e.g. OnboardTenant). Terrantula validates parameters, enforces constraints, and picks the right cell.
  3. Terrantula opens a PR with a new stacks/tenants/<id>.yaml manifest and/or POSTs the workflow payload to your runner.
  4. Your runner clones the repo and runs atmos workflow provision-tenant -s <stack> against your S3 state, then POSTs the outcome back to Terrantula's callback.
  5. Terrantula advances the entity's lifecycle (e.g. to active) on the callback.

The Terrantula catalog is identical to the TFC and bare-TF variants; only the trigger configuration changes. See the cattle-saas-tenants-atmos canonical demo, which anchors exactly this OSS-first configuration.

What stays the same

  • Your runner. Your customer-deployed Atmos runner runs atmos terraform apply. Terrantula never runs Terraform.
  • Your state. It stays in your S3 (Atmos doesn't host state, and neither does Terrantula).
  • Your Atmos config. Stacks, workflows, inheritance, and vendoring — untouched. Terrantula reads manifests and invokes workflows; it doesn't rewrite your Atmos layer.
  • Zero SaaS spend. The whole wedge runs on Terrantula OSS + Atmos + your CI.

Terrantula adds the fleet view, placement, constraint enforcement, and lifecycle — entirely on tooling you host.

Next

  • Quick Start — import your stacks and open the dashboard end-to-end.
  • Deploy on Kubernetes — self-host the Apache 2.0 backend end-to-end.
  • FAQ — how Terrantula differs from Atmos, and why it composes with it.
  • Triggers reference — the atmos-workflow trigger, in detail.
  • Examples — the cattle-saas-tenants-atmos canonical demo.