# dokploy_vault_provider (Resource)

A secret-vault connection Dokploy can pull runtime secrets from at deploy time, referenced from other resources' `env` attributes as `${{vault.<name>.<key>}}` - a plain string this provider does not parse or validate. One of six provider types: `hashicorp` (also covers OpenBao, which speaks the same wire protocol), `infisical`, `aws`, `doppler`, `azure`, `scaleway`.

~> **Secrets are masked on every read, never echoed back.** Dokploy returns every secret field in this resource's config blocks as the literal string `********`, on create, read, and update alike. This provider cannot detect a config value changed in the Dokploy UI - Read leaves every config block exactly as Terraform last wrote it, secret and non-secret fields alike. Manage a vault provider's config only through Terraform. A UI-side edit persists undetected until the next apply that modifies this resource; that apply's full-body update overwrites it with Terraform's config.

~> **A config block cannot be recovered by `terraform import`.** The imported resource's config blocks are left null; re-supply the block matching the provider's actual type in configuration, and the first `terraform apply` writes it as a full-body update, not a partial patch.

~> **Dokploy never validates vault credentials on create or update**, for any provider type - only `verify_connection = true` reaches the real vault, through `vaultProvider.testConnection`, before the write. A misconfigured vault provider otherwise applies successfully and only fails the next deploy that needs a secret from it.

## Example Usage

```terraform
variable "vault_token" {
  type      = string
  sensitive = true
}

resource "dokploy_vault_provider" "secrets" {
  name = "prod-vault"

  hashicorp = {
    url   = "https://vault.example.com:8200"
    token = var.vault_token
    # namespace = "admin" # Vault Enterprise only; omit for OSS Vault or OpenBao.
    # mount     = "secret" # KV mount path; this is the server's own default.
  }

  assignments = [
    {
      project_id = dokploy_project.example.id
      # environment_ids = [] # Omit (or leave empty) to make every
      #                        environment in the project eligible.
    }
  ]

  # Reaches the real vault through vaultProvider.testConnection before
  # writing anything, so a bad token or an unreachable server fails the
  # apply instead of silently creating a broken vault provider.
  verify_connection = true
}

# Reference a secret from this vault provider in another resource's `env`.
# Dokploy resolves ${{vault.<name>.<key>}} at deploy time; this provider
# passes the string through untouched - it does not parse or validate it.
# The doubled `$$` escapes Terraform's own `${...}` interpolation so the
# literal `${{...}}` reaches Dokploy.
#
# resource "dokploy_application" "api" {
#   # ...
#   env = <<-EOT
#     DATABASE_PASSWORD=$${{vault.prod-vault.database_password}}
#   EOT
# }
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `assignments` (Attributes List) Projects (and optionally specific environments within them) this vault provider is available to. An empty list is legal - `assignments = []` is accepted and echoed back by the server (internal/client/doc.go, wave 6c gate E). (see [below for nested schema](#nestedatt--assignments))
- `name` (String) Display name, 1-64 characters, matching `^[a-zA-Z0-9_-]+$`. Dokploy rejects a duplicate name; this provider pre-checks for one before ever sending a create request, so a collision fails cleanly rather than through the server's raw error (internal/client/doc.go, wave 6c).

### Optional

- `aws` (Attributes) AWS Secrets Manager connection. Exactly one of `hashicorp`, `infisical`, `aws`, `doppler`, `azure`, `scaleway` must be set.

~> This block's shape came from the OpenAPI contract alone, not a live probe (internal/client/doc.go, wave 6c) - this resource's own acceptance tests are the first live confirmation of it. (see [below for nested schema](#nestedatt--aws))
- `azure` (Attributes) Azure Key Vault connection. Every field is required at the API - Azure has no optional fields here. Exactly one of `hashicorp`, `infisical`, `aws`, `doppler`, `azure`, `scaleway` must be set.

~> This block's shape came from the OpenAPI contract alone, not a live probe (internal/client/doc.go, wave 6c). (see [below for nested schema](#nestedatt--azure))
- `doppler` (Attributes) Doppler connection. Exactly one of `hashicorp`, `infisical`, `aws`, `doppler`, `azure`, `scaleway` must be set. (see [below for nested schema](#nestedatt--doppler))
- `hashicorp` (Attributes) HashiCorp Vault or OpenBao connection. Exactly one of `hashicorp`, `infisical`, `aws`, `doppler`, `azure`, `scaleway` must be set. (see [below for nested schema](#nestedatt--hashicorp))
- `infisical` (Attributes) Infisical connection. Exactly one of `hashicorp`, `infisical`, `aws`, `doppler`, `azure`, `scaleway` must be set. (see [below for nested schema](#nestedatt--infisical))
- `scaleway` (Attributes) Scaleway Secret Manager connection. Exactly one of `hashicorp`, `infisical`, `aws`, `doppler`, `azure`, `scaleway` must be set. (see [below for nested schema](#nestedatt--scaleway))
- `verify_connection` (Boolean) Test the config against the real vault before writing, through `vaultProvider.testConnection`. Defaults to `false`. On failure the apply fails with the server's message and nothing is created or updated. This attribute is provider-only - Dokploy stores no server-side value for it - so `terraform import` always seeds it `false`.

### Read-Only

- `created_at` (String) Creation timestamp (server-side).
- `id` (String) Vault provider id.

<a id="nestedatt--assignments"></a>
### Nested Schema for `assignments`

Required:

- `project_id` (String) Id of the assigned project.

Optional:

- `environment_ids` (Set of String) Ids of specific environments within the project to restrict this assignment to. Omit (or set an empty list) to make every environment in the project eligible; the server stores and echoes an empty set for that case, not null (internal/client/doc.go, wave 6c).


<a id="nestedatt--aws"></a>
### Nested Schema for `aws`

Required:

- `access_key_id` (String, Sensitive) AWS access key id.
- `region` (String) AWS region for Secrets Manager, e.g. `us-east-1`.
- `secret_access_key` (String, Sensitive) AWS secret access key.

Optional:

- `endpoint` (String) Custom Secrets Manager endpoint, for a compatible service or a VPC endpoint. Omit to use AWS's default endpoint; the server has no default for this field.


<a id="nestedatt--azure"></a>
### Nested Schema for `azure`

Required:

- `client_id` (String) Azure AD application (client) id.
- `client_secret` (String, Sensitive) Azure AD application client secret.
- `tenant_id` (String) Azure AD tenant id.
- `vault_uri` (String) Azure Key Vault URI, e.g. `https://myvault.vault.azure.net/`.


<a id="nestedatt--doppler"></a>
### Nested Schema for `doppler`

Required:

- `service_token` (String, Sensitive) Doppler service token.

Optional:

- `config` (String) Doppler config name (the wire field is also named `config`; `config` is legal as an attribute name here since it is nested inside this block, not at the resource's top level). Omit to let Doppler infer it from the service token; the server has no default for this field.
- `project` (String) Doppler project slug. Omit to let Doppler infer it from the service token; the server has no default for this field.


<a id="nestedatt--hashicorp"></a>
### Nested Schema for `hashicorp`

Required:

- `token` (String, Sensitive) Vault authentication token.
- `url` (String) Vault (or OpenBao) server URL, e.g. `https://vault.example.com:8200`.

Optional:

- `mount` (String) KV secrets engine mount path. Defaults to `secret`.
- `namespace` (String) Vault Enterprise namespace. Omit for OSS Vault or OpenBao; the server has no default for this field.


<a id="nestedatt--infisical"></a>
### Nested Schema for `infisical`

Required:

- `client_id` (String) Infisical machine identity client id.
- `client_secret` (String, Sensitive) Infisical machine identity client secret.
- `environment_slug` (String) Infisical environment slug, e.g. `dev` or `prod`.
- `project_id` (String) Infisical project id.

Optional:

- `secret_path` (String) Path inside the Infisical project to read secrets from. Defaults to `/`.
- `site_url` (String) Infisical instance URL. Defaults to the Infisical Cloud URL.


<a id="nestedatt--scaleway"></a>
### Nested Schema for `scaleway`

Required:

- `project_id` (String) Scaleway project id.
- `secret_key` (String, Sensitive) Scaleway API secret key.

Optional:

- `api_url` (String) Scaleway Secret Manager API URL. Defaults to `https://api.scaleway.com`.
- `region` (String) Scaleway region. Defaults to `fr-par`.

## Import

Import is supported using the following syntax:

The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:

```shell
# Vault providers import by their own id.
#
# Dokploy masks every secret field as "********" on every read (gate R,
# internal/client/doc.go, wave 6c), so no config block can be recovered by
# import - it is left null in the imported state. Re-supply the block
# matching the provider's actual type (hashicorp, infisical, aws, doppler,
# azure, or scaleway) in configuration; the first `terraform apply` after
# import is a full-body update, not an empty plan.
terraform import dokploy_vault_provider.secrets v1a2b3c4d5e6f7g8h9i0j
```