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
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
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)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 ofhashicorp,infisical,aws,doppler,azure,scalewaymust 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)
azure(Attributes) Azure Key Vault connection. Every field is required at the API - Azure has no optional fields here. Exactly one ofhashicorp,infisical,aws,doppler,azure,scalewaymust 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)
doppler(Attributes) Doppler connection. Exactly one ofhashicorp,infisical,aws,doppler,azure,scalewaymust be set. (see below for nested schema)hashicorp(Attributes) HashiCorp Vault or OpenBao connection. Exactly one ofhashicorp,infisical,aws,doppler,azure,scalewaymust be set. (see below for nested schema)infisical(Attributes) Infisical connection. Exactly one ofhashicorp,infisical,aws,doppler,azure,scalewaymust be set. (see below for nested schema)scaleway(Attributes) Scaleway Secret Manager connection. Exactly one ofhashicorp,infisical,aws,doppler,azure,scalewaymust be set. (see below for nested schema)verify_connection(Boolean) Test the config against the real vault before writing, throughvaultProvider.testConnection. Defaults tofalse. 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 - soterraform importalways seeds itfalse.
Read-Only
created_at(String) Creation timestamp (server-side).id(String) Vault provider id.
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).
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.
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/.
Nested Schema for doppler
Required:
service_token(String, Sensitive) Doppler service token.
Optional:
config(String) Doppler config name (the wire field is also namedconfig;configis 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.
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 tosecret.namespace(String) Vault Enterprise namespace. Omit for OSS Vault or OpenBao; the server has no default for this field.
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.devorprod.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.
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 tohttps://api.scaleway.com.region(String) Scaleway region. Defaults tofr-par.
Import
Import is supported using the following syntax:
The terraform import command can be used, for example:
# 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