--- layout: docs page_title: Programmatic best practices description: >- Best practices for managing Vault programmatically. --- # Best practices for programmatic Vault management It can be a challenge to enforce appropriate governance policies on resources created directly from the Vault CLI or API. The best way to manage Vault at scale is to [codify resource management](/vault/tutorials/operations/codify-mgmt-vault-terraform) with [Terraform](/terraform) and the [Terraform Vault provider](https://registry.terraform.io/providers/hashicorp/vault/latest). Terraform applies policy and governance using infrastructure as code (IaC) so you can programmatically manage Vault resources such as authentication methods, plugins, namespaces, and policies. For example, if you have have specific ACL or Sentinel policies that must apply to every Vault namespace, you can rely on Terraform to apply the correct governance policies every time you create a new namespace. ## Terraform recommendations - **Avoid reading or writing long-lived static secrets to Vault from Terraform**. Data read to, or written from, Terraform persists in the Terraform state file and any generated plan files. - **Encrypt the Terraform state file**. Protect the state file with a secure, encrypted backend. - **Follow the principle of least privilege**. Limit who has read/write access to your Terraform state file. - **Limit direct management of Vault resources**. Use [Sentinel policies](https://go.hashi.co/support-block-ns-manipulation-with-sentinel) to limit resource management permissions for resources that should be managed through Terraform. - **Use short-lived credentials**. Credentials persist in the Terraform state file. Short-lived credentials reduce the risk of exposure in the event of a compromised state file. ## Vault recommendations - **Use Vault-backed dynamic credentials for different cloud providers**. [Vault-backed dynamic credentials](/terraform/cloud-docs/workspaces/dynamic-provider-credentials/vault-backed) limits the need for unique dynamic provider credentials across different cloud providers so you can centralize sensitive data management with Vault while generating short-lived credentials with multiple cloud providers. - **Use the namespace attribute in resources and data sources**. Using the namespace attribute of a resource, instead of a provider alias, simplifies your configuration and avoids the need for multiple provider blocks. - **Use distinct token capabilities**. Use the minimal required Vault token capabilities to manage your Vault resources. For example, reading data from a KV data source and drift detection functionality only require the `read` capability. But managing the KV resource requires the `create` or `update` capability depending on whether the resource already exists. And removing the KV resource from the Terraform configuration requires the `delete` capability. - **Migrate existing resources to Terraform**. If you created Vault resources outside of your Terraform provisioning workflow, [migrate the un-managed resources](/vault/docs/configuration/programmatic-management#migrate). - **Use dynamic provider credentials for Vault when possible**. [Dynamic provider credentials](/terraform/cloud-docs/workspaces/dynamic-provider-credentials/vault-configuration) generate short-lived credentials as needed, which limits the need for static credentials and improves the security posture of your integration. - **Do not pass `address`, `token`, or `namespace` to the provider configuration block**. When you use dynamic provider credentials, Terraform populates the environment variable, `TFC_VAULT_ADDR` with `address` and the workspace environment variable, `TFC_VAULT_NAMESPACE`, with `namespace`. Terraform then uses the environment variables to retrieve a value for `token`. - **Do not hardcode Vault credentials**. If you cannot use dynamic provider credentials configure the Vault provider with environment variables. If you use dynamic credentials with the Terraform Vault provider, it means that Terraform manages the Vault token lifecycle. As a result, Vault **does not** create a child token and you cannot use provider arguments for managing the Vault child token (e.g., `token_name` argument).