The arrstack engine returns `apps` alphabetically sorted regardless of the order they were written in, so modelling it as an ordered List makes any config whose order differs fail apply with "Provider produced inconsistent result after apply" and produce perpetual re-diffs. `apps` is semantically a set of app names, so it is now modelled as one. - Changes the `apps` attribute on `arrstack_secret_backend_role` from `types.List`/`schema.ListAttribute` to `types.Set`/`schema.SetAttribute` - Reads engine responses back via `types.SetValueFrom` - Updates unit tests for the set type and adds an order-insensitivity test proving a sorted engine response equals a differently-ordered config value - No other resources or data sources use the List-of-apps pattern Reviewed-on: #2 Co-authored-by: unkin-agent <unkin-agent@unkin.net> Co-committed-by: unkin-agent <unkin-agent@unkin.net>
terraform-provider-vault-secrets-arrstack
A Terraform/OpenTofu provider that manages the arrstack dynamic secrets engine
(vault-plugin-secrets-arrstack)
on HashiCorp Vault or OpenBao, so the engine's mount, config, and roles can be
driven declaratively (e.g. from terraform-vault). The engine mints short-lived
arrproxy API keys scoped to the arr apps (Sonarr, Radarr, Prowlarr).
Source address: artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/vault-secrets-arrstack
(declare it under the local name arrstack, so its resources are arrstack_*).
Resources
| Resource | Manages |
|---|---|
arrstack_secret_backend |
Mounts the engine at a path and writes its config (arrproxy base URL, request timeout, seeded admin token, optional CA cert). |
arrstack_secret_backend_role |
A role: apps (subset of sonarr/radarr/prowlarr), ttl, max_ttl. |
Usage
terraform {
required_providers {
arrstack = {
source = "artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/vault-secrets-arrstack"
version = "0.1.0"
}
}
}
provider "arrstack" {
# address / token fall back to VAULT_ADDR / VAULT_TOKEN.
}
resource "arrstack_secret_backend" "arrstack" {
path = "arrstack"
base_url = "https://arrstack.unkin.net"
admin_token = var.arrproxy_admin_token
}
resource "arrstack_secret_backend_role" "all" {
backend = arrstack_secret_backend.arrstack.path
name = "all"
apps = ["sonarr", "radarr", "prowlarr"]
ttl = 60
max_ttl = 86400
}
Notes
admin_tokenis write-only: Vault never returns it, so it is preserved in Terraform state and does not show drift.ca_certis likewise write-only and preserved; omit it to use the system trust store.- Writing
configmakes the engine authenticate against arrproxy as an admin, so a bad URL or token fails the apply. appsis required; entries must be a subset ofsonarr,radarr,prowlarr.
Import
terraform import arrstack_secret_backend.arrstack arrstack
terraform import arrstack_secret_backend_role.all arrstack/roles/all
Development
make build # build the provider binary
make install # install into ~/.terraform.d/plugins for local use
make test # unit tests (race)
make package # build the release zip
Releases are tag-driven (make patch|minor|major): a Woodpecker pipeline builds
terraform-provider-vault-secrets-arrstack_<version>_linux_amd64.zip and PUTs it
to the artifactapi terraform registry
(.../api/v2/remotes/terraform-unkin/files/terraform-unkin/vault-secrets-arrstack/<file>),
which signs it server-side. Install it via the bare source address above.