A secret can live in two kinds of place: Opafra's own store, which every workspace has, or a connection to a secret manager your team already runs. Plans reach either one through a reference, so a plan never holds a value.
The default store: Opafra#
Every secret you create in Opafra lives here unless you say otherwise: shared secrets on the Inventory, Secrets page, environment secret variables, and server credentials kept locally.
It is stored in Opafra's database, encrypted with a data key unique to your workspace. That data key is itself encrypted by a root key held outside the database, by whoever operates your Opafra deployment. The consequences:
- A copy of the database alone reveals no secret.
- One workspace's key opens nothing belonging to another workspace.
- A value goes in and never comes back out through the API. Reading a secret returns
••••••••; only a run that resolves its reference uses the value.
There is nothing to connect or configure. If your deployment's operator has not set the root key, the Secrets page says so and new secrets cannot be saved until they do.
Reference these secrets as secret://opafra/<key>, or reach an environment secret
variable from a plan as {{ secrets.KEY }}.
Connections: your own stores#
If your team already keeps secrets in HashiCorp Vault, Infisical, AWS Secrets Manager or GCP Secret Manager, connect it. A connection is:
- Named, for example
prod_vault. The name is what references use:secret://prod_vault/apps/db/password. - Per workspace. Each workspace has its own connections, as many as it needs, including
several of the same type (a
prod_vaultand astaging_vault). A reference resolves only through a connection of that name in the workspace running the plan; with no such connection, the step fails closed. - Managed by owners and admins. Only a workspace owner or admin can add, edit, test or remove a connection. Operators and viewers see each connection's name and type, and nothing of its configuration.
- Write-once for credentials. The token, key or client secret you enter is stored encrypted and never returned. Editing a connection shows the credential as stored; leave the field empty to keep it, or type a new one to replace it.
Opafra checks a connection before saving it, so a credential that cannot authenticate is rejected at that point rather than at the first run that needs it.
What Opafra does with a connection#
Opafra reads from a connection when a run resolves a secret://<connection name>/...
reference. It does not list or copy the secrets in your store, and the Secrets page does
not browse them.
It writes to a connection in one case only: a server whose SSH credential you chose to
keep there. Opafra then writes that credential under opafra/servers/<server name> in
the connection, a path it sets from the server name rather than asks for.
Give the connection's credential read access to the paths your plans reference, plus
write access under opafra/servers/ if you keep server credentials there.
Providers#
HashiCorp Vault#
| Field | Notes |
|---|---|
| Address | The Vault server URL |
| Token | The token Opafra authenticates with. Stored, never returned |
| Mount path | The KV v2 engine mount. Defaults to secret |
Give the token a policy scoped to the paths Opafra needs, rather than a root token.
Infisical#
| Field | Notes |
|---|---|
| Site URL | Defaults to https://app.infisical.com |
| Auth method | Universal auth (client ID and client secret), or a service token |
| Project and environment | Which project and which of its environments to read |
| Secret path | Defaults to / |
Prefer universal auth where you have the choice, because the credential can be rotated without editing the connection. Infisical's own notion of environment is independent of an Opafra environment: one connection points at one Infisical environment.
AWS Secrets Manager#
| Field | Notes |
|---|---|
| Region | Required |
| Access key ID and secret access key | The IAM credentials Opafra uses. The secret is stored, never returned |
| Session token | Optional, for temporary credentials |
GCP Secret Manager#
| Field | Notes |
|---|---|
| Project ID | Required |
| Service account JSON | A service account key. Stored, never returned |
A connection always carries its own credentials. It never borrows the identity of the machine Opafra runs on, because that machine serves every workspace and belongs to none.
Choosing where a secret lives#
If your team already runs a secret manager, connect it and reference the secrets where they already are, rather than making Opafra a second place they live. It gives you rotation, audit and access policy that Opafra deliberately does not reimplement.
If you have none, use Opafra's store. It is encrypted per workspace and needs no setup, which beats the alternative it exists to prevent: passwords pasted into plans.
Rotation#
Rotating a secret takes effect on the next run that resolves its reference. Plans do not need editing, because the plan names the reference and never the value. In Opafra's store, rotate by editing the secret and entering a new value; in a connection, rotate it in your own store.
Next steps#
- Connect a secret store for the procedure
- Secret references for the reference formats
- SSH credentials for keys, which follow the same rules