github mattrobinsonsre/terrapod v2.0.0-beta.3

one hour ago

Terrapod is a free, open-source, self-hosted platform replacement for Terraform Enterprise — remote runs, state, a registry, policy-as-code and RBAC around tofu and terraform, with Pulumi and Ansible coerced into the same flow. This is the third 2.0 beta, and it is mostly about making the Ansible configure operation and the caches behind it usable without reading the source.

Highlights

  • Every cache can now be inspected and emptied from the admin page — the package caches (galaxy, pypi, npm, go, nuget, pulumi) and the VCS archive cache join the CLI-binary and provider-binary caches already there. List, filter, totals per ecosystem and per repository, delete one artifact, or evict in bulk by age. Until now an operator could warm a cache and never see what was in it, how big it had grown, or drop one bad artifact without going to object storage by hand. New page: Caches.
  • A workspace chooses which run kind gets the prominent button — default_run_kind, on the workspace, the autodiscovery rule template and bulk update. A workspace whose Terraform half only maintains the Ansible inventory wants Configure under the cursor, not a plan. Ordering in the UI only: every kind the workspace offers stays available, and a kind it does not have is refused rather than stored and ignored.
  • A per-user light/dark theme — the UI defaults to light and each user switches from Account → Dark theme, stored per browser and server-rendered, so there is no flash of the wrong theme. No deployment-wide default and no Helm value; a user's own choice always wins.

Security

  • A credential is redacted from a run's log however short it is. The redactor skipped anything under 24 characters, so a short become_password or Ansible Vault passphrase reached the plan and configure logs in the clear — measured on 2.0.0-beta.2, a 15-character vault password appeared on every line of a configure. Below the floor a value is now matched on token boundaries rather than skipped, and the runner records that the weaker matcher is in use.

    One consequence to know about: a credential that happens to be a short common word — prod, main, test — will now blank that word wherever it stands alone in a run's output. Boundary matching leaves it alone inside a longer word, so production is untouched, but a standalone occurrence is replaced. That trade is deliberate; the alternative is a credential in the clear.

Bug Fixes

  • Cache warming never worked. POST /admin/package-cache/warm, POST /admin/oci/warm and GET /admin/warm-jobs/{id} all returned 500 — a Redis client was obtained the wrong way, so no warm job could be created and none could be read. Pre-seeding a cache ahead of sealing a deployment now works; it did not in beta.1 or beta.2.
  • A committed ansible.cfg is honoured again. The checkout directory was world-writable, which ansible refuses to trust, so an operator's own configuration was silently ignored and the documented behaviour was not the real one.
  • A collection's Python requirements no longer break an earlier collection's. They were installed one collection at a time, so the last to resolve won; they are resolved together now.
  • A configure can carry its own resource profile, and the run page shows a peak per phase. The phase was rejected with a 400 saying it had to be plan or apply, so a configure could not be sized at all — and on a composite run the single peak figure was the configure's, which is the wrong number to size a runner by.
  • A failed VCS fetch during run creation is a typed refusal, not a 500. The message is redacted and the fetch is retried once. An unreachable repository used to surface as an unhandled server error with no run and nothing to read.
  • The provider reads a workspace's configure attributes back correctly. terrapod_workspace went through the TFE-compatible surface, which strips Terrapod's own fields, so configure_enabled and its siblings came back null after a successful apply. The provider and the SDK use the native routes only now.
  • A workspace_id referring to a workspace created in the same plan resolves, and an empty one is a plan-time error rather than a server-side refusal. It was read as an omission, so it either failed with "Missing workspace" or was silently replaced by the provider's default.
  • A catalog item's configuration tarball is byte-identical for identical inputs. The gzip wrapper carried a timestamp, so two provisions of the same item a second apart produced different bytes.

Upgrading

  • opa moves to 1.22.3. It is pull-through cached rather than baked into an image, so a sealed or air-gapped deployment must have 1.22.3 in its mirror before upgrading, or policy evaluation starts failing. trivy and checkov are unchanged.
  • Everything else here is additive. A 1.x operator should read Upgrading to 2.0 first; the removals it lists are deliberate and each has a replacement.

Status

Beta — the 2.0 line is feature-complete and under review. Four findings from this release's own review are tracked rather than fixed and are worth knowing if you use the new cache surfaces: a bulk archive eviction stops at 5000 keys without saying so (#2491), the package listing and bulk evict are unbounded at scale (#2492), some git failures are classified in the wrong direction (#2493), and the eviction routes have no MCP tool (#2494).

Full Changelog: v2.0.0-beta.2...v2.0.0-beta.3

Don't miss a new terrapod release

NewReleases is sending notifications on new releases.