StrataCI — the execution plane
StrataCI is the small, one-time execution plane that StrataCTL stands up inside your own AWS account. It is the infrastructure that installs, updates, and removes StrataBI modules and the platform itself — an S3 bucket, a few DynamoDB tables, a CodeBuild-based ephemeral runner, and the IAM roles that tie them together. Shaleio holds no credentials here: you run StrataCTL with your own AWS identity, and every deploy executes in your account, against state stored in your account.
You provision it once per account/region with stratactl bootstrap, and everything StrataCTL does afterward — install, update, uninstall, dev install, install-stratabi — runs through it.
Why it exists
Installing StrataBI means running OpenTofu against your account. Rather than run that from your workstation (and scatter state and credentials around), StrataCI runs it in an ephemeral, least-privilege runner in your account. The runner fetches a verified bundle, runs OpenTofu against your own S3 state backend, records status, and exits. The result: deployment state and logs live in your account end to end, and the human operator only ever needs their own IAM identity.
stratactl bootstrap
bootstrap provisions (or tears down) the StrataCI plane. It is safe by default — with no flags it prints what it would do and stops; it only touches AWS with --run, and only applies with --run --yes.
stratactl --profile <profile> --region <region> bootstrap # dry run — describe only
stratactl --profile <profile> --region <region> bootstrap --run # init + plan
stratactl --profile <profile> --region <region> bootstrap --run --yes # init + plan + apply
stratactl --profile <profile> --region <region> bootstrap --destroy # tear the plane downIt runs once per account/region. --profile/--region may appear anywhere in the command.
What the template provisions — exactly
The bootstrap Terraform (name_prefix defaults to strataci) creates:
| Resource | Name | Purpose |
|---|---|---|
| S3 bucket | strataci-<account>-<region> (or bucket_name) | Artifact cache, OpenTofu state, and logs. Versioned, KMS-encrypted (bucket keys on), full public-access block, prevent_destroy. |
| DynamoDB — install registry | <prefix>_install_registry | The record of what's installed (hash key module_id), with point-in-time recovery and prevent_destroy. |
| DynamoDB — jobs | <prefix>_jobs | Runner job records (hash key job_id). |
| DynamoDB — state lock | <prefix>_tf_locks | OpenTofu state lock (hash key LockID). |
| CloudWatch log group | /<prefix>/runner | Runner logs (30-day retention). |
| CodeBuild project | <prefix>-runner | The ephemeral runner (see below). |
| Runner IAM role | <prefix>-runner-role | Assumed by CodeBuild; scoped to the bucket, the three tables, its logs, and sts:AssumeRole on the deploy role only. |
| Deploy IAM role | <prefix>-deploy-role | Broad-by-design role the runner assumes with a module-scoped session policy (see the security model). |
| Operator IAM policy | <prefix>-operator | You attach this to your own engineer identity — it's how a human drives StrataCTL. |
All resource names derive from name_prefix, so a second, isolated plane is just a second prefix. Everything billable is serverless/on-demand (PAY_PER_REQUEST tables, CodeBuild per build, S3/logs usage).
tofu output emits ready-to-use values, including a paste-ready [customer] block for ~/.stratactl/config.toml (bucket + table names + project) so StrataCTL resolves the plane with no manual config. The Developer Edition install records these automatically — see Dashboards as code for how stratactl dashboards reuses them.
The ephemeral runner
The CodeBuild project is the runner. It uses no source and an inline buildspec; the per-job spec (action, module, artifact reference, state backend, table names) is injected as environment overrides at StartBuild time. On each run it:
- Ensures OpenTofu is present (installs the pinned
tofu_version, default 1.8.5,
unless the image is prebaked).
- Ensures the
stratarunner package is present (from ans3://wheel or a pip spec
via STRATA_PKG — the CLI passes the launching version so the runner tracks it).
- Ensures
cryptographyis present for offline bundle-signature verification. - Runs
python3 -m strata.runner, which verifies the bundle, runs OpenTofu, and records
status/outputs.
It runs on a standard AWS CodeBuild image by default (runner_image), or on a prebaked ECR image where tofu + strata already exist, so cold builds stay fast.
OpenTofu state on an S3 backend
State durability is the whole point, and it works at two layers.
Module and platform installs. When the runner deploys a bundle, it runs OpenTofu against your S3 backend — if the bundle declares no backend, the runner injects backend "s3" {} and initializes it with your plane's values:
-backend-config=bucket=<your strataci bucket>
-backend-config=key=<module state key>
-backend-config=region=<region>
-backend-config=dynamodb_table=<prefix>_tf_locks # state lock
-backend-config=encrypt=trueState is pulled from S3 on init and pushed on apply, with the tf_locks table providing concurrency safety. Nothing lives on the runner after it exits; update and uninstall reuse the same remote state, so the lifecycle is fully reproducible from your bucket.
StrataCI's own state. The plane can't sit its backend inside the very bucket it is creating, so bootstrap applies with local state and then uploads that state file to s3://<bucket>/bootstrap/terraform.tfstate. That makes teardown durable and machine-independent: bootstrap --destroy pulls the state back from S3 (so you can tear down from any machine, not just the one that installed it), writes a lifecycle override that disables prevent_destroy and sets force_destroy so the plane can delete itself, and runs tofu destroy. Enable S3 versioning (the bucket already has it) as a backstop.
Delivery: how bundles reach the runner
The runner never pulls arbitrary source at deploy time — it runs a signed bundle whose OpenTofu, manifest, and defaults travel together and are verified offline against Shaleio's signing key before anything executes. Where that bundle comes from depends on the edition:
- Developer Edition — HQ-free. The artifact resolves from a public URL, your own S3
bucket, or the conventional bucket key; no StrataHQ contact and no license contract. See Developer Edition.
- Enterprise — account-entitled. StrataCTL fetches the account-entitled signed
runtime/module bundle, resolved from your configuration; the runner verifies its signature before running OpenTofu. See Container image & supply chain and Delivery & teardown.
Delivery mode controls what's left behind: local (the default, and always the mode for the platform) caches the verified bundle into your bucket so later update/uninstall run with no outbound contact — including in air-gapped environments; managed leaves nothing behind and re-fetches at teardown. Full detail in Delivery & teardown.
Security model
Two IAM roles, deliberately split:
- The runner role can touch only the StrataCI bucket, the three tables, and its own log
group — plus assume the deploy role. It holds no broad deploy permissions.
- The deploy role is broad on purpose (it must be a superset of everything any module
or the platform can provision — VPC, ECS, ALB, Cognito, the AWS security services, and so on). The runner assumes it with a session policy derived from the bundle's declared permissions, so the effective permissions are deploy role ∩ what the module asked for. A module can never deploy beyond what its manifest declares.
The operator policy is what a human attaches to their own identity; StrataCTL acts as you, so what you can deploy is bounded by your own IAM. Shaleio never receives credentials. See Security posture.
Teardown
stratactl --profile <profile> --region <region> bootstrap --destroyBecause the state is stored in your bucket and pulled back on destroy, teardown does not depend on the machine that ran the install. Uninstall your modules and platform first (stratactl uninstall <module>, stratactl dev uninstall), then destroy the plane. See the Installation Guide and the FAQ.
Shaleio