Skip to main content

Infrastructure as Code (Terraform)

The System9 estate can be managed as code. A native Terraform provider, System9ai/system9, turns service groups, engagement workspaces, clean rooms, and databases into HCL resources, so an estate is declared in version control and converged with terraform plan / terraform apply like any other infrastructure.

The provider is deliberately thin: it is a GitOps front-end over the shipped estate-as-IaC and engagement-provision BFFs and performs no reconciliation of its own. The backend computes the minimal operation set and enforces the platform's net-potential-gain governor on destructive changes, so the provider does not re-implement diffing, and a destructive plan is judged by the platform, not by the client.

Real and present, developing in-repo

The provider exposes real resources and a data source (enumerated below) with working schemas and acceptance tests. It currently develops in-repo alongside the BFF contract it drives; the module has not yet been extracted to a standalone repository or published to the Terraform Registry. Treat the System9ai/system9 registry source shown in examples as the intended published address, not a live one yet.

How it works​

terraform apply sends the desired state to the estate or engagement-provision plan endpoint, the backend computes the minimal operation set (and runs the net-potential-gain gate on anything destructive), and the provider then calls apply. There is no client-side reconciler.

*Figure SE3: the plan / apply flow. HCL (cyan) is the desired state; the thin provider forwards it to the estate or engagement-provision plan endpoint, where the backend computes the minimal operation set and runs the net-potential-gain gate on any destructive change (amber). Approved operations are converged by apply (green); a destructive change the gate refuses never reaches apply. The provider itself holds no reconciler.

Table equivalent

StepWhere it runsWhat happens
Terraform HCLYour configThe whole resource body is the desired spec
Providerterraform-provider-system9Thin GitOps front-end; no reconciliation of its own
planEstate / engagement-provision BFFBackend computes the minimal operation set
Net-potential-gain gateBackendJudges destructive changes; refuses net-negative ones before apply
applyEstate / engagement-provision BFFConverges the approved operations
Converged estateThe platformService groups, workspaces, clean rooms, and databases in the desired shape

Authentication​

The provider authenticates with an API key sent as a bearer token. A System9 API key authenticates as its bound entity, so the estate routes are role-gated, not scope-gated, grant the bound entity the required permissions via its role:

OperationPermissions the bound entity must hold
Service-group estate: plan / applysystem.cells.inspect / system.cells.manage
Engagement provision: plan / applysystem.data.read / system.data.write

Mint the key through the System9 API-key management surface and keep it out of state and version control by exporting it as an environment variable:

export SYSTEM9_API_KEY="s9_…"

Provider configuration​

AttributeRequiredDescription
endpointyesBase URL of the System9 node App-BFF, e.g. https://node.example.com (do not include the /api/... path)
api_keyyes (sensitive)API key used as a bearer token
insecurenoSkip TLS certificate verification: development only, never enable in production

Resources and data sources​

The provider exposes four managed resources and one data source.

TypeKindWhat it manages
system9_service_group_estateResourceA declarative service-group estate: the whole resource body is the desired estate: service groups plus their quotas, reservations, elastic-membership targets, and cell membership. Supports bounded prune within a declared blast-radius prune_scope
system9_engagement_workspaceResourceAn engagement workspace catalog: the workspace-scoped root data container (catalog id, owning workspace and entity, name, and optional display name / description / scope / default schema)
system9_engagement_clean_roomResourceAn engagement clean room: an isolated collaboration environment keyed by owner entity and name, with optional purpose, governing domain, minimum aggregation threshold, and output-review requirement
system9_engagement_scaleout_databaseResourceAn engagement scaleout database bound to a catalog: database id, owning catalog and entity, name, and optional workload profile / engine / storage group
system9_consulting_lensesData sourceThe registered consulting assessment lenses for a workspace: each lens's id, label, description, the assessment-runner engines it drives, and whether it is runnable
The estate spec is the resource body

For system9_service_group_estate, the entire resource body is the desired EstateSpec, terraform apply converges it. prune is destructive: an undeclared group within prune_scope is deleted, so the blast radius is declared explicitly (by name_prefix and/or group_id_prefix) rather than defaulting to the whole estate.

Usage example​

terraform {
required_providers {
system9 = {
source = "System9ai/system9"
}
}
}

variable "system9_api_key" {
type = string
sensitive = true
# Prefer exporting SYSTEM9_API_KEY / TF_VAR_system9_api_key in the environment.
}

provider "system9" {
endpoint = "https://node.example.com" # node App-BFF base URL
api_key = var.system9_api_key
}

# A declarative service-group estate. The whole resource body is the desired
# EstateSpec; `terraform apply` converges it via the estate-as-IaC BFF.
resource "system9_service_group_estate" "prod" {
name = "prod"

service_group {
group_id = "sg-1"
name = "primary"
group_type = "workload"

quota {
max_cells = 4
min_standby = 1
}

reservation {
isolation_mode = "dedicated"
}

membership_target {
desired_cells = 3
target_utilization = 0.5
autoscale_enabled = true
}

cells = ["cell-a", "cell-b"]
}
}

See also​