+
+## AppBinding
+
+Introduces a way to specify `connection information`, `credential`, and `parameters` that are necessary for communicating with an app or service.
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+
+## Vault Server Version
+
+Introduces the concept of `VaultServerVersion` to specify the docker images of `HashiCorp Vault`, `Unsealer`, and `Exporter`.
+
+- [VaultServerVersion](/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion)
+
+## Vault Server
+
+A `VaultServer` is a `Kubernetes CustomResourceDefinition (CRD)` which is used to deploy a `HashiCorp Vault` server on Kubernetes clusters in a Kubernetes native way. Introduces the concept of `VaultServer` for configuring a HashiCorp Vault server in a Kubernetes native way.
+
+- [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+
+### Vault Unsealer Options
+When a `Vault` server is started, it starts in a `sealed` state. In this state, Vault is configured to know where and how to access the physical storage, but doesn't know how to decrypt any of it.
+
+`Unsealing` is the process of obtaining the plaintext root key necessary to read the decryption key to decrypt the data, allowing access to the Vault. Initializing & Unsealing Vault servers can be a tedious job.
+Introduces to various methods of automatically `Initialization` & `Unsealing` Vault Servers.
+
+- [Overview](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview)
+- [AWS KMS and SSM](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/aws_kms_ssm)
+- [Azure Key Vault](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/azure_key_vault)
+- [Google KMS GCS](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/google_kms_gcs)
+- [Kubernetes Secret](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/kubernetes_secret)
+
+### Vault Server Storage
+The `storage backend` represents the location for the durable storage of Vault's information. Each backend has pros, cons, advantages, and trade-offs. For example, some backends support `High Availability - HA` while others provide a more robust backup and restoration process. Introduces to various `Storage Backend` options supported by `KubeVault`.
+
+- [Overview](/docs/v2025.11.21/concepts/vault-server-crds/storage/overview)
+- [Azure](/docs/v2025.11.21/concepts/vault-server-crds/storage/azure)
+- [DynamoDB](/docs/v2025.11.21/concepts/vault-server-crds/storage/dynamodb)
+- [Etcd](/docs/v2025.11.21/concepts/vault-server-crds/storage/etcd)
+- [GCS](/docs/v2025.11.21/concepts/vault-server-crds/storage/gcs)
+- [In Memory](/docs/v2025.11.21/concepts/vault-server-crds/storage/inmem)
+- [MySQL](/docs/v2025.11.21/concepts/vault-server-crds/storage/mysql)
+- [PosgreSQL](/docs/v2025.11.21/concepts/vault-server-crds/storage/postgresql)
+- [AWS S3](/docs/v2025.11.21/concepts/vault-server-crds/storage/s3)
+- [Swift](/docs/v2025.11.21/concepts/vault-server-crds/storage/swift)
+- [Consul](/docs/v2025.11.21/concepts/vault-server-crds/storage/consul)
+- [Raft](/docs/v2025.11.21/concepts/vault-server-crds/storage/raft)
+
+### Authentication Methods for Vault Server
+`Auth methods` are the components in Vault that perform authentication and are responsible for assigning identity and a set of policies to a user. In all cases, Vault will enforce authentication as part of the request processing. In most cases, Vault will delegate the authentication administration and decision to the relevant configured external auth method (e.g., Amazon Web Services, GitHub, Google Cloud Platform, Kubernetes, Microsoft Azure, Okta, JWT/OIDC).
+
+Having multiple auth methods enables you to use an auth method that makes the most sense for your use case of `Vault` and your organization.
+Introduces to various `Authentication methods` supported by `KubeVault`.
+
+- [Overview](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/overview)
+- [AWS IAM Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/aws-iam)
+- [Kubernetes Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/kubernetes)
+- [TLS Certificates Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/tls)
+- [Token Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/token)
+- [Userpass Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/userpass)
+- [GCP IAM Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/gcp-iam)
+- [Azure Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/azure)
+- [JWT/OIDC Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/jwt-oidc)
+
+
+
+
+## Secret Engine
+
+`SecretEngine` is a Kubernetes `Custom Resource Definition`(CRD). It provides a way to enable and configure a Vault secret engine. Introduces to `SecretEngine` CRD, fields, & it's various use cases.
+
+- [Secret Engine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+
+### Secret Engine Roles
+In a `Secret Engine`, a `role` describes an identity with a set of `permissions`, `groups`, or `policies` you want to attach a user of the Secret Engine. Introduces to various roles supported by `KubeVault`.
+
+- [AWSRole](/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole)
+- [GCPRole](/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole)
+- [AzureRole](/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/azurerole)
+- [PKIRole](/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/pkirole)
+- [MongoDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb)
+- [MySQLRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mysql)
+- [PostgresRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole)
+- [ElasticsearchRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/elasticsearch)
+- [MariaDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mariadb)
+- [RedisRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/redis)
+
+### Secret Access Request
+A `SecretAccessRequest` is a `Kubernetes CustomResourceDefinition (CRD)` which allows a user to request a Vault server for `credentials` in a Kubernetes native way. A `SecretAccessRequest` can be created under various roleRef e.g: `AWSRole`, `GCPRole`, `ElasticsearchRole`, `MongoDBRole`, etc. Introduces to `SecretAccessRequest` CRD, fields & it's various use cases.
+
+- [SecretAccessRequest](/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request)
+
+### Secret Role Binding
+A `SecretRoleBinding` is a `Kubernetes CustomResourceDefinition (CRD)` which allows a user to bind a set of `roles` to a set of `users`. Using the `SecretRoleBinding` it’s possible to bind various roles e.g: `AWSRole`, `GCPRole`, `ElasticsearchRole`, `MongoDBRole`, etc. to Kubernetes `ServiceAccounts`.
+
+- [SecretRoleBinding](/docs/v2025.11.21/concepts/secret-engine-crds/secret-role-binding)
+
+
+
+
+## Vault Policy
+
+Everything in the Vault is path-based, and policies are no exception. Policies provide a declarative way to grant or forbid access to certain operations in Vault. Policies are `deny` by default, so an empty policy grants no permission in the system.
+
+- [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy): is used to create, update or delete Vault policies.
+- [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding): is used to create Vault auth roles associated with an authentication type/entity and a set of Vault policies.
+
+
+
diff --git a/content/docs/v2025.11.21/concepts/_index.md b/content/docs/v2025.11.21/concepts/_index.md
new file mode 100755
index 000000000..6a3b66cd9
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/_index.md
@@ -0,0 +1,16 @@
+---
+title: Concepts | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: concepts
+ name: Concepts
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/architecture.md b/content/docs/v2025.11.21/concepts/architecture.md
new file mode 100644
index 000000000..c19031ede
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/architecture.md
@@ -0,0 +1,38 @@
+---
+title: KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: concepts-architecture
+ name: Architecture
+ parent: concepts
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+
+
+
+# Architecture
+
+KubeVault operator is composed of the following controllers:
+
+- A **Vault Server controller** that deploys Vault in Kubernetes clusters. It also injects unsealer and stastd exporter as sidecars to perform unsealing and monitoring respectively.
+
+- An **Auth controller** that enables auth methods in Vault.
+
+- A **Policy controller** that manages Vault policies and also binds Vault policies with Kubernetes service accounts.
+
+- A **Secret Engine controller** that enables and configures Vault [secret engines](https://www.vaultproject.io/docs/secrets/index.html) based on the given configuration.
+
+- A set of **Role controllers** that configure secret engine roles that are used to generate credentials.
+
+- A set of **AccessKeyRequest controllers** that generate and issue credentials to the user for various secret engine roles.
diff --git a/content/docs/v2025.11.21/concepts/backup-restore/_index.md b/content/docs/v2025.11.21/concepts/backup-restore/_index.md
new file mode 100644
index 000000000..8325ed900
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/backup-restore/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Backup Restore | Concepts | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: backup-restore-concepts
+ name: Backup & Restore (Stash)
+ parent: concepts
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/backup-restore/overview.md b/content/docs/v2025.11.21/concepts/backup-restore/overview.md
new file mode 100644
index 000000000..4fc6c432c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/backup-restore/overview.md
@@ -0,0 +1,87 @@
+---
+title: Vault Backup Restore Overview | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: overview-backup-restore-concepts
+ name: Overview
+ parent: backup-restore-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/README).
+
+# Backup & Restore Vault Using Stash
+
+KubeVault uses [Stash](https://stash.run) to backup and restore Vault. Stash by AppsCode is a cloud native data backup and recovery solution for Kubernetes workloads. Stash utilizes [restic](https://github.com/restic/restic) to securely backup stateful applications to any cloud or on-prem storage backends (for example, S3, GCS, Azure Blob storage, Minio, NetApp, Dell EMC etc.).
+
+## How Backup Works
+
+The following diagram shows how Stash takes a backup of a Vault cluster. Open the image in a new tab to see the enlarged version.
+
+
+
+ Fig: Vault Backup Overview
+
+
+The backup process consists of the following steps:
+
+1. At first, a user creates a secret with access credentials of the backend where the backed up data will be stored.
+
+2. Then, the user creates a `Repository` crd that specifies the backend information along with the secret that holds the credentials to access the backend.
+
+3. Then, the user creates a `BackupConfiguration` crd targeting the [AppBinding CRD](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) of the desired Vault cluster. The `BackupConfiguration` object also specifies the `Task` to use to take backup of the Vault cluster.
+
+4. Stash operator watches for `BackupConfiguration` crd.
+
+5. Once Stash operator finds a `BackupConfiguration` crd, it creates a CronJob with the schedule specified in `BackupConfiguration` object to trigger backup periodically.
+
+6. On the next scheduled slot, the CronJob triggers a backup by creating a `BackupSession` crd.
+
+7. Stash operator also watches for `BackupSession` crd.
+
+8. When it finds a `BackupSession` object, it resolves the respective `Task` and `Function` and prepares a Job definition to take backup.
+
+9. Then, it creates the Job to take backup the targeted Vault cluster.
+
+10. The backup Job reads necessary information to connect with the Vault from the `AppBinding` crd. It also reads backend information and access credentials from `Repository` crd and Storage Secret respectively.
+
+11. Then, the Job dumps snapshot from the targeted Vault and uploads the output to the backend. Stash stores the dumped files temporarily before uploading into the backend. Hence, you should provide a PVC template using `spec.interimVolumeTemplate` field of `BackupConfiguration` crd to use to store those dumped files temporarily.
+
+12. Finally, when the backup is completed, the Job sends Prometheus metrics to the Pushgateway running inside Stash operator pod. It also updates the `BackupSession` and `Repository` status to reflect the backup procedure.
+
+## How Restore Process Works
+
+The following diagram shows how Stash restores backed up data into a Vault cluster. Open the image in a new tab to see the enlarged version.
+
+
+
+ Fig: Vault Restore Process
+
+
+The restore process consists of the following steps:
+
+1. At first, a user creates a `RestoreSession` crd targeting the `AppBinding` of the desired Vault where the backed up data will be restored. It also specifies the `Repository` crd which holds the backend information and the `Task` to use to restore the target.
+
+2. Stash operator watches for `RestoreSession` object.
+
+3. Once it finds a `RestoreSession` object, it resolves the respective `Task` and `Function` and prepares a Job definition to restore.
+
+4. Then, it creates the Job to restore the target.
+
+5. The Job reads necessary information to connect with the Vault from respective `AppBinding` crd. It also reads backend information and access credentials from `Repository` crd and Storage Secret respectively.
+
+6. Then, the job downloads the backed up data from the backend and insert into the desired Vault. Stash stores the downloaded files temporarily before inserting into the targeted Vault. Hence, you should provide a PVC template using `spec.interimVolumeTemplate` field of `RestoreSession` crd to use to store those restored files temporarily.
+
+7. Finally, when the restore process is completed, the Job sends Prometheus metrics to the Pushgateway and update the `RestoreSession` status to reflect restore completion.
+
+## Next Steps
+
+- Backup your Vault cluster using Stash following the guide from [here](/docs/v2025.11.21/guides/backup-restore/overview).
diff --git a/content/docs/v2025.11.21/concepts/overview.md b/content/docs/v2025.11.21/concepts/overview.md
new file mode 100644
index 000000000..48b88936b
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/overview.md
@@ -0,0 +1,97 @@
+---
+title: What is KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: what-is-kubevault-concepts
+ name: Overview
+ parent: concepts
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Overview
+
+## What is KubeVault
+
+KubeVault operator is a Kubernetes controller for [HashiCorp Vault](https://www.vaultproject.io/). Vault is a tool for secrets management, encryption as a service, and privileged access management. Deploying, maintaining, and managing Vault in Kubernetes could be challenging. KubeVault operator eases these operational tasks so that developers can focus on solving business problems.
+
+## Why use KubeVault
+
+KubeVault operator makes it easy to deploy, maintain and manage Vault servers in Kubernetes. It covers automatic initialization and unsealing, and securely stores unseal keys and root tokens in a cloud KMS (Key Management Service) service. It provides the following features:
+
+- Deploy TLS Secured [Vault Server](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+- Manage Vault Server [TLS using Cert-manager](/docs/v2025.11.21/concepts/tls-encryption/overview)
+- Automate [Initialization & Unseal process of Vault Servers](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview)
+- Add Durability to Vault's Data using [Storage Backend](/docs/v2025.11.21/concepts/vault-server-crds/storage)
+- Enable & Configure [Secret Engines](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- Create & Configure [Vault Roles](/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole)
+- Manage [Vault Policy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) & [Vault Policy Binding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding)
+- Manage user privileges using [SecretAccessRequest](/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request)
+- Manage user privileges using [SecretRoleBinding](/docs/v2025.11.21/concepts/secret-engine-crds/secret-role-binding)
+- Inject Vault secrets into K8s resources
+- Automate tedious operations using [KubeVault CLI](/docs/v2025.11.21/reference/cli)
+- Monitor Vault using Prometheus & Grafana Dashboard
+
+## Core features
+
+### Deploy TLS Secured Vault Server
+A VaultServer is a Kubernetes CustomResourceDefinition (CRD) which is used to deploy a HashiCorp Vault server on Kubernetes clusters in a Kubernetes native way.
+
+In production, Vault should always use TLS to provide secure communication between clients and the Vault server. You can deploy a TLS secure VaultServer using the KubeVault operator either with the self-signed certificate or with cert-manager to manage VaultServer TLS.
+
+### Manage Vault Server TLS using Cert-manager
+In production, Vault should always use TLS to provide secure communication between clients and the Vault server. KubeVault lets you use cert-manager to manage VaultServer TLS.
+
+### Automate Initialization & Unseal process of Vault Servers
+
+When a Vault server is started, it starts in a sealed state. In a sealed state, almost no operation is possible with a Vault server. So, you will need to unseal Vault.
+
+KubeVault operator provides automatic initialization and unsealing facility. When you deploy or scale up a Vault server, you don't have to worry about unsealing new Vault pods. The KubeVault operator will do it for you. Also, it provides various secure ways to store unseal keys and root token, e.g: Azure Key Vault, AWS KMS SSM, Google KMS GCS or Kubernetes Secret.
+
+### Enable & Configure Secret Engines
+Secrets engines are components which store, generate, or encrypt data. Secrets engines are incredibly flexible, so it is easiest to think about them in terms of their function. Secrets engines are provided with some set of data, they take some action on that data, and they return a result.
+
+KubeVault lets you enable & configure various Secret Engines e.g: AWS, Azure, Google Cloud KMS, MySQL, MariaDB, Elasticsearch, MongoDB, Postgresql, etc. in a Kubernetes native way.
+
+### Create & Configure Vault Roles
+In a Secret Engine, a role describes an identity with a set of permissions, groups, or policies you want to attach to a user of the Secret Engine.
+
+KubeVault operator lets you create various roles e.g. AWSRole, AzureRole, GCPRole, MySQLRole, MariaDBRole, ElasticsearchRole, MongoDBRole, PostgresRole, etc. in a SecretEngine.
+
+### Manage Vault Policy & Vault Policy Binding
+Policies in Vault provide a declarative way to grant or forbid access to certain paths and operations in Vault. You can create, delete and update policy in Vault in a Kubernetes native way using KubeVault operator. KubeVault operator also provides a way to bind Vault policy with Kubernetes service accounts using the Vault Policy Binding. ServiceAccounts will have the permissions that are specified in the policy.
+
+### Manage user privileges using SecretAccessRequest
+A SecretAccessRequest is a Kubernetes CustomResourceDefinition (CRD) which allows a user to request a Vault server for credentials in a Kubernetes native way. A SecretAccessRequest can be created under various roles that can be enabled in a SecretEngine e.g: AWSRole, GCPRole, ElasticsearchRole, MongoDBRole, etc. This is a more human friendly way to manage DB privileges.
+
+KubeVault operator lets you manage your DB user privileges with dynamic secrets rather than hard-coded credentials using SecretAccessRequest. This means that services that need to access a database no longer need to hardcode credentials: they can request them from Vault. Thus granting, revoking and monitoring user privileges is extremely easy with KubeVault.
+
+### Manage user privileges using SecretRoleBinding
+A SecretRoleBinding is a Kubernetes CustomResourceDefinition (CRD) which allows a user to bind a set of roles to a set of users. Using the SecretRoleBinding it’s possible to bind various roles e.g: AWSRole, GCPRole, ElasticsearchRole, MongoDBRole, etc. to Kubernetes ServiceAccounts. This way is more machine friendly and convenient for running your application with specific permissions.
+
+Injecting Vault Secrets into Kubernetes resources requires specific permissions & using SecretRoleBinding it’s very easy to bind a set of policies to a set of Kubernetes Service Accounts.
+
+### Inject Vault Secret into Kubernetes resources
+Secrets Store CSI Driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a Container Storage Interface (CSI) volume. It allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+KubeVault operator works seamlessly with Secrets Store CSI Driver. This is one of the recommended ways to mount Vault Secrets into Kubernetes resources along with Vault Agent Sidecar Injector.
+
+Secrets Store CSI Driver requires a SecretProviderClass which is a namespaced resource that is used to provide driver configurations and provider-specific parameters to the CSI driver. Writing these SecretProviderClass can be a tedious job, but KubeVault CLI lets you generate SecretProviderClass using simple CLI commands.
+
+### Automate tedious operations using KubeVault CLI
+KubeVault CLI is an integral part of the KubeVault operator. It makes various tasks simple while working with the operator e.g. Approve/Deny/Revoke SecretAccessRequest, Generate SecretProviderClass, Get, Set, List, Sync Vault Unseal Keys and Vault Root Token, etc.
+
+### Monitor Vault using Prometheus & Grafana Dashboard
+You can monitor Vault servers using the Vault dashboard.
+
+
+KubeVault operator has native support for monitoring via [Prometheus](https://prometheus.io/). You can use builtin [Prometheus](https://github.com/prometheus/prometheus) scraper or [Prometheus Operator](https://github.com/coreos/prometheus-operator) to monitor KubeVault operator.
diff --git a/content/docs/v2025.11.21/concepts/policy-crds/_index.md b/content/docs/v2025.11.21/concepts/policy-crds/_index.md
new file mode 100755
index 000000000..c2e9b4578
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/policy-crds/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | Vault Policy
+menu:
+ docs_v2025.11.21:
+ identifier: policy-crds-concepts
+ name: Vault Policy
+ parent: concepts
+ weight: 50
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/policy-crds/vaultpolicy.md b/content/docs/v2025.11.21/concepts/policy-crds/vaultpolicy.md
new file mode 100644
index 000000000..d1d470724
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/policy-crds/vaultpolicy.md
@@ -0,0 +1,125 @@
+---
+title: VaultPolicy | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: vaultpolicy-policy-crds
+ name: VaultPolicy
+ parent: policy-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# VaultPolicy
+
+## What is VaultPolicy
+
+A `VaultPolicy` is a Kubernetes `CustomResourceDefinition` (CRD) which represents Vault server [policies](https://www.vaultproject.io/docs/concepts/policies.html) in a Kubernetes native way.
+
+When a `VaultPolicy` is created, the KubeVault operator will create a policy in the associated Vault server according to specification. If the `VaultPolicy` CRD is deleted, the respective policy will also be deleted from the Vault server.
+
+
+
+## VaultPolicy CRD Specification
+
+Like any official Kubernetes resource, a `VaultPolicy` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `VaultPolicy` object is shown below:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: secret-admin
+ namespace: default
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+ }
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+Here, we are going to describe the various sections of the `VaultPolicy` crd.
+
+### VaultPolicy Spec
+
+VaultPolicy `spec` contains policy and vault information necessary to create a [Vault policy](https://www.vaultproject.io/docs/concepts/policies.html). `VaultPolicy` CRD has the following fields in the `.spec` section.
+
+#### spec.vaultRef
+
+`spec.vaultRef` is a `required` field that specifies the name of an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference which is used to connect with a Vault server. AppBinding must be on the same namespace with VaultPolicy object.
+
+```yaml
+spec:
+ vaultRef:
+ name: vault-app
+```
+
+#### spec.vaultPolicyName
+
+To resolve the naming conflict, KubeVault operator will generate policy names in Vault server in this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. `spec.vaultPolicyName` is an `optional` field. If set, it will overwrite the generated policy name in Vault server.
+
+```yaml
+spec:
+ vaultPolicyName: my-custom-policy
+```
+
+#### spec.policyDocument
+
+`spec.policyDocument` is an `optional` field that specifies the vault policy in `hcl` format. Both `spec.policyDocument` and `spec.policy` cannot be empty at once.
+
+```yaml
+spec:
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+ }
+ path "abc/*" {
+ capabilities = ["read"]
+ }
+```
+
+#### spec.policy
+
+Vault uses [HCL](https://github.com/hashicorp/hcl) as its configuration language. HCL is also fully JSON compatible. That is, JSON can be used as a completely valid input to a system expecting HCL. This helps to make systems interoperable with other systems.
+
+`spec.policy` is an `optional` field that accepts the vault policy in `YAML` format. This can be more convenient since Kubernetes uses YAML as its native configuration language.
+
+```yaml
+spec:
+ policy:
+ path:
+ secret/*:
+ capabilities:
+ - create
+ - read
+ - update
+ - delete
+ - list
+ abc/*:
+ capabilities:
+ - read
+```
+
+### VaultPolicy Status
+
+VaultPolicy `status` shows the status of a Vault Policy. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the policy successfully applied to Vault or failed.
+
+- `conditions` : Represents the latest available observations of a VaultPolicy's current state.
diff --git a/content/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding.md b/content/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding.md
new file mode 100644
index 000000000..1f9e2f26c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding.md
@@ -0,0 +1,178 @@
+---
+title: VaultPolicyBinding | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: vaultpolicybinding-policy-crds
+ name: VaultPolicyBinding
+ parent: policy-crds-concepts
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# VaultPolicyBinding
+
+## What is VaultPolicyBinding
+
+A `VaultPolicyBinding` is a Kubernetes `CustomResourceDefinition` (CRD) which binds Vault server [policies](https://www.vaultproject.io/docs/concepts/policies.html) to an auth method role in a Kubernetes native way.
+
+When a `VaultPolicyBinding` is created, the KubeVault operator will create an auth role according to CRD (CustomResourceDefinition) specification.
+If the user deletes the VaultPolicyBinding CRD, then the respective role will also be deleted from Vault.
+
+
+
+Auth method roles are associated with an authentication type/entity and a set of Vault policies. Currently supported auth methods for VaultPolicyBinding:
+
+- [Kubernetes Auth Method](https://www.vaultproject.io/docs/auth/kubernetes.html): The Kubernetes auth method can be used to authenticate with Vault using a Kubernetes Service Account Token. This method of authentication makes it easy to introduce a Vault token into a Kubernetes Pod.
+
+## VaultPolicyBinding CRD Specification
+
+Like any official Kubernetes resource, a `VaultPolicyBinding` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `VaultPolicyBinding` object is shown below:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: admin-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: secret-admin
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "demo sa"
+ serviceAccountNamespaces:
+ - "demo"
+ ttl: "1000"
+ maxTTL: "2000"
+ period: "1000"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+Here, we are going to describe the various sections of the `VaultPolicyBinding` crd.
+
+### VaultPolicyBinding Spec
+
+VaultPolicyBinding `spec` contains information that is necessary for creating an auth role.
+
+```yaml
+spec:
+ vaultRef:
+ name:
+ vaultRoleName:
+ policies:
+ - name:
+ ref:
+ subjectRef:
+ kubernetes:
+ path:
+ serviceAccountNames:
+ - "sa1"
+ - "sa2"
+ serviceAccountNamespaces:
+ - "ns1"
+ ttl:
+ maxTTL:
+ period:
+```
+
+VaultPolicyBinding spec has the following fields:
+
+#### spec.vaultRef
+
+`spec.vaultRef` is a `required` field that specifies the name of an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains information to communicate with a Vault server. The AppBinding object must be in the same namespace with VaultPolicyBinding object.
+
+```yaml
+spec:
+ vaultRef:
+ name: vault-app
+```
+
+#### spec.vaultRoleName
+
+To avoid naming conflict, KubeVault operator will generate role names in Vault server in this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. `spec.vaultRoleName` is an `optional` field. If set, it will be used instead of the auto-generated role name.
+
+```yaml
+spec:
+ vaultRoleName: my-custom-role
+```
+
+#### spec.policies
+
+`spec.policies` is a `required` field that specifies a list of vault policy references. Each item of the list
+can be **either** a vault policy name **or** VaultPolicy CRD name.
+
+- `name`: Specifies the [vault policy](https://www.vaultproject.io/docs/concepts/policies.html) name.
+ This name should be returned by `vault read sys/policy` command.
+
+- `ref`: Specifies the name of [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) crd object. The KubeVault operator will get the vault policy name
+ from the crd object.
+
+```yaml
+spec:
+ policies:
+ - name: policy1
+ - ref: policy2
+```
+
+#### spec.subjectRef
+
+`spec.subjectRef` is a `required` field that specifies the reference of vault users who will be granted
+token with mentioned policies.
+
+- `kubernetes`: Refers to vault users who will be authenticated via the Kubernetes auth method.
+
+ - `path` : `Optional`. Specifies the path where the Kubernetes auth is enabled. The default value is `kubernetes`.
+
+ - `serviceAccountNames` : `Required`. Specifies the list of service account names.
+ They will have access to use this role. If set to `"*"` all names are allowed,
+ both this and serviceAccountNamespaces **cannot** be `"*"`.
+
+ - `serviceAccountNamespaces` : `Required`. Specifies a list of namespaces allowed to access this role. This value set to "*" means
+ all namespaces are allowed.
+
+ - `ttl` : `Optional`. Specifies the TTL period of the token issued using this role in seconds. Default value "0".
+
+ - `maxTTL` : `Optional`. Specifies the maximum allowed lifetime of tokens issued in seconds using this role.
+
+ - `period` : `Optional`. If set indicates that the token generated using this role should never expire. The token should be renewed within the
+ duration specified by this value. At each renewal, the token's TTL will be set to the value of this parameter.
+
+```yaml
+spec:
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "sa1"
+ - "sa2"
+ serviceAccountNamespaces:
+ - "demo"
+ ttl: "1000"
+ maxTTL: "2000"
+ period: "1000"
+```
+
+### VaultPolicyBinding Status
+
+`status` shows the status of a VaultPolicyBinding. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully created in the Vault or not.
+
+- `conditions` : Represents the latest available observations of a VaultPolicyBinding's current state.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/_index.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/_index.md
new file mode 100755
index 000000000..f0244281d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/_index.md
@@ -0,0 +1,17 @@
+---
+title: Secret Engine CRD | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: secret-engine-crds-concepts
+ name: Secret Engines
+ parent: concepts
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/_index.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/_index.md
new file mode 100755
index 000000000..60ada2325
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | AWS Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: aws-crds-concepts
+ name: AWS
+ parent: secret-engine-crds-concepts
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole.md
new file mode 100644
index 000000000..111b2863b
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole.md
@@ -0,0 +1,192 @@
+---
+title: AwsRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: awsrole-secret-engine-crds
+ name: AwsRole
+ parent: aws-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# AWSRole
+
+## What is AWSRole
+
+An `AWSRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create AWS secret engine role in a Kubernetes native way.
+
+When an `AWSRole` is created, the KubeVault operator [configures](https://www.vaultproject.io/docs/secrets/aws/index.html#setup) a Vault role that maps to a set of permissions in AWS as well as an AWS credential type. When users generate credentials, they are generated against this role. If the user deletes the `AWSRole` CRD,
+then the respective role will also be deleted from Vault.
+
+
+
+## AWSRole CRD Specification
+
+Like any official Kubernetes resource, a `AWSRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `AWSRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AWSRole
+metadata:
+ name: aws-cred
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: aws-secret-engine
+ credentialType: iam_user
+ policyDocument: |
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "ec2:*",
+ "Resource": "*"
+ }
+ ]
+ }
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `AWSRole` crd.
+
+### AWSRole Spec
+
+AWSRole `spec` contains root IAM credentials configuration and role information.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ credentialType:
+ roleARNs:
+ - "ARN1"
+ - "ARN2"
+ policyARNs:
+ - "ARN1"
+ - "ARN2"
+ policyDocument:
+ policy:
+ defaultSTSTTL:
+ maxSTSTTL:
+```
+
+`AWSRole` spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: aws-secret-engine
+```
+
+#### spec.credentialType
+
+`spec.credentialType` is a `required` field that specifies the type of credential to be used when retrieving credentials from the role. Supported types: `iam_user`, `assumed_role` and `federation_token`.
+
+```yaml
+spec:
+ credentialType: iam_user
+```
+
+#### spec.roleARNs
+
+`spec.roleARNs` is an `optional` field that specifies the list of ARNs of the AWS roles this Vault role is allowed to assume.
+
+```yaml
+spec:
+ roleARNs:
+ - arn:aws:iam::452618475015:role/hello.world
+```
+
+#### spec.policyARNs
+
+`spec.policyARNs` is an `optional` field that specifies the list of ARNs of the AWS managed policies to be attached to IAM users when they are requested.
+
+```yaml
+spec:
+ policyARNs:
+ - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
+```
+
+#### spec.policyDocument
+
+`spec.policyDocument` is an `optional` field that specifies the IAM policy document for the role.
+
+```yaml
+spec:
+ policyDocument: |
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "ec2:*",
+ "Resource": "*"
+ }
+ ]
+ }
+```
+
+#### spec.policy
+
+`spec.policy` is an `optional` field that specifies the IAM policy in JSON format.
+ This field is for backward compatibility only.
+
+```yaml
+spec:
+ policy:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Action: ec2:*
+ Resource: "*"
+```
+
+#### spec.defaultSTSTTL
+
+`spec.defaultSTSTTL` is an `optional` field that specifies the default TTL for STS credentials. When a TTL is not specified when STS credentials are requested, and a default TTL is specified
+on the role, then this default TTL will be used. This is valid only when `spec.credentialType` is one of `assumed_role` or `federation_token`.
+
+```yaml
+spec:
+ defaultSTSTTL: "1h"
+```
+
+#### spec.maxSTSTTL
+
+`spec.maxSTSTTL` is an `optional` field that specifies the max allowed TTL for STS credentials. This is valid only when `spec.credentialType` is one of `assumed_role` or `federation_token`.
+
+```yaml
+spec:
+ maxSTSTTL: "1h"
+```
+
+### AWSRole Status
+
+`status` shows the status of the AWSRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of an AWSRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/_index.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/_index.md
new file mode 100755
index 000000000..4dd58efae
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | Azure Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: azure-crds-concepts
+ name: Azure
+ parent: secret-engine-crds-concepts
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/azurerole.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/azurerole.md
new file mode 100644
index 000000000..64195002c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/azurerole.md
@@ -0,0 +1,140 @@
+---
+title: AzureRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: azurerole-secret-engine-crds
+ name: AzureRole
+ parent: azure-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# AzureRole
+
+## What is AzureRole
+
+An `AzureRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create an Azure secret engine role in a Kubernetes native way.
+
+When an `AzureRole` is created, the KubeVault operator [configures](https://www.vaultproject.io/docs/secrets/azure/index.html#setup) a Vault role.
+A role may be set up with either an existing service principal or a set of Azure roles that will be assigned to a dynamically created service principal.
+If the user deletes the `AzureRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## AzureRole CRD Specification
+
+Like any official Kubernetes resource, a `AzureRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `AzureRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AzureRole
+metadata:
+ name: azure-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: azure-secret-engine
+ azureRoles: `[
+ {
+ "role_name": "Contributor",
+ "scope": "/subscriptions//resourceGroups/Website"
+ }
+ ]`
+ applicationObjectID: c1cb042d-96d7-423a-8dba-243c2e5010d3
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `AzureRole` crd.
+
+### AzureRole Spec
+
+AzureRole `spec` contains either new service principal configuration or existing service principal name required for configuring a role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ applicationObjectID:
+ azureRoles:
+ ttl:
+ maxTTL:
+```
+
+`AzureRole` spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: azure-secret-engine
+```
+
+#### spec.azureRoles
+
+`spec.azureRoles` is an `optional` field that specifies a list of Azure roles to be assigned to the generated service principal. The array must be in JSON format, properly escaped as a string.
+
+```yaml
+spec:
+ azureRoles: `[
+ {
+ "role_name": "Contributor",
+ "scope": "/subscriptions//resourceGroups/Website"
+ }
+ ]`
+```
+
+#### spec.applicationObjectID
+
+`spec.applicationObjectID` is an `optional` field that specifies the Application Object ID for an existing service principal that will be used instead of creating dynamic service principals. If present, azure_roles will be ignored. See [roles docs](https://www.vaultproject.io/docs/secrets/azure/index.html#roles) for details on role definition.
+
+```yaml
+spec:
+ applicationObjectID: c1cb042d-96d7-423a-8dba-243c2e5010d3
+```
+
+#### spec.ttl
+
+Specifies the default TTL for service principals generated using this role. Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to the system/engine default TTL time.
+
+```yaml
+spec:
+ ttl: 1h
+```
+
+#### spec.maxTTL
+
+Specifies the maximum TTL for service principals generated using this role. Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to the system/engine max TTL time.
+
+```yaml
+spec:
+ maxTTL: 1h
+```
+
+### AzureRole Status
+
+`status` shows the status of the AzureRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of an AzureRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/_index.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/_index.md
new file mode 100755
index 000000000..8a58fae8f
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | Database Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: database-crds-concepts
+ name: Database
+ parent: secret-engine-crds-concepts
+ weight: 60
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/elasticsearch.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/elasticsearch.md
new file mode 100644
index 000000000..cec58af39
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/elasticsearch.md
@@ -0,0 +1,129 @@
+---
+title: ElasticsearchRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: elasticsearch-database-crds
+ name: ElasticsearchRole
+ parent: database-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# ElasticsearchRole
+
+## What is ElasticsearchRole
+
+A `ElasticsearchRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create an Elasticsearch database secret engine role in a Kubernetes native way.
+
+When a `ElasticsearchRole` is created, the KubeVault operator creates a Vault [role](https://www.vaultproject.io/api/secret/databases/index.html#create-role) according to the specification.
+If the user deletes the `ElasticsearchRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## ElasticsearchRole CRD Specification
+
+Like any official Kubernetes resource, a `ElasticsearchRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `ElasticsearchRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: ElasticsearchRole
+metadata:
+ name: es-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: es-secret-engine
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `ElasticsearchRole` crd.
+
+### ElasticsearchRole Spec
+
+ElasticsearchRole `spec` contains information that necessary for creating a database role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ defaultTTL:
+ maxTTL:
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+ revocationStatements:
+ - "statement-0"
+```
+
+ElasticsearchRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: vault-app
+```
+
+#### spec.creationStatements
+
+`spec.creationStatements` is a `required` field that specifies a list of database statements executed to create and configure a user.
+See in [here](https://www.vaultproject.io/api/secret/databases/elasticdb.html#creation_statements) for Vault documentation.
+
+```yaml
+spec:
+ creationStatements:
+ - "{"elasticsearch_roles": ["superuser"]}"
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the TTL for the leases associated with this role. Accepts time suffixed strings ("1h") or an integer number of seconds.
+Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ defaultTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the maximum TTL for the leases associated with this role. Accepts time suffixed strings ("1h") or an integer number of seconds.
+Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+### ElasticsearchRole Status
+
+`status` shows the status of the ElasticsearchRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation,
+ which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a ElasticsearchRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mariadb.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mariadb.md
new file mode 100644
index 000000000..d4117083b
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mariadb.md
@@ -0,0 +1,135 @@
+---
+title: MariaDBRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: mariadb-database-crds
+ name: MariaDBRole
+ parent: database-crds-concepts
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# MariaDBRole
+
+## What is MariaDBRole
+
+A `MariaDBRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create a database secret engine role in a Kubernetes native way.
+
+When a `MariaDBRole` is created, the KubeVault operator creates a
+[role](https://www.vaultproject.io/api/secret/databases/index.html#create-role) according to the specification.
+If the user deletes the `MariaDBRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## MariaDBRole CRD Specification
+
+Like any official Kubernetes resource, a `MariaDBRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `MariaDBRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MariaDBRole
+metadata:
+ name: mariadb-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: mariadb-secret-engine
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `MariaDBRole` crd.
+
+### MariaDBRole Spec
+
+MariaDBRole `spec` contains information that necessary for creating a database role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ defaultTTL:
+ maxTTL:
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+ revocationStatements:
+ - "statement-0"
+```
+
+MariaDBRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: mariadb-secret-engine
+```
+
+#### spec.creationStatements
+
+`spec.creationStatements` is a `required` field that specifies a list of database statements executed to create and configure a user.
+The `{{name}}` and `{{password}}` values will be substituted by Vault.
+
+```yaml
+spec:
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the TTL for the leases associated with this role.
+Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ defaultTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the maximum TTL for the leases associated with this role.
+Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.revocationStatements
+
+`spec.revocationStatements` is an `optional` field that specifies a list of database statements to be executed to revoke a user. The `{{name}}` value will be substituted. If not provided defaults to a generic drop user statement.
+
+### MariaDBRole Status
+
+`status` shows the status of the MariaDBRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation,
+ which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a MariaDBRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb.md
new file mode 100644
index 000000000..b07524b3c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb.md
@@ -0,0 +1,135 @@
+---
+title: MongoDBRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: mongodb-database-crds
+ name: MongoDBRole
+ parent: database-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# MongoDBRole
+
+## What is MongoDBRole
+
+A `MongoDBRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create a MongoDB database secret engine role in a Kubernetes native way.
+
+When a `MongoDBRole` is created, the KubeVault operator creates a Vault [role](https://www.vaultproject.io/api/secret/databases/index.html#create-role) according to the specification.
+If the user deletes the `MongoDBRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## MongoDBRole CRD Specification
+
+Like any official Kubernetes resource, a `MongoDBRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `MongoDBRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MongoDBRole
+metadata:
+ name: mdb-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: es-secret-engine
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `MongoDBRole` crd.
+
+### MongoDBRole Spec
+
+MongoDBRole `spec` contains information that necessary for creating a database role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ defaultTTL:
+ maxTTL:
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+ revocationStatements:
+ - "statement-0"
+```
+
+MongoDBRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: es-secret-engine
+```
+
+#### spec.creationStatements
+
+`spec.creationStatements` is a `required` field that specifies a list of database statements executed to create and configure a user.
+See in [here](https://www.vaultproject.io/api/secret/databases/mongodb.html#creation_statements) for Vault documentation.
+
+```yaml
+spec:
+ creationStatements:
+ - "{ \"db\": \"admin\", \"roles\": [{ \"role\": \"readWrite\" }, {\"role\": \"read\", \"db\": \"foo\"}] }"
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the TTL for the leases associated with this role. Accepts time suffixed strings ("1h") or an integer number of seconds.
+ Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ defaultTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the maximum TTL for the leases associated with this role. Accepts time suffixed strings ("1h") or an integer number of seconds.
+Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.revocationStatements
+
+`spec.revocationStatements` is an `optional` field that specifies
+a list of database statements to be executed to revoke a user.
+See [here](https://www.vaultproject.io/api/secret/databases/mongodb.html#revocation_statements) for Vault documentation.
+
+### MongoDBRole Status
+
+`status` shows the status of the MongoDBRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation,
+ which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a MongoDBRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mysql.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mysql.md
new file mode 100644
index 000000000..2adca9e6b
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mysql.md
@@ -0,0 +1,135 @@
+---
+title: MySQLRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: mysql-database-crds
+ name: MySQLRole
+ parent: database-crds-concepts
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# MySQLRole
+
+## What is MySQLRole
+
+A `MySQLRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create a database secret engine role in a Kubernetes native way.
+
+When a `MySQLRole` is created, the KubeVault operator creates a
+[role](https://www.vaultproject.io/api/secret/databases/index.html#create-role) according to the specification.
+If the user deletes the `MySQLRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## MySQLRole CRD Specification
+
+Like any official Kubernetes resource, a `MySQLRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `MySQLRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MySQLRole
+metadata:
+ name: mysql-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: sql-secret-engine
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `MySQLRole` crd.
+
+### MySQLRole Spec
+
+MySQLRole `spec` contains information that necessary for creating a database role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ defaultTTL:
+ maxTTL:
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+ revocationStatements:
+ - "statement-0"
+```
+
+MySQLRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: sql-secret-engine
+```
+
+#### spec.creationStatements
+
+`spec.creationStatements` is a `required` field that specifies a list of database statements executed to create and configure a user.
+The `{{name}}` and `{{password}}` values will be substituted by Vault.
+
+```yaml
+spec:
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the TTL for the leases associated with this role.
+Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ defaultTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the maximum TTL for the leases associated with this role.
+Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.revocationStatements
+
+`spec.revocationStatements` is an `optional` field that specifies a list of database statements to be executed to revoke a user. The `{{name}}` value will be substituted. If not provided defaults to a generic drop user statement.
+
+### MySQLRole Status
+
+`status` shows the status of the MySQLRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation,
+ which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a MySQLRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole.md
new file mode 100644
index 000000000..15424378d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole.md
@@ -0,0 +1,147 @@
+---
+title: PostgresRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: postgresrole-database-crds
+ name: PostgresRole
+ parent: database-crds-concepts
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# PostgresRole
+
+## What is PostgresRole
+
+A `PostgresRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create a database secret engine role in a Kubernetes native way.
+
+When a `PostgresRole` is created, the KubeVault operator creates a [role](https://www.vaultproject.io/api/secret/databases/index.html#create-role) according to specification.
+If the user deletes the `PostgresRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## PostgresRole CRD Specification
+
+Like any official Kubernetes resource, a `PostgresRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `PostgresRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: PostgresRole
+metadata:
+ name: pg-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: vault-app
+ creationStatements:
+ - "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';"
+ - "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `PostgresRole` crd.
+
+### PostgresRole Spec
+
+PostgresRole `spec` contains information that necessary for creating a database role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ defaultTTL:
+ maxTTL:
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+ revocationStatements:
+ - "statement-0"
+ rollbackStatements:
+ - "statement-0"
+ renewStatements:
+ - "statement-0"
+```
+
+PostgresRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: pg-secret-engine
+```
+
+#### spec.creationStatements
+
+`spec.creationStatements` is a `required` field that specifies a list of database statements executed to create and configure a user.
+The `{{name}}`, `{{password}}` and `{{expiration}}` values will be substituted by Vault.
+
+```yaml
+spec:
+ creationStatements:
+ - "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';"
+ - "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the TTL for the leases associated with this role.
+Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ defaultTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the maximum TTL for the leases associated with this role.
+Accepts time suffixed strings ("1h") or an integer number of seconds. Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.revocationStatements
+
+`spec.revocationStatements` is an `optional` field that specifies a list of database statements to be executed to revoke a user. The `{{name}}` value will be substituted. If not provided defaults to a generic drop user statement.
+
+#### spec.rollbackStatements
+
+`spec.rollbackStatements` is an `optional` field that specifies a list of database statements to be executed
+rollback a create operation in the event of an error. Not every plugin type will support this functionality.
+
+#### spec.renewStatements
+
+`spec.renewStatements` is an `optional` field that specifies a list of database statements to be executed to renew a user. Not every plugin type will support this functionality.
+
+### PostgresRole Status
+
+`status` shows the status of the PostgresRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation,
+ which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a PostgresRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/redis.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/redis.md
new file mode 100644
index 000000000..7f9860f09
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/redis.md
@@ -0,0 +1,132 @@
+---
+title: RedisRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: redis-database-crds
+ name: RedisRole
+ parent: database-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# RedisRole
+
+## What is RedisRole
+
+A `RedisRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create a Redis database secret engine role in a Kubernetes native way.
+
+When a `RedisRole` is created, the KubeVault operator creates a Vault [role](https://www.vaultproject.io/api/secret/databases/index.html#create-role) according to the specification.
+If the user deletes the `RedisRole` CRD, then the respective role will also be deleted from Vault.
+
+
+
+## RedisRole CRD Specification
+
+Like any official Kubernetes resource, a `RedisRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `RedisRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: RedisRole
+metadata:
+ name: rd-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: redis-secret-engine
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `RedisRole` crd.
+
+### RedisRole Spec
+
+RedisRole `spec` contains information that necessary for creating a database role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ creationStatements:
+ - "statement-0"
+ - "statement-1"
+ revocationStatements:
+ - "statement-0"
+```
+
+RedisRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: redis-secret-engine
+```
+
+#### spec.creationStatements
+
+`spec.creationStatements` is a `required` field that specifies a list of database statements executed to create and configure a user.
+See in [here](https://developer.hashicorp.com/vault/api-docs/secret/databases/redis#creation_statements) for Vault documentation.
+
+```yaml
+spec:
+ creationStatements:
+ - '["~*", "+@read","+@write"]'
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the TTL for the leases associated with this role. Accepts time suffixed strings ("1h") or an integer number of seconds.
+ Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ defaultTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the maximum TTL for the leases associated with this role. Accepts time suffixed strings ("1h") or an integer number of seconds.
+Defaults to system/engine default TTL time.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.revocationStatements
+
+`spec.revocationStatements` is an `optional` field that specifies
+a list of database statements to be executed to revoke a user.
+See [here](https://www.vaultproject.io/api/secret/databases/redis.html#revocation_statements) for Vault documentation.
+
+### RedisRole Status
+
+`status` shows the status of the RedisRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation,
+ which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a RedisRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/_index.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/_index.md
new file mode 100755
index 000000000..433af457b
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | GCP Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: gcp-crds-concepts
+ name: GCP
+ parent: secret-engine-crds-concepts
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole.md
new file mode 100644
index 000000000..3afdc3150
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole.md
@@ -0,0 +1,139 @@
+---
+title: GCPRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: gcprole-secret-engine-crds
+ name: GCPRole
+ parent: gcp-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# GCPRole
+
+## What is GCPRole
+
+A `GCPRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create a GCP secret engine role in a Kubernetes native way.
+
+When a `GCPRole` is created, the KubeVault operator [configures](https://www.vaultproject.io/docs/secrets/gcp/index.html#setup) a Vault roleset.
+The rolesets determine the permissions that Service Account credentials generated by Vault will have on GCP resources. If the user deletes the `GCPRole` CRD, then the respective role will also be deleted from Vault.
+
+For maintaining similarity with other secret engines we will refer **roleset as role** in the following description.
+
+
+
+## GCPRole CRD Specification
+
+Like any official Kubernetes resource, a `GCPRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `GCPRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: GCPRole
+metadata:
+ name: gcp-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: gcp-secret-engine
+ secretType: access_token
+ project: ackube
+ bindings: 'resource "//cloudresourcemanager.googleapis.com/projects/ackube" {
+ roles = ["roles/viewer"]
+ }'
+ tokenScopes: ["https://www.googleapis.com/auth/cloud-platform"]
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `GCPRole` crd.
+
+### GCPRole Spec
+
+GCPRole `spec` contains the necessary information required to create a GCP secret engine role.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ path:
+ secretType:
+ project:
+ bindings:
+ tokenScopes:
+```
+
+GCPRole spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: gcp-secret-engine
+```
+
+#### spec.secretType
+
+`spec.secretType` is a `required` field that specifies the type of secret generated for this roleset. Accepted values: `access_token`, `service_account_key`.
+
+```yaml
+spec:
+ secretType: access_token
+```
+
+#### spec.project
+
+`spec.project` is a `required` field that specifies the name of the GCP project where roleset's service account belongs to.
+
+```yaml
+spec:
+ project: ackube
+```
+
+#### spec.bindings
+
+`spec.bindings` is a `required` field that specifies the bindings configuration string.
+
+```yaml
+spec:
+ bindings: 'resource "//cloudresourcemanager.googleapis.com/projects/ackube" {
+ roles = ["roles/viewer"]
+ }'
+```
+
+#### spec.tokenScopes
+
+`spec.tokenScopes` is an `optional` field that specifies the list of
+OAuth scopes to assign to `access_token` secrets generated under this role
+ set (`access_token` role sets only)
+
+```yaml
+spec:
+ tokenScopes: ["https://www.googleapis.com/auth/cloud-platform"]
+```
+
+### GCPRole Status
+
+`status` shows the status of the GCPRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of a GCPRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/_index.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/_index.md
new file mode 100644
index 000000000..ec014056d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | PKI Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: pki-crds-concepts
+ name: PKI
+ parent: secret-engine-crds-concepts
+ weight: 50
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/pkirole.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/pkirole.md
new file mode 100644
index 000000000..fc0e68be8
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/pki-secret-engine/pkirole.md
@@ -0,0 +1,145 @@
+---
+title: PKIRole | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: pkirole-secret-engine-crds
+ name: PKIRole
+ parent: pki-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# PKIRole
+
+## What is PKIRole
+
+An `PKIRole` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to create PKI secret engine role in a Kubernetes native way.
+
+When an `PKIRole` is created, the KubeVault operator [configures](https://www.vaultproject.io/docs/secrets/pki/index.html#setup) a Vault role that maps to a set of permissions in PKI as well as an PKI credential type. When users generate credentials, they are generated against this role. If the user deletes the `PKIRole` CRD,
+then the respective role will also be deleted from Vault.
+
+
+
+## PKIRole CRD Specification
+
+Like any official Kubernetes resource, a `PKIRole` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `PKIRole` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: PKIRole
+metadata:
+ name: pki-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: pki-secret-engine
+ allowedDomains:
+ - "kubevault.com"
+ allowSubdomains: true
+ maxTTL: "720h"
+ additionalPayload:
+ "allow_ip_sans": "true"
+```
+
+> Note: To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`
+
+Here, we are going to describe the various sections of the `PKIRole` crd.
+
+### PKIRole Spec
+
+PKIRole `spec` contains role information.
+
+```yaml
+spec:
+ secretEngineRef:
+ name:
+ allowedDomains:
+ allowSubdomains:
+ defaultTTL:
+ maxTTL:
+ additionalPayload:
+ "key": "value"
+```
+
+`PKIRole` spec has the following fields:
+
+#### spec.secretEngineRef
+
+`spec.secretEngineRef` is a `required` field that specifies the name of a `SecretEngine`.
+
+```yaml
+spec:
+ secretEngineRef:
+ name: pki-secret-engine
+```
+
+#### spec.allowedDomains
+
+`spec.allowedDomains` is a `required` field that specifies the domains this role is allowed to issue certificates for
+
+```yaml
+spec:
+ allowedDomains:
+ - "kubevault.com"
+```
+
+#### spec.allowSubdomains
+
+`spec.allowSubdomains` is an `optional` field that specifies the if subdomains is allowed.
+
+```yaml
+spec:
+ allowSubdomains: true
+```
+
+#### spec.defaultTTL
+
+`spec.defaultTTL` is an `optional` field that specifies the default TTL for certificates.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.maxTTL
+
+`spec.maxTTL` is an `optional` field that specifies the max allowed TTL for certificates.
+
+```yaml
+spec:
+ maxTTL: "1h"
+```
+
+#### spec.additionalPayload
+
+`spec.additionalPayload` is an `optional` field which can used to provide any key value of [vault-api](https://developer.hashicorp.com/vault/api-docs/secret/pki#create-update-role)
+which will be used to create the role.
+
+```yaml
+spec:
+ additionalPayload:
+ "key1": "value1"
+ "key2": "value2"
+
+```
+
+### PKIRole Status
+
+`status` shows the status of the PKIRole. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the role successfully applied to Vault or not.
+
+- `conditions` : Represent observations of an PKIRole.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request.md
new file mode 100644
index 000000000..12be02370
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request.md
@@ -0,0 +1,190 @@
+---
+title: Secret Access Request
+menu:
+ docs_v2025.11.21:
+ identifier: secret-access-request-secret-engine-crds
+ name: SecretAccessRequest
+ parent: secret-engine-crds-concepts
+ weight: 11
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# SecretAccessRequest
+
+## What is SecretAccessRequest
+
+A `SecretAccessRequest` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to request a Vault server for credentials in a Kubernetes native way.
+A `SecretAccessRequest` can be created under various `roleRef` e.g: `AWSRole`, `GCPRole`, `ElasticsearchRole`, `MongoDBRole`, etc. A `SecretAccessRequest` has three different phases e.g:
+`WaitingForApproval`, `Approved`, `Denied`. If `SecretAccessRequest` is approved, then the KubeVault operator will issue credentials and create Kubernetes secret containing credentials. The secret name will be specified in `status.secret.name` field.
+
+Once a `SecretAccessRequest` phase is `Approved`, it can't be `Denied`. A `Denied` phase will automatically change to `WaitingForApproval` phase if any changes in `SecretAccessRequest.spec` is made by the user.
+
+
+
+
+KubeVault operator performs the following operations when a `SecretAccessRequest` CRD is created:
+
+- Checks whether `status.phase` is `Approved` or not
+- If Approved, requests the Vault server for credentials
+- Creates a Kubernetes Secret which contains the credentials
+- Sets the name of the k8s secret to SecretAccessRequest's `status.secret.name`
+- Sets the namespace of the k8s secret to SecretAccessRequest's `status.secret.namespace`
+- Assigns read permissions on that Kubernetes secret to specified subjects or user identities
+
+## SecretAccessRequest CRD Specification
+
+Like any official Kubernetes resource, a `SecretAccessRequest` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `SecretAccessRequest` object for the `AWSRole` is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: aws-cred-req
+ namespace: dev
+spec:
+ roleRef:
+ kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: test
+```
+
+Here, we are going to describe the various sections of the `SecretAccessRequest` CRD.
+
+### SecretAccessRequest Spec
+
+SecretAccessRequest `spec` contains information about the role and the subjects.
+
+```yaml
+spec:
+ roleRef:
+ apiGroup:
+ kind:
+ name:
+ subjects:
+ - kind:
+ apiGroup:
+ name:
+ namespace:
+ ttl:
+```
+
+`SecretAccessRequest` spec has the following fields:
+
+#### spec.roleRef
+
+`spec.roleRef` is a `required` field that specifies the role against which credentials will be issued.
+
+It has the following fields:
+
+- `roleRef.apiGroup` : `Optional`. Specifies the APIGroup of the resource being referenced.
+
+- `roleRef.kind` : `Required`. Specifies the kind of the resource being referenced.
+
+- `roleRef.name` : `Required`. Specifies the name of the object being referenced.
+
+
+```yaml
+spec:
+ roleRef:
+ kind: AWSRole
+ name: aws-role
+```
+
+#### spec.subjects
+
+`spec.subjects` is a `required` field that contains a list of references to the object or user identities on whose behalf this request is made. These object or user identities will have read access to the k8s credential secret. This can either hold a direct API object reference or a value for non-objects such as user and group names.
+
+It has the following fields:
+
+- `kind` : `Required`. Specifies the kind of object being referenced. Values defined by
+ these API groups are "User", "Group", and "ServiceAccount". If the Authorizer does not
+ recognize the kind value, the Authorizer will report an error.
+
+- `apiGroup` : `Optional`. Specifies the APIGroup that holds the API group of the referenced subject.
+ Defaults to `""` for ServiceAccount subjects.
+
+- `name` : `Required`. Specifies the name of the object being referenced.
+
+- `namespace`: `Required`. Specifies the namespace of the object being referenced.
+
+```yaml
+spec:
+ subjects:
+ - kind: ServiceAccount
+ name: sa
+ namespace: demo
+```
+
+#### spec.ttl
+
+`spec.ttl` is an `optional` field that specifies the TTL for the use
+of the STS token. This is specified as a string with a duration suffix.
+
+```yaml
+spec:
+ ttl: "1h"
+```
+
+### SecretAccessRequest Status
+
+`status` shows the status of the `SecretAccessRequest`. It is managed by the KubeVault operator. It contains the following fields:
+
+- `secret`:
+ - `secret.name`: Specifies the name of the secret containing the credential.
+ - `secret.namespace`: Specifies the namespace of the secret containing the credential.
+
+- `lease`: Contains lease information of the issued credential.
+
+- `conditions` : Represent observations of a `SecretAccessRequest`. It has the following fields:
+ - `conditions[].type` : Specifies request approval state. Supported type: `Approved` and `Denied`, `Available`.
+ - `conditions[].status` : Specifies request approval status. Supported type: `True`, `False`.
+ - `conditions[].reason` : Specifies brief reason for the request state.
+ - `conditions[].message` : Specifies human-readable message with details about the request state.
+ - `conditions[].observerGeneration`: Specifies ObserverGeneration for the request state.
+
+- `phase` : Represent the phase of the `SecretAccessRequest`. Supported type: `Approved` and `Denied`, `WaitingForApproval`.
+
+`Approved` `SecretAccessRequest.status` may look like this:
+
+```yaml
+status:
+ conditions:
+ - lastTransitionTime: "2021-09-28T09:36:45Z"
+ message: 'This was approved by: kubectl vault approve secretaccessrequest'
+ observedGeneration: 1
+ reason: KubectlApprove
+ status: "True"
+ type: Approved
+ - lastTransitionTime: "2021-09-28T09:36:49Z"
+ message: The requested credentials successfully issued.
+ observedGeneration: 1
+ reason: SuccessfullyIssuedCredential
+ status: "True"
+ type: Available
+ lease:
+ duration: 1h0m0s
+ id: k8s.-.aws.dev.aws-secret-engine/creds/k8s.-.dev.aws-role/ACUzSSp5aLVBzNhoqe6wEqaW
+ renewable: true
+ observedGeneration: 1
+ phase: Approved
+ secret:
+ name: aws-cred-req-92m0n9
+ namespace: dev
+
+```
+
+> Note: Credential will be issued only if the `status.phase` is `Approved`. Otherwise, the KubeVault operator will not issue any credentials.
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/secret-role-binding.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/secret-role-binding.md
new file mode 100644
index 000000000..9f2aafaae
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/secret-role-binding.md
@@ -0,0 +1,328 @@
+---
+title: Secret Role Binding
+menu:
+ docs_v2025.11.21:
+ identifier: secret-role-binding-secret-engine-crds
+ name: SecretRoleBinding
+ parent: secret-engine-crds-concepts
+ weight: 12
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# SecretRoleBinding
+
+## What is SecretRoleBinding
+
+A `SecretRoleBinding` is a Kubernetes `CustomResourceDefinition` (CRD) which allows a user to bind a set of roles to a set of users.
+Using the `SecretRoleBinding` it's possible to bind various roles e.g: `AWSRole`, `GCPRole`, `ElasticsearchRole`, `MongoDBRole`, etc. to Kubernetes ServiceAccounts.
+A `SecretRoleBinding` has three different phases e.g: `Processing`, `Success`, `Failed`. Once a `SecretRoleBinding` is successful, it will create a `VaultPolicy` and a `VaultPolicyBinding`.
+
+
+## SecretRoleBinding CRD Specification
+
+Like any official Kubernetes resource, a `SecretRoleBinding` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+A sample `SecretRoleBinding` object that binds `AWSRole` to a Kubernetes `ServiceAccount` is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-r-binding
+ namespace: dev
+spec:
+ roles:
+ - kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: test
+```
+
+Here, we are going to describe the various sections of the `SecretRoleBinding` CRD.
+
+### SecretRoleBinding Spec
+
+SecretAccessRequest `spec` contains information about the role and the subjects.
+
+```yaml
+spec:
+ roles:
+ - kind:
+ name:
+ subjects:
+ - kind:
+ name:
+ namespace:
+```
+
+`SecretRoleBinding` spec has the following fields:
+
+#### spec.roles
+
+`spec.roles` is a `required` field that specifies the roles list for which the `VaultPolicy` will be created.
+
+It has the following fields:
+
+- `roleRef.apiGroup` : `Optional`. Specifies the APIGroup of the resource being referenced.
+
+- `roleRef.kind` : `Required`. Specifies the kind of the resource being referenced.
+
+- `roleRef.name` : `Required`. Specifies the name of the object being referenced.
+
+
+```yaml
+spec:
+ roles:
+ - kind:
+ name:
+```
+
+#### spec.subjects
+
+`spec.subjects` is a `required` field that contains a list of references to the object or user identities on whose behalf this request is made. These object or user identities will have read access to the k8s credential secret. This can either hold a direct API object reference or a value for non-objects such as user and group names.
+
+It has the following fields:
+
+- `kind` : `Required`. Specifies the kind of object being referenced. Values defined by
+ these API groups are "User", "Group", and "ServiceAccount". If the Authorizer does not
+ recognize the kind value, the Authorizer will report an error.
+
+- `apiGroup` : `Optional`. Specifies the APIGroup that holds the API group of the referenced subject.
+ Defaults to `""` for ServiceAccount subjects.
+
+- `name` : `Required`. Specifies the name of the object being referenced.
+
+- `namespace`: `Optional`. Specifies the namespace of the object being referenced.
+
+```yaml
+spec:
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: test
+```
+
+### SecretRoleBinding Status
+
+`status` shows the status of the `SecretRoleBinding`. It contains the following fields:
+
+- `conditions` : Represent observations of a `SecretAccessRequest`. It has the following fields:
+ - `conditions[].type` : Specifies request approval state. Supported type: `VaultPolicySuccess` and `VaultPolicyBindingSuccess`, `SecretRoleBindingSuccess`.
+ - `conditions[].status` : Specifies request approval status. Supported type: `True`, `False`.
+ - `conditions[].reason` : Specifies brief reason for the request state.
+ - `conditions[].message` : Specifies human-readable message with details about the request state.
+ - `conditions[].observerGeneration`: Specifies ObserverGeneration for the request state.
+
+- `phase` : Represent the phase of the `SecretRoleBinding`. Supported type: `Success` and `Failed`, `Processing`.
+
+- `policyRef` : Represent the `VaultPolicy` created by the `SecretRoleBinding`.
+ - `policyRef.name`: The name of the `VaultPolicy` created by the `SecretRoleBinding`.
+ - `policyRef.namespace`: The namespace of the `VaultPolicy` created by the `SecretRoleBinding`.
+
+- `policyBindingRef` : Represent the `VaultPolicyBinding` created by the `SecretRoleBinding`.
+ - `policyRef.name`: The name of the `VaultPolicyBinding` created by the `SecretRoleBinding`.
+ - `policyRef.namespace`: The namespace of the `VaultPolicyBinding` created by the `SecretRoleBinding`.
+
+
+A Successful `SecretAccessRequest.status` may look like this:
+
+```yaml
+status:
+ conditions:
+ - lastTransitionTime: "2021-09-28T12:56:35Z"
+ message: VaultPolicy phase is Successful
+ observedGeneration: 1
+ reason: VaultPolicySucceeded
+ status: "True"
+ type: VaultPolicySuccess
+ - lastTransitionTime: "2021-09-28T12:56:35Z"
+ message: VaultPolicyBinding is Successful
+ observedGeneration: 1
+ reason: VaultPolicyBindingSucceeded
+ status: "True"
+ type: VaultPolicyBindingSuccess
+ - lastTransitionTime: "2021-09-28T12:56:35Z"
+ message: SecretRoleBinding is Successful
+ observedGeneration: 1
+ reason: SecretRoleBindingSucceeded
+ status: "True"
+ type: SecretRoleBindingSuccess
+ observedGeneration: 1
+ phase: Success
+ policyBindingRef:
+ name: srb-dev-secret-r-binding
+ namespace: demo
+ policyRef:
+ name: srb-dev-secret-r-binding
+ namespace: demo
+
+```
+
+#### SecretRoleBinding status.policyRef
+
+We can get the `VaultPolicy` if the `SecretRoleBinding` phase is `Success`:
+
+```bash
+$ kubectl get vaultpolicy -n demo srb-dev-secret-r-binding -oyaml
+```
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ annotations:
+ secretrolebindings.engine.kubevault.com/name: secret-r-binding
+ secretrolebindings.engine.kubevault.com/namespace: dev
+ creationTimestamp: "2021-09-28T13:04:15Z"
+ finalizers:
+ - kubevault.com
+ generation: 1
+ name: srb-dev-secret-r-binding
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: b73a5a72-d575-4b91-8e95-938828268535
+ resourceVersion: "53571"
+ uid: b4a2ba18-66c3-4f3c-aa35-71b0d66c845f
+spec:
+ policyDocument: |
+
+ path "/k8s.-.aws.dev.aws-secret-engine/creds/k8s.-.dev.aws-role" {
+ capabilities = ["read"]
+ }
+
+ path "/k8s.-.aws.dev.aws-secret-engine/sts/k8s.-.dev.aws-role" {
+ capabilities = ["create", "update"]
+ }
+ vaultRef:
+ name: vault
+status:
+ conditions:
+ - lastTransitionTime: "2021-09-28T13:04:15Z"
+ message: policy is ready to use
+ reason: Provisioned
+ status: "True"
+ type: Available
+ observedGeneration: 1
+ phase: Success
+
+```
+
+#### VaultPolicy spec
+
+- `spec.policyDocument`: contains the document of permissions that are given to the users by `SecretRoleBinding`.
+- `spec.vaultRef`: contains the Vault reference.
+
+```yaml
+spec:
+ policyDocument: |
+
+ path "/k8s.-.aws.dev.aws-secret-engine/creds/k8s.-.dev.aws-role" {
+ capabilities = ["read"]
+ }
+
+ path "/k8s.-.aws.dev.aws-secret-engine/sts/k8s.-.dev.aws-role" {
+ capabilities = ["create", "update"]
+ }
+ vaultRef:
+ name: vault
+```
+
+
+#### SecretRoleBinding status.policyBindingRef
+
+We can get the `VaultPolicyBinding` if the `SecretRoleBinding` phase is `Success`:
+
+```bash
+$ kubectl get vaultpolicybinding -n demo srb-dev-secret-r-binding -oyaml
+```
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ annotations:
+ secretrolebindings.engine.kubevault.com/name: secret-r-binding
+ secretrolebindings.engine.kubevault.com/namespace: dev
+ creationTimestamp: "2021-09-28T13:04:15Z"
+ finalizers:
+ - kubevault.com
+ generation: 1
+ name: srb-dev-secret-r-binding
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: b73a5a72-d575-4b91-8e95-938828268535
+ resourceVersion: "53576"
+ uid: c37dc7ca-03ca-4191-af6c-fe91e544394a
+spec:
+ policies:
+ - ref: srb-dev-secret-r-binding
+ subjectRef:
+ kubernetes:
+ name: k8s.-.demo.srb-dev-secret-r-binding
+ path: kubernetes
+ serviceAccountNames:
+ - test-user-account
+ serviceAccountNamespaces:
+ - test
+ vaultRef:
+ name: vault
+ vaultRoleName: k8s.-.demo.srb-dev-secret-r-binding
+status:
+ conditions:
+ - lastTransitionTime: "2021-09-28T13:04:16Z"
+ message: policy binding is ready to use
+ reason: Provisioned
+ status: "True"
+ type: Available
+ observedGeneration: 1
+ phase: Success
+
+```
+
+#### VaultPolicyBinding spec
+
+- `spec.policies`: contains the `VaultPolicy` references.
+- `spec.subjectRef`: contains the Kubernetes subject reference and the `ServiceAccount` list.
+- `spec.vaultRef`: contains the Vault reference.
+- `spec.vaultRoleName`: contains the Role Name created by the operator.
+
+```yaml
+spec:
+ policies:
+ - ref: srb-dev-secret-r-binding
+ subjectRef:
+ kubernetes:
+ name: k8s.-.demo.srb-dev-secret-r-binding
+ path: kubernetes
+ serviceAccountNames:
+ - test-user-account
+ serviceAccountNamespaces:
+ - test
+ vaultRef:
+ name: vault
+ vaultRoleName: k8s.-.demo.srb-dev-secret-r-binding
+
+```
+
+`VaultPolicyBinding.spec.vaultRoleName` is the role name which will be bound of the policies.
+This role may be used during the creation of [SecretProviderClass](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass) for using the [Secrets-store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/introduction.html). This defaults to following format: `k8s.${cluster or -}.${metadata.namespace}.${metadata.name}`
+
+> Note: Here, the `VaultPolicy` and the `VaultPolicyBinding` both have the same name with prefix `srb` added to them to indicate that they're created by the `SecretRoleBinding` creation.
diff --git a/content/docs/v2025.11.21/concepts/secret-engine-crds/secretengine.md b/content/docs/v2025.11.21/concepts/secret-engine-crds/secretengine.md
new file mode 100644
index 000000000..bd47c40ca
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/secret-engine-crds/secretengine.md
@@ -0,0 +1,580 @@
+---
+title: Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: secret-engine-crds
+ name: SecretEngine
+ parent: secret-engine-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# SecretEngine
+
+## What is a SecretEngine
+
+A `SecretEngine` is a Kubernetes `CustomResourceDefinition` (CRD) which is designed to automate the process of enabling and configuring secret engines in Vault in a Kubernetes native way.
+
+Secrets engines are components that store, generate,
+or encrypt data. Secrets engines are provided some set of data, they take some action on that data, and they return a result.
+Secrets engines are enabled at a "path" in Vault.
+In this way, each secrets engine defines its paths and properties. To the user, secrets engines behave similar to a virtual filesystem, supporting operations like read, write, and delete.
+
+When a `SecretEngine` CRD is created, the KubeVault operator will perform the following operations:
+
+- **Creates** vault policy for the secret engine. The vault policy name follows the naming format:`k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. For example, the policy for GCP secret engine is below:
+
+```hcl
+ path "/config" {
+ capabilities = ["create", "update", "read", "delete"]
+ }
+
+ path "/roleset/*" {
+ capabilities = ["create", "update", "read", "delete"]
+ }
+
+ path "/token/*" {
+ capabilities = ["create", "update", "read"]
+ }
+
+ path "/key/*" {
+ capabilities = ["create", "update", "read"]
+ }
+```
+
+- **Updates** the Kubernetes auth role of the default k8s service account created with `VaultServer` with a new policy. The new policy will be merged with previous policies.
+
+- **Enables** the secrets engine at a given path. By default, they are enabled at their "type" (e.g. "aws" is enabled at "aws/").
+
+- **Configures** the secret engine with the given configuration.
+
+## SecretEngine CRD Specification
+
+Like any official Kubernetes resource, a `SecretEngine` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `SecretEngine` object is shown below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: first-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ gcp:
+ credentialSecret: "gcp-cred"
+status:
+ observedGeneration: 1
+ phase: Success
+```
+
+Here, we are going to describe the various sections of the `SecretEngine` crd.
+
+### SecretEngine Spec
+
+SecretEngine `.spec` contains information about the secret engine configuration and an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference which is used to connect with a Vault server.
+
+SecretEngine `.spec` has the following fields:
+
+#### spec.vaultRef
+
+`spec.vaultRef` is a `required` field that specifies an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+reference which is used to connect with a Vault server. AppBinding must be on the same namespace of the secret engine crd.
+
+```yaml
+spec:
+ vaultRef:
+ name: vault
+```
+
+#### spec.path
+
+`spec.path` will be set by the KubeVault operator.
+
+Secret engines are enabled at a "path" in Vault. When a request comes to Vault, the router automatically routes anything with the route prefix to the secret engine. Since operator configures a secret engine to a specified path with SecretEngine resource, you can provide **only one secret engine configuration** out of the following ones:
+
+- `spec.aws` : Specifies aws secret engine configuration
+
+- `spec.azure`: Specifies azure secret engine configuration
+
+- `spec.pki`: Specifies pki secret engine configuration
+
+- `spec.gcp`: Specifies gcp secret engine configuration
+
+- `spec.postgres`: Specifies database(postgres) secret engine configuration
+
+- `spec.mongodb`: Specifies database(mongodb) secret engine configuration
+
+- `spec.mysql`: Specifies database(mysql) secret engine configuration
+
+- `spec.elasticsearch`: Specifies database(elasticsearch) secret engine configuration
+
+- `spec.redis`: Specifies database(redis) secret engine configuration
+
+#### spec.aws
+
+`spec.aws` specifies the configuration required to configure
+AWS secret engine. [See more](https://www.vaultproject.io/api/secret/aws/index.html#parameters)
+
+```yaml
+spec:
+ aws:
+ credentialSecret: aws-cred
+ region: us-east-1
+ leaseConfig:
+ lease: 1h
+ leaseMax: 1h
+```
+
+- `aws.credentialSecret` : `Required`. Specifies the k8s secret name that contains AWS access key ID and secret access key
+
+ ```yaml
+ spec:
+ aws:
+ credentialSecret:
+ ```
+
+ The `data` field of the secret must contain the following key-value pairs:
+
+ ```yaml
+ data:
+ access_kay:
+ secret_key:
+ ```
+
+- `aws.region` : `Required`. Specifies the AWS region.
+
+- `aws.iamEndpoint` : `Optional`. Specifies a custom HTTP IAM endpoint to use.
+
+- `aws.stsEndpoint` : `Optional`. Specifies a custom HTTP STS endpoint to use.
+
+- `config.maxRetries` : `Optional`. Specifies the number of max retries the client should use for recoverable errors.
+
+- `aws.leaseConfig` : `Optional`. Specifies the lease configuration.
+
+ ```yaml
+ config:
+ leaseConfig:
+ lease: 1h
+ leaseMax: 1h
+ ```
+
+It has the following fields:
+
+ - `leaseConfig.lease` : `Optional`. Specifies the lease value. Accepts time suffixed strings (eg, "1h").
+
+ - `leaseConfig.leaseMax` : `Optional`. Specifies the maximum lease value. Accepts time suffixed strings (eg, "1h").
+
+#### spec.azure
+
+`spec.azure` specifies the configuration required to configure
+Azure secret engine. [See more](https://www.vaultproject.io/api/secret/azure/index.html#configure-access)
+
+```yaml
+spec:
+ azure:
+ credentialSecret: azure-cred
+ environment: AzurePublicCloud
+```
+
+- `credentialSecret` : `Required`. Specifies the k8s secret name containing azure credentials. The `data` field of the mentioned k8s secret can have the following key-value pairs.
+
+ - `subscription-id` : `Required`. Specifies the subscription id for the Azure Active Directory.
+
+ - `tenant-id` : `Required`. Specifies the tenant id for the Azure Active Directory.
+
+ - `client-id` : `Optional`. Specifies the OAuth2 client id to connect to Azure.
+
+ - `client-secret` : `Optional`. Specifies the OAuth2 client secret to connect to Azure.
+
+ ```yaml
+ data:
+ subscription-id:
+ tenant-id:
+ client-id:
+ client-secret:
+ ```
+
+- `environment` : `Optional`. Specifies the Azure environment. If not specified, Vault will use Azure Public Cloud.
+
+#### spec.gcp
+
+`spec.gcp` specifies the configuration required to configure GCP
+secret engine. [See more](https://www.vaultproject.io/api/secret/gcp/index.html#write-config)
+
+```yaml
+ spec:
+ gcp:
+ credentialSecret: gcp-cred
+ ttl: 0s
+ maxTTL: 0s
+```
+
+- `credentialSecret` : `Required`. Specifies the k8s secret name that contains google application credentials.
+
+ ```yaml
+ spec:
+ gcp:
+ credentialSecret:
+ ```
+
+ The `data` field of the mentioned k8s secret must contain the following key-value pair:
+
+ ```yaml
+ data:
+ sa.json:
+ ```
+
+- `ttl` : `Optional`. Specifies default config TTL for long-lived credentials (i.e. service account keys). Default value is 0s.
+
+- `maxTTL` : `Optional`. Specifies the maximum config TTL for long-lived credentials (i.e. service account keys). The default value is 0s.
+
+#### spec.pki
+
+`spec.pki` specifies the configuration required to configure
+PKI secret engine. [See more](https://developer.hashicorp.com/vault/api-docs/secret/pki#generate-root)
+
+```yaml
+spec:
+ pki:
+ isRootCA: false
+ parentCARef:
+ name: pki-root
+ namespace: demo
+ commonName: "kubevault.com"
+ ttl: "87600h"
+ maxLeaseTTL: "487600h"
+```
+
+- `isRootCA` : `Required`. Specifies if the secret engine will be used as a RootCA
+
+- `parentCARef` : `Required`. Specifies the namespace and name of the secret engine which will sign the intermediate CA.
+
+- `commonName` : `Required`. Specifies the requested CN for the certificate. If more than one common_name is desired, specify the alternative names in the `spec.altNames` list.
+
+- `ttl` : `Optional`. Specifies he requested Time To Live (after which the certificate will be expired).
+
+- `maxLeaseTTL` : `Optional`. Specifies maximum lease for the certificates.
+
+#### spec.postgres
+
+`spec.postgres` specifies the configuration required to configure PostgreSQL database secret engine. [See more](https://www.vaultproject.io/api/secret/databases/postgresql.html#configure-connection)
+
+ ```yaml
+ spec:
+ postgres:
+ databaseRef:
+ name:
+ namespace:
+ pluginName:
+ allowedRoles:
+ - "rule1"
+ - "rule2"
+ maxOpenConnections:
+ maxIdleConnections:
+ maxConnectionLifetime:
+ ```
+
+- `databaseRef` : `Required`. Specifies an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference that is required to connect to a PostgreSQL database. It is also used to generate `db_name` (i.e. `/v1/path/config/db_name`) where the database secret engine will be configured at. The name of the `db_name` follows this pattern: `k8s.{clusterName}.{namespace}.{name}`.
+
+ - `name` : `Required`. Specifies the AppBinding name.
+
+ - `namespace` : `Required`. Specifies the AppBinding namespace.
+
+ ```yaml
+ postgres:
+ databaseRef:
+ name: db-app
+ namespace: demo
+ ```
+
+ The generated `db_name` for the above example will be: `k8s.-.demo.db-app`. If the cluster name is empty, it is replaced by "`-`".
+
+- `pluginName` : `Optional`. Specifies the name of the plugin to use for this connection.
+ Default plugin name is `postgres-database-plugin`.
+
+ ```yaml
+ postgres:
+ pluginName: postgres-database-plugin
+ ```
+
+- `allowedRoles` : `Optional`. Specifies a list of roles allowed to use this connection.
+ Default to `"*"` (i.e. any role can use this connection).
+
+ ```yaml
+ postgres:
+ allowedRoles:
+ - "readonly"
+ ```
+
+- `maxOpenConnections` : `Optional`. Specifies the maximum number of open connections to
+ the database. Default value 2.
+
+ ```yaml
+ postgres:
+ maxOpenConnections: 3
+ ```
+
+- `maxIdleConnections` : `Optional`. Specifies the maximum number of idle connections to the database. Zero uses the value of max_open_connections and a negative value disables idle connections. If larger than max_open_connections it will be reduced to be equal. Default value 0.
+
+ ```yaml
+ postgres:
+ maxIdleConnections: 1
+ ```
+
+- `maxConnectionLifetime` : `Optional`. Specifies the maximum amount of time a connection may be reused. If <= 0s connections are reused forever. Default value 0s.
+
+ ```yaml
+ postgres:
+ maxConnectionLifetime: 5s
+ ```
+
+#### spec.mongodb
+
+`spec.mongodb` specifies the configuration required to configure MongoDB database secret engine. [See more](https://www.vaultproject.io/api/secret/databases/mongodb.html#configure-connection)
+
+```yaml
+ spec:
+ mongodb:
+ databaseRef:
+ name:
+ namespace:
+ pluginName:
+ allowedRoles:
+ - "role1"
+ - "role2"
+ writeConcern:
+```
+
+- `databaseRef` : `Required`. Specifies an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference that is required to connect to a MongoDB database. It is also used to generate `db_name` (i.e. `/v1/path/config/db_name`) where the database secret engine will be configured at. The naming of `db_name` follows: `k8s.{clusterName}.{namespace}.{name}`.
+
+ - `name` : `Required`. Specifies the AppBinding name.
+
+ - `namespace` : `Required`. Specifies the AppBinding namespace.
+
+ ```yaml
+ mongodb:
+ databaseRef:
+ name: db-app
+ namespace: demo
+ ```
+
+ The generated `db_name` for the above example will be: `k8s.-.demo.db-app`. If the cluster name is empty, it is replaced by "`-`".
+
+- `pluginName` : `Optional`. Specifies the name of the plugin to use for this connection.
+Default plugin name is `mongodb-database-plugin`.
+
+ ```yaml
+ mongodb:
+ pluginName: mongodb-database-plugin
+ ```
+
+- `allowedRoles` : `Optional`. Specifies a list of roles allowed to use this connection.
+ Default to `"*"` (i.e. any role can use this connection).
+
+ ```yaml
+ mongodb:
+ allowedRoles:
+ - "readonly"
+ ```
+
+- `writeConcern` : `Optional`. Specifies the MongoDB write concern.
+ This is set for the entirety of the session, maintained for the life cycle of the plugin process. Must be a serialized JSON object,
+ or a base64-encoded serialized JSON object. The JSON payload values map to the values in the Safe struct from the mongo driver.
+
+ ```yaml
+ mongodb:
+ writeConcern: `{ \"wmode\": \"majority\", \"wtimeout\": 5000 }`
+ ```
+
+#### spec.mysql
+
+`spec.mysql` specifies the configuration required to configure MySQL database secret engine. [See more](https://www.vaultproject.io/api/secret/databases/mysql-maria.html#configure-connection)
+
+ ```yaml
+ spec:
+ mysql:
+ databaseRef:
+ name:
+ namespace:
+ pluginName:
+ allowedRoles:
+ - "role1"
+ - "role2"
+ - ... ...
+ maxOpenConnections:
+ maxIdleConnections:
+ maxConnectionLifetime:
+ ```
+
+- `databaseRef` : `Required`. Specifies an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference that is required to connect to a MySQL database. It is also used to generate `db_name` (i.e. `/v1/path/config/db_name`) where the database secret engine will be configured at. The naming of `db_name` follows: `k8s.{clusterName}.{namespace}.{name}`.
+
+ - `name` : `Required`. Specifies the AppBinding name.
+
+ - `namespace` : `Required`. Specifies the AppBinding namespace.
+
+ ```yaml
+ mysql:
+ databaseRef:
+ name: db-app
+ namespace: demo
+ ```
+
+ The generated `db_name` for the above example will be: `k8s.-.demo.db-app`. If the cluster name is empty, it is replaced by "`-`".
+
+- `pluginName` : `Optional`. Specifies the name of the plugin to use for this connection.
+ The default plugin name is `mysql-database-plugin`.
+
+ ```yaml
+ mysql:
+ pluginName: mysql-database-plugin
+ ```
+
+- `allowedRoles` : `Optional`. Specifies a list of roles allowed to use this connection.
+ Default to `"*"` (i.e. any role can use this connection).
+
+ ```yaml
+ mysql:
+ allowedRoles:
+ - "readonly"
+ ```
+
+- `maxOpenConnections` : `Optional`. Specifies the maximum number of open connections to the database. Default value 2.
+
+ ```yaml
+ mysql:
+ maxOpenConnections: 3
+ ```
+
+- `maxIdleConnections` : `Optional`. Specifies the maximum number of idle connections to the database. Zero uses the value of max_open_connections and a negative value disables idle connections. If larger than max_open_connections it will be reduced to be equal. Default value 0.
+
+ ```yaml
+ mysql:
+ maxIdleConnections: 1
+ ```
+
+- `maxConnectionLifetime` : `Optional`. Specifies the maximum amount of time a connection may be reused. If <= 0s connections are reused forever. Default value 0s.
+
+ ```yaml
+ mysql:
+ maxConnectionLifetime: 5s
+ ```
+
+#### spec.elasticsearch
+
+`spec.elasticsearch` specifies the configuration required to configure Elasticsearch database secret engine. [See more](https://www.vaultproject.io/api/secret/databases/elasticdb.html#configure-connection)
+
+ ```yaml
+ spec:
+ elasticsearch:
+ databaseRef:
+ name:
+ namespace:
+ pluginName:
+ allowedRoles:
+ - "role1"
+ - "role2"
+ - ... ...
+ ```
+
+- `databaseRef` : `Required`. Specifies an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference that is required to connect to an Elasticsearch database. It is also used to generate `db_name` (i.e. `/v1/path/config/db_name`) where the database secret engine will be configured at. The naming of `db_name` follows: `k8s.{clusterName}.{namespace}.{name}`.
+
+ - `name` : `Required`. Specifies the AppBinding name.
+
+ - `namespace` : `Required`. Specifies the AppBinding namespace.
+
+ ```yaml
+ elasticsearch:
+ databaseRef:
+ name: db-app
+ namespace: demo
+ ```
+
+ The generated `db_name` for the above example will be: `k8s.-.demo.db-app`. If the cluster name is empty, it is replaced by "`-`".
+
+- `pluginName` : `Optional`. Specifies the name of the plugin to use for this connection.
+ The default plugin name is `elasticsearch-database-plugin`.
+
+ ```yaml
+ elasticsearch:
+ pluginName: elasticsearch-database-plugin
+ ```
+
+- `allowedRoles` : `Optional`. Specifies a list of roles allowed to use this connection.
+ Default to `"*"` (i.e. any role can use this connection).
+
+ ```yaml
+ elasticsearch:
+ allowedRoles:
+ - "readonly"
+ ```
+
+#### spec.redis
+`spec.redis` specifies the configuration required to configure Redis database secret engine. [See more](https://developer.hashicorp.com/vault/api-docs/secret/databases/redis#configure-connection)
+
+ ```yaml
+ spec:
+ redis:
+ databaseRef:
+ name:
+ namespace:
+ pluginName:
+ allowedRoles:
+ - "role1"
+ - "role2"
+ - ... ...
+ ```
+
+- `databaseRef` : `Required`. Specifies an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) reference that is required to connect to an Redis database. It is also used to generate `db_name` (i.e. `/v1/path/config/db_name`) where the database secret engine will be configured at. The naming of `db_name` follows: `k8s.{clusterName}.{namespace}.{name}`.
+
+ - `name` : `Required`. Specifies the AppBinding name.
+
+ - `namespace` : `Required`. Specifies the AppBinding namespace.
+
+ ```yaml
+ redis:
+ databaseRef:
+ name: db-app
+ namespace: demo
+ ```
+
+ The generated `db_name` for the above example will be: `k8s.-.demo.db-app`. If the cluster name is empty, it is replaced by "`-`".
+
+- `pluginName` : `Optional`. Specifies the name of the plugin to use for this connection.
+ The default plugin name is `redis-database-plugin`.
+
+ ```yaml
+ redis:
+ pluginName: redis-database-plugin
+ ```
+
+- `allowedRoles` : `Optional`. Specifies a list of roles allowed to use this connection.
+ Default to `"*"` (i.e. any role can use this connection).
+
+ ```yaml
+ redis:
+ allowedRoles:
+ - "readonly"
+ ```
+
+
+### SecretEngine Status
+
+`status` shows the status of the SecretEngine. It is managed by the KubeVault operator. It contains the following fields:
+
+- `observedGeneration`: Specifies the most recent generation observed for this resource. It corresponds to the resource's generation, which is updated on mutation by the API Server.
+
+- `phase`: Indicates whether the secret engine successfully configured in the Vault or not.
+
+- `conditions` : Represent observations of a SecretEngine.
diff --git a/content/docs/v2025.11.21/concepts/tls-encryption/_index.md b/content/docs/v2025.11.21/concepts/tls-encryption/_index.md
new file mode 100644
index 000000000..fe033cf9c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/tls-encryption/_index.md
@@ -0,0 +1,17 @@
+---
+title: Concepts | Vault Server TLS
+menu:
+ docs_v2025.11.21:
+ identifier: vault-server-tls
+ name: Vault Server TLS
+ parent: concepts
+ weight: 50
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/tls-encryption/configuration.md b/content/docs/v2025.11.21/concepts/tls-encryption/configuration.md
new file mode 100644
index 000000000..3f7f24134
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/tls-encryption/configuration.md
@@ -0,0 +1,127 @@
+---
+title: Configure TLS/SSL for VaultServer | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: vault-tls-concepts
+ name: TLS/SSL Configuration
+ parent: vault-server-tls
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Configure TLS/SSL for VaultServer
+
+`KubeVault` provides support for TLS/SSL for `VaultServer`. This tutorial will show you how to use `KubeVault` to deploy a `VaultServer` with TLS/SSL configuration.
+
+## Before You Begin
+
+- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
+
+- Install [`cert-manger`](https://cert-manager.io/docs/installation/) v1.4.0 or later to your cluster to manage your SSL/TLS certificates.
+
+- Install `KubeVault` operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial.
+
+ ```bash
+ $ kubectl create ns demo
+ namespace/demo created
+ ```
+
+### Deploy VaultServer with TLS/SSL configuration
+
+As pre-requisite, at first, we are going to create an Issuer/ClusterIssuer. This Issuer/ClusterIssuer is used to create certificates. Then we are going to deploy a VaultServer with TLS/SSL configuration.
+
+### Create Issuer/ClusterIssuer
+
+Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer,
+
+- Start off by generating our ca-certificates using openssl,
+
+```bash
+$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=vault/O=kubevault"
+```
+
+- create a secret using the certificate files we have just generated,
+
+```bash
+$ kubectl create secret tls vault-ca --cert=ca.crt --key=ca.key --namespace=demo
+secret/vault-ca created
+```
+
+Now, we are going to create an `Issuer` using the `vault-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` cr that we are going to create,
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: vault-issuer
+ namespace: demo
+spec:
+ ca:
+ secretName: vault-ca
+```
+
+Let’s create the `Issuer` cr we have shown above,
+
+```bash
+$ kubectl apply -f issuer.yaml
+issuer.cert-manager.io/vault-issuer created
+```
+
+### Deploy VaultServer with TLS/SSL configuration
+
+Here, our issuer `vault-issuer` is ready to deploy a `VaultServer` Cluster with TLS/SSL configuration. Below is the YAML for VaultServer that we are going to create,
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ tls:
+ issuerRef:
+ apiGroup: "cert-manager.io"
+ kind: Issuer
+ name: vault-issuer
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ secretEngines:
+ - mysql
+ version: 1.10.3
+ replicas: 3
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
+```
+
+Here,
+
+- `spec.tls.issuerRef` refers to the `vault-issuer` issuer.
diff --git a/content/docs/v2025.11.21/concepts/tls-encryption/overview.md b/content/docs/v2025.11.21/concepts/tls-encryption/overview.md
new file mode 100644
index 000000000..110d3edf0
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/tls-encryption/overview.md
@@ -0,0 +1,118 @@
+---
+title: Overview | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: vault-tls-overview
+ name: Overview
+ parent: vault-server-tls
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Overview
+
+**Prerequisite :** To configure TLS/SSL in `VaultServer`, `KubeVault` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/).
+
+To issue a certificate, the following cr of `cert-manager` is used:
+
+- `Issuer/ClusterIssuer`: Issuers and ClusterIssuers represent certificate authorities (CAs) that are able to generate signed certificates by honoring certificate signing requests. All cert-manager certificates require a referenced issuer that is in a ready condition to attempt to honor the request. You can learn more details [here](https://cert-manager.io/docs/concepts/issuer/).
+
+- `Certificate`: `cert-manager` has the concept of Certificates that define the desired x509 certificate which will be renewed and kept up to date. You can learn more details [here](https://cert-manager.io/docs/concepts/certificate/).
+
+**VaultServer CRD Specification:**
+
+KubeValt uses the following cr fields to enable SSL/TLS encryption in `VaultServer`.
+
+```yaml
+spec:
+ tls:
+ issuerRef:
+ apiGroup: "cert-manager.io"
+ kind: Issuer
+ name: vault-issuer
+ certificates:
+ - alias: server
+ secretName: vautl-server-certs
+ subject:
+ organizations:
+ - kubevault
+ - alias: client
+ secretName: vault-client-certs
+ subject:
+ organizations:
+ - kubevault
+
+```
+
+The `spec.tls` contains the following fields:
+
+- `tls.issuerRef` - is an `optional` field that references to the `Issuer` or `ClusterIssuer` custom resource object of [cert-manager](https://cert-manager.io/docs/concepts/issuer/). It is used to generate the necessary certificate secrets for Elasticsearch. If the `issuerRef` is not specified, the operator creates a self-signed CA and also creates necessary certificate (valid: 365 days) secrets using that CA.
+ - `apiGroup` - is the group name of the resource that is being referenced. Currently, the only supported value is `cert-manager.io`.
+ - `kind` - is the type of resource that is being referenced. The supported values are `Issuer` and `ClusterIssuer`.
+ - `name` - is the name of the resource ( `Issuer` or `ClusterIssuer` ) that is being referenced.
+
+- `tls.certificates` - is an `optional` field that specifies a list of certificate configurations used to configure the certificates. It has the following fields:
+ - `alias` - represents the identifier of the certificate. It has the following possible value:
+ - `server` - is used for the server certificate configuration.
+ - `client` - is used for the client certificate configuration.
+ - `storage` - is used for the storage certificate configuration.
+ - `ca` - is used for the ca certificate configuration.
+
+ - `secretName` - ( `string` | `"-alias-certs"` ) - specifies the k8s secret name that holds the certificates.
+
+ - `subject` - specifies an `X.509` distinguished name (DN). It has the following configurable fields:
+ - `organizations` ( `[]string` | `nil` ) - is a list of organization names.
+ - `organizationalUnits` ( `[]string` | `nil` ) - is a list of organization unit names.
+ - `countries` ( `[]string` | `nil` ) - is a list of country names (ie. Country Codes).
+ - `localities` ( `[]string` | `nil` ) - is a list of locality names.
+ - `provinces` ( `[]string` | `nil` ) - is a list of province names.
+ - `streetAddresses` ( `[]string` | `nil` ) - is a list of street addresses.
+ - `postalCodes` ( `[]string` | `nil` ) - is a list of postal codes.
+ - `serialNumber` ( `string` | `""` ) is a serial number.
+
+ For more details, visit [here](https://golang.org/pkg/crypto/x509/pkix/#Name).
+
+ - `duration` ( `string` | `""` ) - is the period during which the certificate is valid. A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as `"300m"`, `"1.5h"` or `"20h45m"`. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+ - `renewBefore` ( `string` | `""` ) - is a specifiable time before expiration duration.
+ - `dnsNames` ( `[]string` | `nil` ) - is a list of subject alt names.
+ - `ipAddresses` ( `[]string` | `nil` ) - is a list of IP addresses.
+ - `uris` ( `[]string` | `nil` ) - is a list of URI Subject Alternative Names.
+ - `emailAddresses` ( `[]string` | `nil` ) - is a list of email Subject Alternative Names.
+
+
+## How TLS/SSL configures in VaultServer
+
+The following figure shows how `KubeVault` is used to configure TLS/SSL in Postgres. Open the image in a new tab to see the enlarged version.
+
+Deploying VaultServer with TLS/SSL configuration process consists of the following steps:
+
+1. At first, a user creates an `Issuer/ClusterIssuer` cr.
+
+2. Then the user creates a `VaultServer` cr.
+
+3. `KubeVault` community operator watches for the `VaultServer` cr.
+
+4. When it finds one, it creates `Secret`, `Service`, etc. for the `VaultServer`.
+
+5. `KubeVault` operator watches for `VaultServer`(5c), `Issuer/ClusterIssuer`(5b), `Secret` and `Service`(5a).
+
+6. When it finds all the resources(`VaultServer`, `Issuer/ClusterIssuer`, `Secret`, `Service`), it creates `Certificates` by using `tls.issuerRef` and `tls.certificates` field specification from `VaultServer` cr.
+
+7. `cert-manager` watches for certificates.
+
+8. When it finds one, it creates certificate secrets `cert-secrets`(server, client, exporter secrets, etc.) that hold the actual self-signed certificate.
+
+9. `KubeVault` community operator watches for the Certificate secrets `tls-secrets`.
+
+10. When it finds all the tls-secret, it creates a `StatefulSet` so that Postgres server is configured with TLS/SSL.
+
+In the next doc, we are going to show a step by step guide on how to configure a `VaultServer` with TLS/SSL.
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/concepts/vault-ops-request/_index.md b/content/docs/v2025.11.21/concepts/vault-ops-request/_index.md
new file mode 100644
index 000000000..a3ae18516
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-ops-request/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Ops Request | Concepts | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: ops-request-concepts
+ name: Vault Ops Request
+ parent: concepts
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/vault-ops-request/overview.md b/content/docs/v2025.11.21/concepts/vault-ops-request/overview.md
new file mode 100644
index 000000000..f3620f9e5
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-ops-request/overview.md
@@ -0,0 +1,210 @@
+---
+title: Vault Ops Request Overview | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: overview-ops-request-concepts
+ name: Overview
+ parent: ops-request-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/README).
+
+# VaultOpsRequest
+
+## What is VaultOpsRequest
+
+`VaultOpsRequest` is a Kubernetes `Custom Resource Definitions` (CRD). It provides a declarative configuration for `Vault` administrative operations like restart, reconfigure TLS etc. in a Kubernetes native way.
+
+## VaultOpsRequest CRD Specifications
+
+Like any official Kubernetes resource, a `VaultOpsRequest` has `TypeMeta`, `ObjectMeta`, `Spec` and Status sections.
+
+Here, some sample `VaultOpsRequest` CRs for different administrative operations is given below:
+
+### Sample `VaultOpsRequest` for restarting `VaultServer`:
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: restart-vault-request
+ namespace: demo
+spec:
+ restart: {}
+ type: Restart
+ vaultRef:
+ name: vault
+status:
+ conditions:
+ - lastTransitionTime: "2022-12-04T09:27:07Z"
+ message: Vault ops request is restarting nodes
+ observedGeneration: 1
+ reason: Restart
+ status: "True"
+ type: Restart
+ - lastTransitionTime: "2022-12-04T09:29:23Z"
+ message: Successfully restarted all nodes
+ observedGeneration: 1
+ reason: RestartNodes
+ status: "True"
+ type: RestartNodes
+ - lastTransitionTime: "2022-12-04T09:29:23Z"
+ message: Successfully completed the modification process.
+ observedGeneration: 1
+ reason: Successful
+ status: "True"
+ type: Successful
+ observedGeneration: 1
+ phase: Successful
+
+```
+
+### Sample `VaultOpsRequest` Objects for Reconfiguring TLS of the `VaultServer`:
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-add-tls
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ issuerRef:
+ name: vault-issuer
+ kind: Issuer
+ apiGroup: "cert-manager.io"
+ certificates:
+ - alias: client
+ emailAddresses:
+ - abc@appscode.com
+
+```
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-rotate
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ rotateCertificates: true
+
+```
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-change-issuer
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ issuerRef:
+ name: vault-new-issuer
+ kind: Issuer
+ apiGroup: "cert-manager.io"
+
+```
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-remove
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ remove: true
+
+```
+
+Here, we are going to describe the various sections of a `VaultOpsRequest` crd.
+
+A `VaultOpsRequest` object has the following fields in the spec section.
+
+### spec.vaultRef
+
+`spec.vaultRef` is a required field that point to the `Vault` object for which the administrative operations will be performed. This field consists of the following sub-field:
+- `spec.databaseRef.name` : specifies the name of the `Vault` object.
+
+### spec.type
+
+`spec.type` specifies the kind of operation that will be applied to the `VaultServer`. Currently, the following types of operations are allowed in `VaultOpsRequest`.
+- Restart
+- ReconfigureTLS
+
+You can perform only one type of operation on a single `VaultOpsRequest` CR. You should not create two `VaultOpsRequest` simultaneously.
+
+### spec.tls
+
+If you want to reconfigure the TLS configuration of your `VaultServer` i.e. add TLS, remove TLS, update issuer/cluster issuer or Certificates and rotate the certificates, you have to specify `spec.tls` section. This field consists of the following sub-field:
+
+- `spec.tls.issuerRef` specifies the issuer name, kind and api group.
+- `spec.tls.certificates` specifies the certificates.
+- `spec.tls.rotateCertificates` specifies that we want to rotate the certificate of this `VaultServer`.
+- `spec.tls.remove` specifies that we want to remove tls from this `VaultServer`.
+
+### VaultOpsRequest `Status`
+
+`.status` describes the current state and progress of a `VautlOpsRequest` operation. It has the following fields:
+
+### status.phase
+
+`status.phase` indicates the overall phase of the operation for this `VaultOpsRequest`. It can have the following three values:
+
+| Phase | Meaning |
+| ---------- |-------------------------------------------------------------------------------------|
+| Successful | KubeVault has successfully performed the operation requested in the VaultOpsRequest |
+| Failed | KubeVault has failed the operation requested in the VaultOpsRequest |
+| Denied | KubeVault has denied the operation requested in the VaultOpsRequest |
+
+### status.observedGeneration
+
+`status.observedGeneration` shows the most recent generation observed by the `VaultOpsRequest` controller.
+
+### status.conditions
+
+`status.conditions` is an array that specifies the conditions of different steps of `VaultOpsRequest` processing. Each condition entry has the following fields:
+- `types` specifies the type of the condition. `VaultOpsRequest` has the following types of conditions:
+
+| Type | Meaning |
+|------------------------------|-------------------------------------------------------------------------------|
+| `Progressing` | Specifies that the operation is now in the progressing state |
+| `Successful` | Specifies such a state that the operation on the vault was successful. |
+| `ResumeVaultServer` | Specifies such a state that the vault is resumed by the operator |
+| `Failed` | Specifies such a state that the operation on the database failed. |
+| `UpdateStatefulSetResources` | Specifies such a state that the Statefulset resources has been updated |
+| `RestartNodes` | Specifies whether the vault nodes has been restarted or not |
+| `CertificateSynced` | Specifies whether the certificates has been synced across all the vault nodes |
+
+
+- The `status` field is a string, with possible values `True`, `False`, and `Unknown`.
+ - `status` will be `True` if the current transition succeeded.
+ - `status` will be `False` if the current transition failed.
+ - `status` will be `Unknown` if the current transition was denied.
+- The `message` field is a human-readable message indicating details about the condition.
+- The `reason` field is a unique, one-word, CamelCase reason for the condition's last transition.
+- The `lastTransitionTime` field provides a timestamp for when the operation last transitioned from one state to another.
+- The `observedGeneration` shows the most recent condition transition generation observed by the controller.
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/_index.md b/content/docs/v2025.11.21/concepts/vault-server-crds/_index.md
new file mode 100755
index 000000000..03295988e
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Server | Concepts | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: vault-server-crds-concepts
+ name: Vault Server
+ parent: concepts
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/appbinding.md b/content/docs/v2025.11.21/concepts/vault-server-crds/appbinding.md
new file mode 100644
index 000000000..4307dd029
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/appbinding.md
@@ -0,0 +1,285 @@
+---
+title: AppBinding | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: appbinding-vault-server-crds
+ name: AppBinding
+ parent: vault-server-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# AppBinding
+
+## What is AppBinding
+
+AppBinding CRD provides a way to specify connection information, credential, and parameters that are necessary for communicating with an app/service. In KubeVault operator, AppBinding used to communicate with externally provisioned Vault, database, etc.
+
+An `AppBinding` is a Kubernetes `CustomResourceDefinition`(CRD) which points to an application using either its URL (usually for a non-Kubernetes resident service instance) or a Kubernetes service object (if self-hosted in a Kubernetes cluster), some optional parameters and a credential secret. To learn more about AppBinding and the problems it solves, please read this blog post: [The case for AppBinding](https://blog.byte.builders/post/the-case-for-appbinding).
+
+If you deploy a Vault using [KubeVault](https://kubevault.com/docs/latest/welcome/), the `AppBinding` object will be created automatically for it. Otherwise, you have to create an `AppBinding` object manually pointing to your desired Vault.
+
+KubeVault uses [Stash](https://stash.run/) to perform backup/recovery of Vault cluster. Stash needs to know how to connect with a target Vault and the credentials necessary to access it. This is done via an `AppBinding`.
+
+## AppBinding CRD Specification
+
+Like any official Kubernetes resource, an `AppBinding` has `TypeMeta`, `ObjectMeta` and `Spec` sections. However, unlike other Kubernetes resources, it does not have a `Status` section.
+
+An `AppBinding` object created by `KubeVault` for a Vault is shown below,
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ appRef:
+ apiGroup: kubevault.com
+ kind: VaultServer
+ name: vault
+ namespace: demo
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ backend: raft
+ backupTokenSecretRef:
+ name: vault-backup-token
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.75cf1449-0675-4cce-9fbe-965441450355.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.75cf1449-0675-4cce-9fbe-965441450355.demo.vault
+ unsealer:
+ mode:
+ googleKmsGcs:
+ bucket: vault-testing-keys
+ credentialSecretRef:
+ name: gcp-cred
+ kmsCryptoKey: vault-testing-key
+ kmsKeyRing: vault-testing
+ kmsLocation: global
+ kmsProject: appscode-testing
+ secretShares: 5
+ secretThreshold: 3
+ vaultRole: vault-policy-controller
+```
+
+Here, we are going to describe the sections of an `AppBinding` crd.
+
+Here, we are going to describe the sections of an `AppBinding` crd that are relevant to KubeVault.
+
+### AppBinding `Spec`
+
+An `AppBinding` object has the following fields in the `spec` section:
+
+### spec.appRef
+
+`spec.appRef` refers to the application for which this AppBinding was created.
+
+```yaml
+appRef:
+ apiGroup: kubevault.com
+ kind: VaultServer
+ name: vault
+ namespace: demo
+```
+
+#### spec.parameters.backupTokenSecretRef
+
+`spec.parameters.backupTokenSecretRef` specifies the name of the secret which contains the token with the permission to take backup snapshot & restore. This secret must be in the same namespace as the `AppBinding`.
+
+This secret must contain the following keys:
+
+| Key | Usage |
+|:----------:|---------------------------------------------------------|
+| `token` | token with permission to take backup snapshot & restore |
+
+### spec.parameters.backend
+
+`spec.parameters.backend` indicates the Storage Backend type Vault is using.
+
+### spec.parameters.stash
+
+`spec.parameters.stash` section contains the stash parameters for Backup & Restore tasks. `spec.parameters.stash.addon` contains the
+information about the `Task` for backup & restore. It also contains the `params` which indicates the `keyPrefix`
+that is prepended with the name of vault `unseal-keys` & `root-token`,
+e.g. `k8s.kubevault.com.demo.vault-root-token`, `k8s.kubevault.com.demo.vault-root-token-unseal-key-0`, `k8s.kubevault.com.demo.vault-root-token-unseal-key-1`, etc.
+
+```yaml
+stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+```
+
+### spec.parameters.unsealer
+
+`spec.parameters.unsealer` contains the Vault unsealer information, e.g. secret shares & threshold of unseal keys, the location of unseal-keys, etc.
+
+```yaml
+unsealer:
+ mode:
+ googleKmsGcs:
+ bucket: vault-testing-keys
+ credentialSecretRef:
+ name: gcp-cred
+ kmsCryptoKey: vault-testing-key
+ kmsKeyRing: vault-testing
+ kmsLocation: global
+ kmsProject: appscode-testing
+ secretShares: 5
+ secretThreshold: 3
+```
+
+### spec.clientConfig
+
+`spec.clientConfig` is a required field that specifies the information to make a connection with an app.
+
+```yaml
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: HTTPS
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+It has the following fields:
+
+- `clientConfig.url` : `Optional`. Specifies the location of the app, in standard URL form (`[scheme://]host:port/path`).
+
+- `clientConfig.service`: `Optional`. Specifies the reference of the Kubernetes service for this app. It has the following fields:
+
+ - `service.scheme` : `Optional`. Specifies which scheme to use, for example, HTTP, https. If specified, then it will be applied as the prefix in this format: `scheme://`. If not specified, then nothing will be prefixed.
+ - `service.name` : `Required`. Specifies the name of the service. This `service.name` and AppBinding's namespace will be used to create app DNS.
+ - `service.port` : `Required`. Specifies the port that will be exposed by this app.
+ - `service.path` : `Optional`. Specifies the URL path which will be sent in any request to this service.
+ - `service.query` : `Optional`. Specifies the encoded query string, without '?' which will be sent in any request to this service.
+
+> Note: Either `clientConfig.url` or `clientConfig.service` must be specified.
+
+- `clientConfig.caBundle`: `Optional`. Specifies the PEM encoded CA bundle which will be used to validate the serving certificate of this app.
+
+- `clientConfig.insecureSkipTLSVerify`: `Optional`. To skip TLS certificate verification when communicating with this app. This is strongly discouraged. You should use the `clientConfig.caBundle` instead.
+
+### spec.secret
+
+`spec.secret` is an optional field that specifies the name of the secret containing credentials associated with AppBinding. It must be in AppBinding's namespace.
+
+```yaml
+spec:
+ secret:
+ name: vault-token
+```
+
+### spec.parameters
+
+`spce.parameters` is an optional field that specifies the list of parameters to be used to connect to the app, backup, restore, etc. The Parameters field is *not* secret or secured in any way and should *never* be used to hold sensitive information.
+
+```yaml
+spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ backend: raft
+ backupTokenSecretRef:
+ name: vault-backup-token
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.75cf1449-0675-4cce-9fbe-965441450355.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.75cf1449-0675-4cce-9fbe-965441450355.demo.vault
+ unsealer:
+ mode:
+ googleKmsGcs:
+ bucket: vault-testing-keys
+ credentialSecretRef:
+ name: gcp-cred
+ kmsCryptoKey: vault-testing-key
+ kmsKeyRing: vault-testing
+ kmsLocation: global
+ kmsProject: appscode-testing
+ secretShares: 5
+ secretThreshold: 3
+ vaultRole: vault-policy-controller
+```
+
+### spec.secretTransforms
+
+`spec.secretTransforms` is an optional field that contains the list of transformations that should be applied to the credentials associated with the AppBinding before they are inserted into the Secret. For example, the credential secret specified in `spec.secret.name` has the key `USERNAME`, but the consumer requires the username to be exposed under the key `DB_USER` instead. To have the KubeVault operator transform the secret, the following secret transformation must be specified in `spec.secretTransforms`.
+
+```yaml
+spec:
+ secretTransforms:
+ - renameKey:
+ from: USERNAME
+ to: DB_USER
+```
+
+It has the following fields:
+
+- `secretTransforms[].renameKey`: `Optional`. Specifies a transform that renames a credentials secret entry's key. It has the following fields:
+ - `renameKey.from`: `Required`. Specifies the name of the key to rename.
+ - `renameKey.to`: `Required`. Specifies the new name for the key.
+
+- `secretTransforms[].addKey`: `Optional`. Specifies a transform that adds an additional key to the credentials secret.
+ - `addKey.key`: `Required`. Specifies the name of the key to add.
+ - `addKey.value`: `Required`. Specifies the value (possibly non-binary) to add to the secret under the specified key.
+ - `addKey.stringValue`: `Required`. Specifies the string value to add to the secret under the specified key. If both `addKey.value` and `addKey.stringValue` are specified, then `addKey.value` is ignored and `addKey.stringValue` is stored.
+ - `addKey.jsonPathExpression`: `Required`. Specifies the JSONPath expression, the result of which will be added to the Secret under the specified key. For example, given the following credentials: `{ "foo": { "bar": "foobar" } }` and the jsonPathExpression `{.foo.bar}`, the value `foobar` will be stored in the credentials secret under the specified key.
+
+- `secretTransforms[].addKeysFrom`: `Optional`. Specifies a transform that merges all the entries of an existing secret into the credentials secret.
+ - `addKeysFrom.secretRef.name`: `Optinal`. Specifies the name of the secret.
+ - `addKeysFrom.secretRef.namespace`: `Optinal`. Specifies the namespace of the secret.
+
+- `secretTransforms[].removeKey`: `Optional`. Specifies a transform that removes a credentials secret entry.
+ - `removeKey.key`. `Required`. Specifies the key to remove from secret.
+
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/_index.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/_index.md
new file mode 100755
index 000000000..028963fcf
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Server Authentication
+menu:
+ docs_v2025.11.21:
+ identifier: auth-methods-vault-server-crds
+ name: Authentication
+ parent: vault-server-crds-concepts
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding.md
new file mode 100644
index 000000000..14fb8cc87
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding.md
@@ -0,0 +1,156 @@
+---
+title: AppBinding | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: appbinding-auth-methods
+ name: AppBinding
+ parent: auth-methods-vault-server-crds
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# AppBinding
+
+## What is AppBinding
+
+AppBinding CRD provides a way to specify connection information, credential, and parameters that are necessary for communicating with an app/service. In KubeVault operator, AppBinding used to communicate with externally provisioned Vault, database, etc.
+
+An `AppBinding` is a Kubernetes `CustomResourceDefinition`(CRD) which points to an application using either its URL (usually for a non-Kubernetes resident service instance) or a Kubernetes service object (if self-hosted in a Kubernetes cluster), some optional parameters and a credential secret. To learn more about AppBinding and the problems it solves, please read this blog post: [The case for AppBinding](https://blog.byte.builders/post/the-case-for-appbinding).
+
+## AppBinding CRD Specification
+
+Like any official Kubernetes resource, an `AppBinding` has `TypeMeta`, `ObjectMeta` and `Spec` sections. However, unlike other Kubernetes resources, it does not have a `Status` section.
+
+An `AppBinding` object created by `KubeVault` for a Vault server is shown below,
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ type: vault
+ secret:
+ name: vault-token
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: HTTPS
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+Here, we are going to describe the sections of an `AppBinding` crd that are relevant to KubeVault.
+
+### AppBinding `Spec`
+
+An `AppBinding` object has the following fields in the `spec` section:
+
+### spec.type
+
+`spec.type` is an optional field that specifies the type of app.
+
+```yaml
+spec:
+ type: vault
+```
+
+### spec.clientConfig
+
+`spec.clientConfig` is a required field that specifies the information to make a connection with an app.
+
+```yaml
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: HTTPS
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+It has following fields:
+
+- `clientConfig.url` : `Optional`. Specifies the location of the app, in standard URL form (`[scheme://]host:port/path`).
+
+- `clientConfig.service`: `Optional`. Specifies the reference of the Kubernetes service for this app. It has the following fields:
+
+ - `service.scheme` : `Optional`. Specifies which scheme to use, for example, HTTP, https. If specified, then it will be applied as the prefix in this format: `scheme://`. If not specified, then nothing will be prefixed.
+ - `service.name` : `Required`. Specifies the name of the service. This `service.name` and AppBinding's namespace will be used to create app DNS.
+ - `service.port` : `Required`. Specifies the port that will be exposed by this app.
+ - `service.path` : `Optional`. Specifies the URL path which will be sent in any request to this service.
+ - `service.query` : `Optional`. Specifies the encoded query string, without '?' which will be sent in any request to this service.
+
+> Note: Either `clientConfig.url` or `clientConfig.service` must be specified.
+
+- `clientConfig.caBundle`: `Optional`. Specifies the PEM encoded CA bundle which will be used to validate the serving certificate of this app.
+
+- `clientConfig.insecureSkipTLSVerify`: `Optional`. To skip TLS certificate verification when communicating with this app. This is strongly discouraged. You should use the `clientConfig.caBundle` instead.
+
+### spec.secret
+
+`spec.secret` is an optional field that specifies the name of the secret containing credentials associated with AppBinding. It must be in AppBinding's namespace.
+
+```yaml
+spec:
+ secret:
+ name: vault-token
+```
+
+### spec.parameters
+
+`spce.parameters` is an optional field that specifies the list of parameters to be used to connect to the app. The Parameters field is *not* secret or secured in any way and should *never* be used to hold sensitive information.
+
+```yaml
+spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes
+ vaultRole: vault-policy-controller
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+```
+
+### spec.secretTransforms
+
+`spec.secretTransforms` is an optional field that contains the list of transformations that should be applied to the credentials associated with the AppBinding before they are inserted into the Secret. For example, the credential secret specified in `spec.secret.name` has the key `USERNAME`, but the consumer requires the username to be exposed under the key `DB_USER` instead. To have the KubeVault operator transform the secret, the following secret transformation must be specified in `spec.secretTransforms`.
+
+```yaml
+spec:
+ secretTransforms:
+ - renameKey:
+ from: USERNAME
+ to: DB_USER
+```
+
+It has the following fields:
+
+- `secretTransforms[].renameKey`: `Optional`. Specifies a transform that renames a credentials secret entry's key. It has the following fields:
+ - `renameKey.from`: `Required`. Specifies the name of the key to rename.
+ - `renameKey.to`: `Required`. Specifies the new name for the key.
+
+- `secretTransforms[].addKey`: `Optional`. Specifies a transform that adds an additional key to the credentials secret.
+ - `addKey.key`: `Required`. Specifies the name of the key to add.
+ - `addKey.value`: `Required`. Specifies the value (possibly non-binary) to add to the secret under the specified key.
+ - `addKey.stringValue`: `Required`. Specifies the string value to add to the secret under the specified key. If both `addKey.value` and `addKey.stringValue` are specified, then `addKey.value` is ignored and `addKey.stringValue` is stored.
+ - `addKey.jsonPathExpression`: `Required`. Specifies the JSONPath expression, the result of which will be added to the Secret under the specified key. For example, given the following credentials: `{ "foo": { "bar": "foobar" } }` and the jsonPathExpression `{.foo.bar}`, the value `foobar` will be stored in the credentials secret under the specified key.
+
+- `secretTransforms[].addKeysFrom`: `Optional`. Specifies a transform that merges all the entries of an existing secret into the credentials secret.
+ - `addKeysFrom.secretRef.name`: `Optinal`. Specifies the name of the secret.
+ - `addKeysFrom.secretRef.namespace`: `Optinal`. Specifies the namespace of the secret.
+
+- `secretTransforms[].removeKey`: `Optional`. Specifies a transform that removes a credentials secret entry.
+ - `removeKey.key`. `Required`. Specifies the key to remove from secret.
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/aws-iam.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/aws-iam.md
new file mode 100644
index 000000000..d42302be0
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/aws-iam.md
@@ -0,0 +1,89 @@
+---
+title: Connect to Vault using AWS IAM Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: aws-iam-auth-methods
+ name: AWS IAM
+ parent: auth-methods-vault-server-crds
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using AWS IAM Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. For [AWS IAM authentication](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method), it has to be enabled and configured in the Vault server. Follow the steps below to create an appropriate AppBinding:
+
+- You have to specify `spec.secret` in the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding).
+
+- The specified secret must be in AppBinding's namespace.
+
+- The type of the specified secret must be `"kubevault.com/aws"`.
+
+- The specified secret data can have the following key:
+ - `Secret.Data["access_key_id"]` : `Required`. Specifies AWS access key.
+ - `Secret.Data["secret_access_key"]` : `Required`. Specifies AWS access secret.
+ - `Secret.Data["security_token"]` : `Optional`. Specifies AWS security token.
+
+- The additional information required for AWS IAM authentication can be provided as AppBinding's `spec.parameters`.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-aws
+ vaultRole: demo
+ aws:
+ headerValue: vault.example.com
+ ```
+
+ - `parameters.path` : `optional`. Specifies the path where AWS auth is enabled in Vault. Default to `aws`.
+ - `parameters.vaultRole` : `required`. Specifies the name of the Vault auth [role](https://www.vaultproject.io/api/auth/aws/index.html#create-role) against which login will be performed.
+ - `parameters.aws.headerValue` : `optional`. Specifies the header value that required if X-Vault-AWS-IAM-Server-ID Header is set in Vault.
+
+Sample AppBinding and Secret is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: aws-cred
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-aws
+ vaultRole: demo
+ aws:
+ headerValue: vault.example.com
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aws-cred
+ namespace: demo
+type: kubevault.com/aws
+data:
+ access_key_id: cm9vdA==
+ secret_access_key: cm9vdA==
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/azure.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/azure.md
new file mode 100644
index 000000000..d542e7c6c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/azure.md
@@ -0,0 +1,95 @@
+---
+title: Connect to Vault using Azure Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: azure-auth-methods
+ name: Azure
+ parent: auth-methods-vault-server-crds
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using Azure Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. For [Azure authentication](https://www.vaultproject.io/docs/auth/azure.html), it has to be [enabled](https://www.vaultproject.io/docs/auth/azure.html#via-the-cli-1) and [configured](https://www.vaultproject.io/docs/auth/azure.html#via-the-cli-1) in the Vault server. Follow the steps below to create an appropriate AppBinding:
+
+- You have to specify the k8s secret name in `spec.secret` in the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding).
+
+- The specified secret must be in AppBinding's namespace.
+
+- The type of the specified secret must be `"kubevault.com/azure"`.
+
+- The specified secret data can have the following key:
+ - `Secret.Data["msiToken"]` : `Required`. Signed JSON Web Token (JWT) from Azure MSI. Documentation can be found in [here](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)
+
+- The additional information required for the Azure authentication method can be provided as AppBinding's `spec.parameters`.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-azure
+ vaultRole: demo-role
+ azure:
+ subscriptionID: 1bfc9f66-316d-433e-b13d-c55589f642ca
+ resourceGroupName: vault-test
+ vmName: test
+ vmssName: test-set
+ ```
+
+ - `path` : `optional`. Specifies the path where Azure auth is enabled in Vault. If this path is not provided, the path will be set by default path `azure`.
+ - `vaultRole` : `required`. Specifies the name of the Vault auth [role](https://www.vaultproject.io/api/auth/azure/index.html#create-role) against which login will be performed.
+ - `azure.subscriptionID` : `optional`. Specifies the subscription ID for the machine that generated the MSI token. This information can be obtained through instance metadata.
+ - `azure.resourceGroupName` : `optional`. Specifies the resource group for the machine that generated the MSI token. This information can be obtained through instance metadata.
+ - `azure.vmName` : `optional`. Specifies the virtual machine name for the machine that generated the MSI token. This information can be obtained through instance metadata. If `vmssName` is provided, this value is ignored.
+ - `azure.vmssName` : `optional`. Specifies the virtual machine scale set name for the machine that generated the MSI token. This information can be obtained through instance metadata.
+
+Sample AppBinding and Secret is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: azure-cred
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-azure
+ vaultRole: demo-role
+ azure:
+ subscriptionID: 1bfc9f66-316d-433e-b13d-c55589f642ca
+ resourceGroupName: vault-test
+ vmName: test
+ vmssName: test-set
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9UQTFNREl3T1RNeU5UaGFGdzB5T1RBME1qa3dPVE15TlRoYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdkVwTGVUT05ZRGxuTDkyMDlVQWY0Njc1CnR4MXpGL2J2UlZkejZjcVlYYWI1d0o0TmJoNGUxRFJDbmp6WXg1aDd0N1RLQXpvN3BWMWlzOFVHTTJUWGdPcloKa0hLQVJjOEFjekgxekE5Sk9mWkdGVk4xaXZBOTJHZ0xvVHNURDh4VTk0OWZ3Um8rYm5RemFqL2tLeHA5Z0puZQppYzBUenV5SEw2UTVseXRTVkoxWWhHSGdBdGM0eTBOcGZXZTZRekk1RnFXM2t1THFyaEVmRGV5TnR0UDUzaVV4ClpJN1IrbHBlVWsrY0NKZ2U0cTU1eGUvVmFpdEN6VVFIQVhLd0czRlNoYTc5cTBtb3J3N0ZIMW5YRDQwa0EwUXkKRlUxQTZtaDd5QVovb3BydWF0NFZjSDNwakdweGFvMzdLMGZQOXZXVjBvUnI5bm85YnM1MlI5L0I4cTVwYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFsd09iT3luNzZNMFRYMm53d1hlUkRreVdmNVczT3U4WGJQS3FEeXF1VnBIVUY2dHMKMmhuZFcyTXFJTEx3OUFYOXp1cFV4bzVKNEZadVNYYkNXUEt1a3VJbGtKYTRWMzAyeEtLNUJnT0R0TkdlQmNJQwpqNkFxZzUrU3dBVm9Va1FzcG52KzFBYVBOM0V1MldGNXlKaElaN0FnbjZERUYyWGlUQ3UvNm5lZVFLWC85QXVpCnNyTEZ2eE9TMEZuUTZ5YnpURGordHdTSGM4TkpHbWhKaGVOTVg5MmlYbHkrWG5VSmdRYU1tQzg5Y3JaRGRXczQKTnoyY0hMZFNZNnFNaHlSZGJ6NHZqdzlnVllMYXN5WjVFSTh2K1FmRTNOVE5SdlVJdlNwTVNQN09DT09UbTlteAprSlRVYjdCeW9DV0tzUDBGeWQ5RkdSVnZRQ0xFZi85MVNOeU5Sdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: azure-cred
+ namespace: demo
+type: kubevault.com/azure
+data:
+ msiToken: ZXlKMGVYQWlPaUcFpDSTZJa2hDQ0o5LmV5SmhkV1FpT2lKpPaTh2YzNSekxuZHBibVJ2ZDNNdWJtVjBM
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/gcp-iam.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/gcp-iam.md
new file mode 100644
index 000000000..fb3637a7e
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/gcp-iam.md
@@ -0,0 +1,81 @@
+---
+title: Connect to Vault using GCP IAM Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: gcp-iam-auth-methods
+ name: GCP IAM
+ parent: auth-methods-vault-server-crds
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using GCP IAM Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. For [GCP IAM authentication](https://www.vaultproject.io/docs/auth/gcp.html#configuration), it has to be enabled and configured in the Vault server. Follow the steps below to create an appropriate AppBinding:
+
+- You have to specify `spec.secret` in the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding).
+
+- The specified secret must be in AppBinding's namespace.
+
+- The type of the specified secret must be `"kubevault.com/gcp"`.
+
+- The specified secret data can have the following key:
+ - `Secret.Data["sa.json"]` : `Required`. Specifies the google application credentials.
+
+- The additional information required for the GCP IAM authentication method can be provided as AppBinding's `spec.parameters`.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-gcp
+ vaultRole: demo-role
+ ```
+
+ - `path` : `optional`. Specifies the path where GCP auth is enabled in Vault. If this path is not provided, the path will be set by default path `gcp`.
+ - `vaultRole` : `required`. Specifies the name of the Vault auth [role](https://www.vaultproject.io/api/auth/gcp/index.html#create-role) against which login will be performed.
+
+Sample AppBinding and Secret is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: gcp-cred
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-gcp
+ vaultRole: demo-role
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9UQTBNVGN3TkRFM05UVmFGdzB5T1RBME1UUXdOREUzTlRWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNGxKeTNsMThKMjZ2WWlZakNYZm54M1dvCnpaNUh4WUUvWmVNT1BKTFZyN0kwb2Rrc3N6bXhieWROaGJaN2kvQ2xOUzRvclB1eVFJZ29Ncng1bHRvTDhEd1cKRmZQZ0RGbFM4WjArcHNwRU00WEtVYnpBQk9lY0JaUnhZYTJPdmJqeFZjTE1PYzI5VGw4TzYzc2ZFeTlDcWhrRApEaUZDeFQ2bFd1MjZ0YmNzZEwwNFdBVzZDN1pyakhtaUMvWHhGcnl6STllRUVhb0xkVTdHMDJhTmFmOVBZM0RaCjBNRTJtOUNXMDYzOFZMeCtZMjR3cXMrQVJrUmg3cUVVKy9qK2lId2Y5N0hKMi8vcGdNMEFRcklOSk1kQ1ZNZEsKZ2hGYUs4NjZBdDNsa1R0U0FOclVtM3pCN1lEN20rYjNTRlJ5clMzM2RDZG5zNlp3NDdTQjFjWEJxcCs1SFFJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeUZTR1drSkV3U25nTW5zQXJ3c2xYckIyQm1NNHdNdzJtSkwyWk9CSDVlWm9ka0QKVmpsS1ltSVlKRE9rS2pIR2JuQys3KzVJd1J0ais4Um9uT0lSSnp3Vy9PZnUyUFJML1JmQmxmVmwxKzJJZlNWVQprbEVsRnlHNHRQL202ZjhWU2U5ZEpSZkFOWGRkcGdlOUd3dFlTbGsyaGI1aE5RTzVFSTAyVVYwdVVpWGcwNWRECkgyYkppQ1FQcHBxc3NiL09yNWQ5YXBSV3FMMzliQ0Z5Zi9GTzhZVVNYL0NEM1ZlZzhic24yWWc2bU14b2tUTGIKM1EvWll0NGthS0t0UVNreDV3NXh6bmZGNVBHenRIVmtSMkc0SVNRdDBVK2t1TVpRZTEyVCszS2ZqVitSVkZkZApWRkFpekxPOC82ZEFvRk5mQ3M4c2xsUDVEYXRLWnNXT2hROFJMZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: gcp-cred
+ namespace: demo
+type: kubevault.com/gcp
+data:
+ sa.json: ZXlKMGVYQWlPaUcFpDSTZJa2hDQ0o5LmV5SmhkV1FpT2lKpPaTh2YzNSekxuZHBibVJ2ZDNNdWJtVjBM
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/jwt-oidc.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/jwt-oidc.md
new file mode 100644
index 000000000..8df11c7b7
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/jwt-oidc.md
@@ -0,0 +1,97 @@
+---
+title: Connect to Vault using JWT/OIDC Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: jwt-oidc-auth-methods
+ name: JWT/OIDC
+ parent: auth-methods-vault-server-crds
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+The `JWT` auth method can be used to authenticate with Vault using `OIDC` or by providing a `JWT`.
+
+The `OIDC` method allows authentication via a configured `OIDC Provider` using the user's web browser. This method may be initiated from the `Vault UI` or the command line. Alternatively, a `JWT` can be provided directly.
+
+## Enable & Configure JWT/OIDC Auth method
+
+While deploying the `VaultServer` it's possible to define the list of auth methods users want to enable with it.
+
+A `VaultServer` `.spec.authMethods` section may look like this:
+
+```yaml
+spec:
+ authMethods:
+ - type: jwt
+ path: jwt
+ jwtConfig:
+ ...
+ - type: oidc
+ path: oidc
+ oidcConfig:
+ ...
+
+```
+
+* `.spec.authMethods.type` is a required field, the type of authentication method we want to enable.
+* `.spec.authMethods.path` is a required field, the path where we want to enable this authentication method.
+* `.spec.authMethods.jwtConfig / .spec.authMethods.oidcConfig` contains various configuration for this authentication method. Some of the `paramerters` are listed here:
+ * `defaultLeaseTTL` - The default lease duration, specified as a string duration like "5s" or "30m".
+ * `maxLeaseTTL` - The maximum lease duration, specified as a string duration like "5s" or "30m".
+ * `pluginName` - The name of the plugin in the plugin catalog to use.
+ * `auditNonHMACRequestKeys` - List of keys that will not be HMAC'd by audit devices in the request data object.
+ * `auditNonHMACResponseKeys` - List of keys that will not be HMAC'd by audit devices in the response data object.
+ * `listingVisibility` - Specifies whether to show this mount in the UI-specific listing endpoint.
+ * `passthroughRequestHeaders` - List of headers to whitelist and pass from the request to the backend.
+ * `credentialSecretRef` - K8s Secret reference containing credential related secrets.
+ * `tlsSecretRef` - K8s Secret reference containing tls related secrets.
+ * `oidcDiscoveryURL` - The OIDC Discovery URL, without any .well-known component (base path). Cannot be used with "jwks_url" or "jwt_validation_pubkeys".
+ * `oidcClientID` - The OAuth Client ID from the provider for OIDC roles.
+ * `oidcResponseMode` - The response mode to be used in the OAuth2 request. Allowed values are "query" and "form_post". Defaults to "query". If using Vault namespaces, and oidc_response_mode is "form_post", then "namespace_in_state" should be set to false.
+ * `oidcResponseTypes` - (comma-separated string, or array of strings: ) - The response types to request. Allowed values are "code" and "id_token". Defaults to "code". Note: "id_token" may only be used if "oidc_response_mode" is set to "form_post".
+ * `defaultRole` - The default role to use if none is provided during login.
+ * `providerConfig` - Configuration options for provider-specific handling. Providers with specific handling include: Azure, Google. The options are described in each provider's section in OIDC Provider Setup.
+ * `jwksURL` - JWKS URL to use to authenticate signatures. Cannot be used with "oidc_discovery_url" or "jwt_validation_pubkeys".
+ * `jwtValidationPubkeys` - (comma-separated string, or array of strings: ). A list of PEM-encoded public keys to use to authenticate signatures locally. Cannot be used with "jwks_url" or "oidc_discovery_url".
+ * `jwtSupportedAlgs` - (comma-separated string, or array of strings: ) A list of supported signing algorithms. Defaults to [RS256] for OIDC roles. Defaults to all available algorithms for JWT roles.
+ * `boundIssuer` - The value against which to match the iss claim in a JWT.
+
+After an authentication method is successfully enabled, `KubeVault` operator will configure it with the provided configuration.
+
+After successfully enabling & configuring authentication methods, a VaultServer `.status.authMethodStatus` may look like this:
+```yaml
+status:
+ authMethodStatus:
+ - path: jwt
+ status: EnableSucceeded
+ type: jwt
+ - path: kubernetes
+ status: EnableSucceeded
+ type: kubernetes
+
+```
+
+We can verify it using the `Vault CLI`:
+
+```bash
+$ vault auth list
+
+Path Type Accessor Description
+---- ---- -------- -----------
+jwt/ jwt auth_jwt_ba23cc30 n/a
+kubernetes/ kubernetes auth_kubernetes_40fd86fd n/a
+token/ token auth_token_950c8b80 token based credentials
+```
+
+So, this is how `JWT/OIDC` authentication method could be enabled & configured with `KubeVault`.
+
+> For a step-by-step guide on JWT/OIDC authentication method, see [this](/docs/v2025.11.21/guides/vault-server/auth-method).
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/kubernetes.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/kubernetes.md
new file mode 100644
index 000000000..e2a0d6d3d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/kubernetes.md
@@ -0,0 +1,149 @@
+---
+title: Connect to Vault using Kubernetes Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: kubernetes-auth-methods
+ name: Kubernetes
+ parent: auth-methods-vault-server-crds
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using Kubernetes Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. For [Kubernetes Authentication](https://www.vaultproject.io/docs/auth/kubernetes.html), it has to be enabled and configured in the Vault server. In KubeVault operator, it can be performed in two ways:
+
+- Using ServiceAccount Name
+- Using ServiceAccount Token Secret
+
+## Kubernetes Authentication using ServiceAccount Name
+
+To perform Kubernetes Authentication using ServiceAccount Name,
+
+- You have to specify serviceaccount name and [role](https://www.vaultproject.io/api/auth/kubernetes/index.html#create-role) name in `spec.parameters` of the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding). If Kubernetes auth method is enabled in different path (not `kubernetes`), then you also have to specify it in `spec.parameters` of AppBinding.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: k8s # Kubernetes auth is enabled in this path
+ vaultRole: demo # role name against which login will be done
+ kubernetes:
+ serviceAccountName: vault-sa # service account name
+ ```
+
+- The specified ServiceAccount must be in AppBinding's namespace.
+
+Sample AppBinding is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: k8s
+ vaultRole: demo
+ kubernetes:
+ serviceAccountName: vault-sa
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+## Kubernetes Authentication using ServiceAccount Token Secret
+
+To perform Kubernetes Authentication using ServiceAccount Token Secret,
+
+- You have to specify serviceaccount token secret in `spec.secret` of the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding). Kubernetes create a token secret for every serviceaccount. You can use that in `spec.secret`.
+
+ ```bash
+ $ kubectl create serviceaccount sa
+ serviceaccount/sa created
+
+ $ kubectl get serviceaccount/sa -o yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: sa
+ namespace: default
+ secrets:
+ - name: sa-token-6n9pv
+
+ $ kubectl get secrets/sa-token-6n9pv -o yaml
+ apiVersion: v1
+ data:
+ ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t
+ namespace: ZGVmYXVsdA==
+ token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlK
+ kind: Secret
+ metadata:
+ annotations:
+ kubernetes.io/service-account.name: sa
+ kubernetes.io/service-account.uid: db22a517-0771-11e9-8744-080027907e77
+ name: sa-token-6n9pv
+ namespace: default
+ type: kubernetes.io/service-account-token
+ ```
+
+- The specified secret must be in AppBinding's namespace.
+
+- The specified token secret must have the following key:
+ - `Secret.Data["token"]` : `Required`. Specifies the serviceaccount token.
+
+- The type of the specified token secret must be `kubernetes.io/service-account-token`.
+
+- The additional information required for the Kubernetes authentication method can be provided as AppBinding's `spec.parameters`.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: k8s
+ vaultRole: demo-role
+ ```
+
+ - `path` : `optional`. Specifies the path where Kubernetes auth is enabled in Vault. If this path is not provided, the path will be set by default path `kubernetes`.
+ - `vaultRole` : `required`. Specifies the name of the Vault auth [role](https://www.vaultproject.io/api/auth/kubernetes/index.html#create-role) against which login will be performed.
+
+Sample AppBinding is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: sa-token
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: k8s
+ vaultRole: demo-role
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/overview.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/overview.md
new file mode 100644
index 000000000..ac19177d1
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/overview.md
@@ -0,0 +1,34 @@
+---
+title: Managing Externally Provisioned Vault Servers
+menu:
+ docs_v2025.11.21:
+ identifier: overview-auth-methods
+ name: External Vault
+ parent: auth-methods-vault-server-crds
+ weight: 5
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Managing Externally Provisioned Vault Servers
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. These Vault servers can be running outside a Kubernetes cluster or running inside a Kubernetes cluster but provisioned using a Helm chart.
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. Following authentication methods are currently supported by the KubeVault operator:
+
+- [AWS IAM Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/aws-iam)
+- [Kubernetes Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/kubernetes)
+- [TLS Certificates Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/tls)
+- [Token Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/token)
+- [Userpass Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/userpass)
+- [GCP IAM Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/gcp-iam)
+- [Azure Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/azure)
+- [JWT/OIDC Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/jwt-oidc)
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/tls.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/tls.md
new file mode 100644
index 000000000..52ebdbabf
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/tls.md
@@ -0,0 +1,83 @@
+---
+title: Connect to Vault using TLS Certificate Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: tls-auth-methods
+ name: TLS Certificates
+ parent: auth-methods-vault-server-crds
+ weight: 25
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using TLS Certificate Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. For [TLS Certificates authentication](https://www.vaultproject.io/docs/auth/cert.html), it has to be enabled and configured in Vault. Follow the steps below to create an appropriate AppBinding:
+
+- You have to specify `spec.secret` in the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding).
+
+- The specified secret must be in AppBinding's namespace.
+
+- The type of the specified secret must be `kubernetes.io/tls`.
+
+- The specified secret data must have the following key:
+ - `Secret.Data["tls.crt"]` : `Required`. Specifies the tls certificate.
+ - `Secret.Data["tls.key"]` : `Required`. Specifies the tls private key.
+
+- The additional information required for the TLS Certificate authentication method can be provided as AppBinding's `spec.parameters`.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-cert
+ vaultRole: demo-role
+ ```
+
+ - `path` : `optional`. Specifies the path where the TLS Certificate auth is enabled in Vault. If this path is not provided, the path will be set by default path `cert`.
+ - `vaultRole` : `required`. Specifies the name of the Vault auth [role](https://www.vaultproject.io/api/auth/cert/index.html#create-ca-certificate-role) against which login will be performed.
+
+Sample AppBinding and Secret is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: tls
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-cert
+ vaultRole: demo-role
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: tls
+ namespace: demo
+type: kubernetes.io/tls
+data:
+ tls.crt: cm9vdA==
+ tls.key: cm9vdA==
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/token.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/token.md
new file mode 100644
index 000000000..8ba7f9963
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/token.md
@@ -0,0 +1,62 @@
+---
+title: Connect to Vault using Token Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: token-auth-methods
+ name: Token
+ parent: auth-methods-vault-server-crds
+ weight: 30
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using Token Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. To use [Token Authentication](https://www.vaultproject.io/docs/auth/token.html#token-auth-method), follow the steps below to create an appropriate AppBinding:
+
+- You have to specify `spec.secret` in the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding).
+
+- The type of the specified secret must be `kubevault.com/token`.
+
+- The specified secret data must have the following key:
+ - `Secret.Data["token"]` : `Required`. Specifies the Vault authentication token.
+
+- The specified secret must be in AppBinding's namespace.
+
+Sample AppBinding and Secret is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: vault-token
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+```yaml
+apiVersion: v1
+data:
+ token: cm9vdA==
+kind: Secret
+metadata:
+ name: vault-token
+ namespace: demo
+type: kubevault.com/token
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/userpass.md b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/userpass.md
new file mode 100644
index 000000000..9c4cd6eb6
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/userpass.md
@@ -0,0 +1,80 @@
+---
+title: Connect to Vault using Userpass Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: userpass-auth-methods
+ name: Userpass
+ parent: auth-methods-vault-server-crds
+ weight: 35
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Connect to Vault using Userpass Auth Method
+
+The KubeVault operator uses an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to connect to an externally provisioned Vault server. For [Userpass authentication](https://www.vaultproject.io/docs/auth/userpass.html), it has to be enabled and configured in the Vault server. Follow the steps below to create an appropriate AppBinding:
+
+- You have to specify `spec.secret` in the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding).
+
+- The type of the specified secret must be `kubernetes.io/basic-auth`.
+
+- The specified secret data must have the following key:
+ - `Secret.Data["username"]` : `Required`. Specifies the username used for authentication.
+ - `Secret.Data["password"]` : `Required`. Specifies the password used for authentication.
+
+- The specified secret must be in AppBinding's namespace.
+
+- The additional information required for the Userpass authentication method can be provided as AppBinding's `spec.parameters`.
+
+ ```yaml
+ spec:
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-userpass
+ ```
+
+ - `path` : `optional`. Specifies the path where the Userpass auth is enabled in Vault. If this path is not provided, the path will be set by default path `userpass`.
+
+Sample AppBinding and Secret is given below:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: userpass-cred
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: my-userpass
+ clientConfig:
+ service:
+ name: vault
+ scheme: HTTPS
+ port: 8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: userpass-cred
+ namespace: demo
+type: kubernetes.io/basic-auth
+data:
+ username: cm9vdA==
+ password: cm9vdA==
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/_index.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/_index.md
new file mode 100755
index 000000000..a3fe6887e
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: storage-vault-server-crds
+ name: Storage
+ parent: vault-server-crds-concepts
+ weight: 25
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/azure.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/azure.md
new file mode 100644
index 000000000..128239632
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/azure.md
@@ -0,0 +1,101 @@
+---
+title: Azure | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: azure-storage
+ name: Azure
+ parent: storage-vault-server-crds
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Azure
+
+In Azure storage backend, Vault data will be stored in [Azure Storage Container](https://azure.microsoft.com/en-us/services/storage/). Vault documentation for azure storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/azure.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-azure
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ azure:
+ accountName: "vault-ac"
+ accountKeySecret: "azure-cred"
+ container: "my-vault-storage"
+```
+
+## spec.backend.azure
+
+To use Azure as backend storage in Vault specify `spec.backend.azure` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ azure:
+ accountName:
+ accountKeySecret:
+ container:
+ maxParallel:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.azure` field.
+
+### azure.accountName
+
+`azure.accountName` is a required field that specifies the Azure Storage account name.
+
+```yaml
+spec:
+ backend:
+ azure:
+ accountName: "my-vault-storage"
+```
+
+### azure.accountKeySecret
+
+`azure.accountKeySecret` is a required field that specifies the name of the secret containing Azure Storage account key. The secret contains the following key:
+
+- `account_key`
+
+```yaml
+spec:
+ backend:
+ azure:
+ accountKeySecret: "azure-storage-key"
+```
+
+### azure.container
+
+`azure.container` is a required field that specifies the Azure Storage Blob container name.
+
+```yaml
+spec:
+ backend:
+ azure:
+ container: "my-vault-storage"
+```
+
+### azure.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ azure:
+ maxParallel: 124
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/consul.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/consul.md
new file mode 100644
index 000000000..9f19544a7
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/consul.md
@@ -0,0 +1,322 @@
+---
+title: Consul | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: consul-storage
+ name: Consul
+ parent: storage-vault-server-crds
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Consul
+
+In the Consul storage backend, Vault data will be stored in the consul storage container. Vault documentation for Consul storage backend can be found in [here](https://www.vaultproject.io/docs/configuration/storage/consul.html)
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ backend:
+ consul:
+ address: "http://my-service.demo.svc:8500"
+ path: "vault"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+```
+
+If you need to disable the server from executing the `mlock` syscall, you can provide [disable_mlock](https://www.vaultproject.io/docs/configuration/#disable_mlock) in a ConfigMap and mention the name in `spec.configSource.configMap.name`.
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: extra-config
+ namespace: demo
+data:
+ vault.hcl: |
+ disable_mlock = true
+```
+
+To use Consul as a storage backend, first, we need to deploy Consul. Documentation for deploying Consul in Kubernetes can be found [here](https://www.consul.io/docs/k8s/installation/install). Below is an example yaml for deploying Consul suitable for demo purposes:
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: consul-example
+ namespace: demo
+ labels:
+ app: consul
+spec:
+ containers:
+ - name: example
+ image: "consul:latest"
+ restartPolicy: Never
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: my-service
+ namespace: demo
+spec:
+ selector:
+ app: consul
+ ports:
+ - protocol: TCP
+ port: 8500
+ type: NodePort
+```
+
+## spec.backend.consul
+
+To use Consul as backend storage in Vault, we need to specify `spec.backend.consul` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+More information about the Consul backend storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/consul.html)
+
+```yaml
+spec:
+ backend:
+ consul:
+ address:
+ checkTimeout:
+ consistencyMode:
+ disableRegistration:
+ maxParallel:
+ path:
+ scheme:
+ service:
+ serviceTags:
+ serviceAddress:
+ aclTokenSecretName:
+ sessionTTL:
+ lockWaitTime:
+ tlsSecretName:
+ tlsMinVersion:
+ tlsSkipVerify:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.consul` field.
+
+### consul.address
+
+Specifies the address of the Consul agent to communicate with. This can be an IP address, DNS record, or Unix socket. It is recommended that you communicate with a local Consul agent; do not communicate directly with a server.
+
+```yaml
+spec:
+ backend:
+ consul:
+ address: "127.0.0.1:8500"
+```
+
+### consul.checkTimeout
+
+Specifies the check interval used to send health check information back to Consul. This is specified using a label suffix like "30s" or "1h"
+
+```yaml
+spec:
+ backend:
+ consul:
+ checkTimeout: "5s"
+```
+
+### consul.consistencyMode
+
+Specifies the Consul consistency mode. Possible values are "default" or "strong".
+
+```yaml
+spec:
+ backend:
+ consul:
+ consistencyMode: "default"
+```
+
+### consul.disableRegistration
+
+Specifies whether Vault should register itself with Consul.
+
+```yaml
+spec:
+ backend:
+ consul:
+ disableRegistration: "false"
+```
+
+### consul.maxParallel
+
+Specifies the maximum number of concurrent requests to Consul.
+
+```yaml
+spec:
+ backend:
+ consul:
+ maxParallel: "128"
+```
+
+### consul.path
+
+Specifies the path in Consul's key-value store where Vault data will be stored.
+
+```yaml
+spec:
+ backend:
+ consul:
+ path: "vault"
+```
+
+### consul.scheme
+
+Specifies the scheme to use when communicating with Consul. This can be set to "http" or "https". It is highly recommended you communicate with Consul over https over non-local connections. When communicating over a Unix socket, this option is ignored.
+
+```yaml
+spec:
+ backend:
+ consul:
+ scheme: "http"
+```
+
+### consul.service
+
+Specifies the name of the service to register in Consul.
+
+```yaml
+spec:
+ backend:
+ consul:
+ service: "vault"
+```
+
+### consul.serviceTags
+
+Specifies a comma-separated list of tags to attach to the service registration in Consul.
+
+```yaml
+spec:
+ backend:
+ consul:
+ serviceTags: ""
+```
+
+### consul.serviceAddress
+
+Specifies a service-specific address to set on the service registration in Consul. If unset, Vault will use what it knows to be the HA redirect address - which is usually desirable. Setting this parameter to `""` will tell Consul to leverage the configuration of the node the service is registered on dynamically.
+
+```yaml
+spec:
+ backend:
+ consul:
+ serviceAddress: ""
+```
+
+### consul.aclTokenSecretName
+
+Specifies the secret name that contains ACL token with permission to read and write from the path in Consul's key-value store. ACL Token should be stored in `data["aclToken"]=`
+
+```yaml
+spec:
+ backend:
+ consul:
+ aclTokenSecretName: aclcred
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aclcred
+ namespace: demo
+data:
+ aclToken: |-
+ ZGF0YQ==
+```
+
+### consul.sessionTTL
+
+Specifies the minimum allowed session TTL. The consul server has a lower limit of 10s on the session TTL by default. The value of session_ttl here cannot be lesser than 10s unless the session_ttl_min on the consul server's configuration has a lesser value.
+
+```yaml
+spec:
+ backend:
+ consul:
+ sessionTTL: "15s"
+```
+
+### consul.lockWaitTime
+
+Specifies the wait time before a lock acquisition is made. This affects the minimum time it takes to cancel a lock acquisition.
+
+```yaml
+spec:
+ backend:
+ consul:
+ lockWaitTime: "15s"
+```
+
+### consul.tlsSecretName
+
+Specifies the secret name that contains tls_ca_file, tls_cert_file and tls_key_file for consul communication.
+
+```yaml
+spec:
+ backend:
+ consul:
+ tlsSecretName: tls
+```
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: tls
+ namespace: demo
+data:
+ ca.crt: eyJtc2ciOiJleGFtcGxlIn0=
+ client.crt: eyJtc2ciOiJleGFtcGxlIn0=
+ client.key: eyJtc2ciOiJleGFtcGxlIn0=
+```
+
+### consul.tlsMinVersion
+
+Specifies the minimum TLS version to use. Accepted values are "tls10", "tls11" or "tls12".
+
+```yaml
+spec:
+ backend:
+ consul:
+ tlsMinVersion: "tls12"
+```
+
+### consul.tlsSkipVerify
+
+Disable verification of TLS certificates. Using this option is highly discouraged. It is a `boolean` type variable.
+
+```yaml
+spec:
+ backend:
+ consul:
+ tlsSkipVerify: false
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/dynamodb.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/dynamodb.md
new file mode 100644
index 000000000..f7944f98d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/dynamodb.md
@@ -0,0 +1,167 @@
+---
+title: Dynamodb | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: dynamodb-storage
+ name: Dynamodb
+ parent: storage-vault-server-crds
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# DynamoDB
+
+In DynamoDB storage backend, Vault data will be stored in [DynamoDB](https://aws.amazon.com/dynamodb/). Vault documentation for DynamoDB storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/dynamodb.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-dynamodb
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ dynamodb:
+ table: "my-vault-table"
+ region: "us-west-1"
+ readCapacity: 5
+ writeCapacity: 5
+```
+
+## spec.backend.dynamodb
+
+To use dynamoDB as backend storage in Vault specify `spec.backend.dynamodb` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ table:
+ region:
+ endpoint:
+ haEnabled:
+ readCapacity:
+ writeCapacity:
+ credentialSecret:
+ sessionTokenSecret:
+ maxParallel:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.dynamodb` field.
+
+### dynamodb.table
+
+`dynamodb.table` is a required field that specifies the name of the DynamoDB table. If the specified table does not exist, then Vault will create it during initialization. If it is not initialized, then Vault will set value to `vault-dynamodb-backend`.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ table: "my-vault-table"
+```
+
+### dynamodb.endpoint
+
+`dynamodb.endpoint` is an optional field that specifies an alternative, AWS compatible, DynamoDB endpoint.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ endpoint: "endpoint.com"
+```
+
+### dynamodb.region
+
+`dynamodb.region` is an optional field that specifies the AWS region. If this field is not specified, then Vault will set value to `us-east-1`.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ region: "us-east-1"
+```
+
+### dynamodb.credentialSecret
+
+`dynamodb.credentialSecret` is an optional field that specifies the secret name containing AWS access key and AWS secret key. The secret contains the following keys:
+
+- `access_key`
+- `secret_key`
+
+Leaving the `access_key` and `secret_key` fields empty will cause Vault to attempt to retrieve credentials from the AWS metadata service.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ credentialSecret: "aws-credential"
+```
+
+### dynamodb.sessionTokenSecret
+
+`dynamodb.sessionTokenSecret` is an optional field that specifies the secret name containing the AWS session token. The secret contains the following key:
+
+- `session_token`
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ sessionTokenSecret: "aws-session-token"
+```
+
+### dynamodb.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ maxParallel: 124
+```
+
+### dynamodb.readCapacity
+
+`dynamodb.readCapacity` is an optional field that specifies the maximum number of reads consumed per second on the table. If it is not specified, then Vault will set value to `5`.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ readCapacity: 10
+```
+
+### dynamodb.writeCapacity
+
+`dynamodb.writeCapacity` is an optional field that specifies the maximum number of writes performed per second on the table. If it is not specified, then Vault will set value to `5`.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ writeCapacity: 10
+```
+
+### dynamodb.haEnabled
+
+`dynamodb.haEnabled` is an optional field that specifies whether this backend should be used to run Vault in high availability mode. This field accepts boolean value. The default value is `false`.
+
+```yaml
+spec:
+ backend:
+ dynamodb:
+ haEnabled: true
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/etcd.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/etcd.md
new file mode 100644
index 000000000..6557a0f99
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/etcd.md
@@ -0,0 +1,140 @@
+---
+title: Etcd | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: etcd-storage
+ name: Etcd
+ parent: storage-vault-server-crds
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Etcd
+
+In Etcd storage backend, Vault data will be stored in [Etcd](https://etcd.io/). Vault documentation for Etcd storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/etcd.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-etcd
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ etcd:
+ address: "http://example.etcd.svc:2379"
+ etcdApi: "v3"
+```
+
+## spec.backend.etcd
+
+To use Etcd as storage backend in Vault specify `spec.backend.etcd` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ etcd:
+ address: "http://example.etcd.svc:2379"
+ etcdApi: "v3"
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.etcd` field.
+
+### etcd.address
+
+`etcd.address` is a required field that specifies the addresses of the etcd instances.
+
+```yaml
+spec:
+ backend:
+ etcd:
+ address: "http://example.etcd.svc:2379"
+```
+
+### etcd.haEnable
+
+`etcd.haEnable` is an optional field that specifies if high availability should be enabled. This field accepts boolean value. The default value is `false`.
+
+```yaml
+spec:
+ backend:
+ etcd:
+ haEnable: true
+```
+
+### etcd.etcdApi
+
+`etcd.etcdApi` is an optional field that specifies the version of the API to communicate with etcd. If this field is not specified, then Vault will derive it automatically. If the cluster version is 3.1+ and there has been no data written using the v2 API, the auto-detected default is v3.
+
+```yaml
+spec:
+ backend:
+ etcd:
+ etcdApi: "v3"
+```
+
+### etcd.path
+
+`etcd.path` is an optional field that specifies the path in etcd where Vault data will be stored. If this field is not specified, then Vault will set default value `/vault/`.
+
+```yaml
+spec:
+ backend:
+ etcd:
+ path: "/data/"
+```
+
+### etcd.sync
+
+`etcd.sync` is an optional field that specifies whether to sync a list of available etcd services on startup. This field accepts boolean value. The default value is `false`.
+
+```yaml
+spec:
+ backend:
+ etcd:
+ sync: true
+```
+
+### etcd.discoverySrv
+
+`etcd.discoverySrv` is an optional field that specifies the domain name to query for SRV records describing cluster endpoints. If this field is not specified, then Vault will set default value `example.com`
+
+```yaml
+spec:
+ backend:
+ etcd:
+ discoverySrv: "example.com"
+```
+
+### etcd.credentialSecretName
+
+`etcd.credentialSecretName` is an optional field that specifies the secret name that contains username and password to use when authenticating with the etcd server. The secret contains the following keys:
+
+- `username`
+- `password`
+
+```yaml
+spec:
+ backend:
+ etcd:
+ credentialSecretName: "etcd-credential"
+```
+
+### etcd.tlsSecretName
+
+`etcd.tlsSecretName` is an optional field that specifies the secret name that contains TLS assets for etcd communication. The secret contains following keys:
+
+- `tls_ca_file`
+- `tls_cert_file`
+- `tls_key_file`
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/filesystem.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/filesystem.md
new file mode 100644
index 000000000..6db155aca
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/filesystem.md
@@ -0,0 +1,144 @@
+---
+title: Filesystem | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: filesystem-storage
+ name: Filesystem
+ parent: storage-vault-server-crds
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Filesystem
+
+The [Filesystem storage backend](https://www.vaultproject.io/docs/configuration/storage/filesystem.html) stores Vault data on the filesystem using a standard directory structure. As the Filesystem backend does not support high availability (HA), it can be used for **single node** setups(i.e. vaultserver.spec.replicas: 1). A `VolumeClaimTemplate` can be specified to create (or reuse if already exist) a [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) so that Vault data can be stored in the corresponding [PersistentVolume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.3"
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ backend:
+ file:
+ path: /mnt/vault/data
+ volumeClaimTemplate:
+ metadata:
+ name: vault-pvc
+ spec:
+ accessModes: ["ReadWriteOnce"]
+ resources:
+ requests:
+ storage: 50Mi
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+```
+
+## spec.backend.file
+
+To use file system as storage backend in Vault server, specify the `spec.backend.file` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ file:
+ path: /mnt/vault/data
+ volumeClaimTemplate:
+ metadata:
+ name: vault-pvc
+ spec:
+ accessModes: ["ReadWriteOnce"]
+ resources:
+ requests:
+ storage: 50Mi
+```
+
+Here, we are going to describe various attributes of the `spec.backend.file` field.
+
+### file.path
+
+`file.path` is a `required` field that specifies the absolute path to the directory where the data will be stored.
+
+```yaml
+backend:
+ file:
+ path: /mnt/vault/data
+```
+
+### file.volumeClaimTemplate
+
+`file.volumeClaimTemplate` is a `required` field that specifies a [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) object that will provide storage for Vault server. The KubeVault operator will use the PVC if it already exists, otherwise, it will create a new PVC. On the deletion of VaultServer CRD, the PVC will be left intact. To clean up, you must delete the PVC manually.
+
+```yaml
+file:
+ volumeClaimTemplate:
+ metadata:
+ name: vault-pvc
+ spec:
+ accessModes: ["ReadWriteOnce"]
+ resources:
+ requests:
+ storage: 50Mi
+```
+
+#### file.volumeClaimTemplate.metadata
+
+`volumeClaimTemplate.metadata` is an `optional` field that specifies a standard object's metadata. The following fields can be provided:
+
+- `name` : `optional`. Specifies a name that uniquely identifies this object within the current namespace. Default to the name of VaultServer.
+- `labels` : `optional`. Specifies a map of string keys and values that can be used to organize and categorize objects. Default to the labels of the VaultServer.
+
+```yaml
+volumeClaimTemplate:
+ metadata:
+ name: vault-pvc
+ labels:
+ app: vault
+```
+
+#### file.volumeClaimTemplate.spec
+
+`volumeClaimTemplate.spec` is a `required` field that defines the desired characteristics of a volume. It contains all fields and features of a standard [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) object's spec.
+
+Sub-fields are given below:
+
+- `accessModes`
+- `selector`
+- `resources`
+- `volumeName`
+- `storageClassName`
+- `volumeMode`
+- `dataSource`
+
+```yaml
+file:
+ volumeClaimTemplate:
+ spec:
+ accessModes: ["ReadWriteOnce"]
+ resources:
+ requests:
+ storage: 50Mi
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/gcs.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/gcs.md
new file mode 100644
index 000000000..d090ca2a3
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/gcs.md
@@ -0,0 +1,112 @@
+---
+title: GCS | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: gcs-storage
+ name: GCS
+ parent: storage-vault-server-crds
+ weight: 25
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Google Cloud Storage (GCS)
+
+In Google Cloud Storage (GCS) storage backend, Vault data will be stored in [Google Cloud Storage](https://cloud.google.com/storage/docs/). Vault documentation for GCS storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/google-cloud-storage.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-gcs
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ gcs:
+ bucket: "my-vault-storage"
+ credentialSecret: "my-gcs-credential"
+```
+
+## spec.backend.gcs
+
+To use GCS as backend storage in Vault specify `spec.backend.gcs` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ gcs:
+ bucket:
+ chunkSize:
+ maxParallel:
+ haEnabled:
+ credentialSecret:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.gcs` field.
+
+### gcs.bucket
+
+`gcs.bucket` is a required field that specifies the name of the bucket to use for storage.
+
+```yaml
+spec:
+ backend:
+ gcs:
+ bucket: "my-vault-storage"
+```
+
+### gcs.chunkSize
+
+`gcs.chunkSize` is an optional field that specifies the maximum size (in kilobytes) to send in a single request. If this field is not specified, then Vault will set value to `8192`. If this filed is set to 0, Vault will attempt to send the whole object at once, but will not retry any failures.
+
+```yaml
+spec:
+ backend:
+ gcs:
+ chunkSize: "1024"
+```
+
+### gcs.credentialSecret
+
+`gcs.credentialSecret` is a required field that specifies the name of the secret containing Google application credential. The secret contains the following key:
+
+- `sa.json`
+
+```yaml
+spec:
+ backend:
+ gcs:
+ credentialSecret: "google-application-credential"
+```
+
+### gcs.haEnabled
+
+`gcs.haEnabled` is an optional field that specifies if high availability mode is enabled. This field accepts boolean value. The default value is `false`.
+
+```yaml
+spec:
+ backend:
+ gcs:
+ haEnabled: true
+```
+
+### gcs.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ gcs:
+ maxParallel: 124
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/inmem.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/inmem.md
new file mode 100644
index 000000000..841909b2b
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/inmem.md
@@ -0,0 +1,46 @@
+---
+title: In Memory | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: inmem-storage
+ name: In Memory
+ parent: storage-vault-server-crds
+ weight: 30
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# In-Memory
+
+In `In-Memory` backend storage, Vault data will be kept in memory. If the Kubernetes pod on which Vault is running is restarted, then all data will be lost. This is useful for development and experimentation, but the use of this backend is highly discouraged in production. Vault documentation for In-Memory storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/in-memory.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-inmem
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ inmem: {}
+```
+
+## spec.backend.inmem
+
+To use In-Memory as storage backend in Vault specify `spec.backend.inmem` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ inmem: {}
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/mysql.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/mysql.md
new file mode 100644
index 000000000..6641eecae
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/mysql.md
@@ -0,0 +1,127 @@
+---
+title: MySQL | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: mysql-storage
+ name: MySQL
+ parent: storage-vault-server-crds
+ weight: 35
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# MySQL
+
+In MySQL storage backend, Vault data will be stored in MySQL. Vault documentation for MySQL storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/mysql.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-mysql
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ mysql:
+ address: "my.mysql.com:3306"
+ userCredentialSecret: "mysql-cred"
+```
+
+## spec.backend.mysql
+
+To use MySQL as backend storage in Vault, specify `spec.backend.mysql` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ mysql:
+ address:
+ database:
+ table:
+ userCredentialSecret:
+ tlsCASecret:
+ maxParallel:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.mysql` field.
+
+### mysql.address
+
+`mysql.address` is a required field that specifies the address of the MySQL host.
+
+```yaml
+spec:
+ backend:
+ mysql:
+ address: "my.mysql.com:3306"
+```
+
+### mysql.userCredentialSecret
+
+`mysql.userCredentialSecret` is a required field that specifies the name of the secret containing MySQL username and password to connect with the database. The secret contains the following fields:
+
+- `username`
+- `password`
+
+```yaml
+spec:
+ backend:
+ mysql:
+ userCredentialSecret: "mysql-cred"
+```
+
+### mysql.database
+
+`mysql.database` is an optional field that specifies the name of the database. If the database does not exist, Vault will attempt to create it. If it is not specified, then Vault will set vault `vault`.
+
+```yaml
+spec:
+ backend:
+ mysql:
+ database: "my_vault"
+```
+
+### mysql.table
+
+`mysql.table` is an optional field that specifies the name of the table. If the table does not exist, Vault will attempt to create it. If it is not specified, then Vault will set value to `vault`.
+
+```yaml
+spec:
+ backend:
+ mysql:
+ table: "vault_data"
+```
+
+### mysql.tlsCASecret
+
+`mysql.tlsCASecret` is an optional field that specifies the name of the secret containing the CA certificate to connect using TLS. The secret contains the following fields:
+
+- `tls_ca_file`
+
+```yaml
+spec:
+ backend:
+ mysql:
+ tlsCASecret: "mysql-ca"
+```
+
+### mysql.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ mysql:
+ maxParallel: 124
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/overview.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/overview.md
new file mode 100644
index 000000000..02c4183b9
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/overview.md
@@ -0,0 +1,47 @@
+---
+title: Overview
+menu:
+ docs_v2025.11.21:
+ identifier: storage-overview
+ name: Overview
+ parent: storage-vault-server-crds
+ weight: 1
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Storage Backend
+
+## Configuring Storage Backend
+
+```yaml
+spec:
+ backend:
+ :
+ ...
+```
+
+Here, we are going to describe the various attributes of the `spec.backend` field.
+
+List of supported modes:
+
+- [Azure](/docs/v2025.11.21/concepts/vault-server-crds/storage/azure)
+- [Consul](/docs/v2025.11.21/concepts/vault-server-crds/storage/consul)
+- [DynamoDB](/docs/v2025.11.21/concepts/vault-server-crds/storage/dynamodb)
+- [Etcd](/docs/v2025.11.21/concepts/vault-server-crds/storage/etcd)
+- [Filesystem](/docs/v2025.11.21/concepts/vault-server-crds/storage/filesystem)
+- [GCS](/docs/v2025.11.21/concepts/vault-server-crds/storage/gcs)
+- [Inmem](/docs/v2025.11.21/concepts/vault-server-crds/storage/inmem)
+- [MySQL](/docs/v2025.11.21/concepts/vault-server-crds/storage/mysql)
+- [PostgreSQL](/docs/v2025.11.21/concepts/vault-server-crds/storage/postgresql)
+- [Raft](/docs/v2025.11.21/concepts/vault-server-crds/storage/raft)
+- [S3](/docs/v2025.11.21/concepts/vault-server-crds/storage/s3)
+- [Swift](/docs/v2025.11.21/concepts/vault-server-crds/storage/swift)
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/postgresql.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/postgresql.md
new file mode 100644
index 000000000..7533ce7c0
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/postgresql.md
@@ -0,0 +1,87 @@
+---
+title: PostgreSQL | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: postgresql-storage
+ name: PostgreSQL
+ parent: storage-vault-server-crds
+ weight: 40
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# PostgreSQL
+
+In PostgreSQL storage backend, Vault data will be stored in [PostgreSQL](https://www.postgresql.org/). Vault documentation for PostgreSQL storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/postgresql.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-postgresql
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ postgresql:
+ connectionURLSecret: "my-postgres-conn"
+```
+
+## spec.backend.postgresql
+
+To use PostgreSQL as backend storage in Vault specify `spec.backend.postgresql` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ postgresql:
+ connectionURLSecret:
+ table:
+ maxParallel:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.postgresql` field.
+
+### postgresql.connectionURLSecret
+
+`postgresql.connectionURLSecret` is a required field that specifies the name of the secret containing the connection string to use to authenticate and connect to PostgreSQL. The secret contains the following key:
+
+- `connection_url`
+
+```yaml
+spec:
+ backend:
+ postgresql:
+ connectionURLSecret: "my-postgres-conn"
+```
+
+### postgresql.table
+
+`postgresql.table` is an optional field that specifies the name of the table in which to write Vault data. If it is not specified, then Vault will set the value `vault_kv_store`. Vault will not create the table, so this table must exist in the database.
+
+```yaml
+spec:
+ backend:
+ postgresql:
+ table: "vault_data"
+```
+
+### postgresql.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ postgresql:
+ maxParallel: 124
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/raft.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/raft.md
new file mode 100644
index 000000000..3103e8f2d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/raft.md
@@ -0,0 +1,145 @@
+---
+title: Raft | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: raft-storage
+ name: Raft
+ parent: storage-vault-server-crds
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Raft
+
+In the `Raft` storage backend, vault data will be stored in provided file system path. Vault documentation for `Raft` storage backend can be found in [here](https://www.vaultproject.io/docs/configuration/storage/raft.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: default
+spec:
+ replicas: 3
+ version: 1.7.3
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: WipeOut
+
+```
+
+## spec.backend.raft
+
+To use `Raft` as backend storage in Vault, we need to specify `spec.backend.raft` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+More information about the `Raft` backend storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/raft.html)
+
+```yaml
+spec:
+ backend:
+ raft:
+ path:
+ performanceMultiplier:
+ trailingLogs:
+ snapshotThreshold:
+ maxEntrySize:
+ autoPilotReconcileInterval:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.raft` field.
+
+### raft.path
+
+`Path` specifies the filesystem path where the vault data gets stored. This value can be overridden by setting the `VAULT_RAFT_PATH` environment variable. `default: ""`
+
+```yaml
+spec:
+ backend:
+ raft:
+ path: "/vault/data"
+```
+
+### raft.performanceMultiplier
+
+An integer multiplier used by servers to scale key Raft timing parameters. Tuning this affects the time it takes Vault to detect leader failures and to perform leader elections, at the expense of requiring more network and CPU resources for better performance. `default: 0`
+```yaml
+spec:
+ backend:
+ raft:
+ performanceMultiplier: 0
+```
+
+### raft.trailingLogs
+
+This controls how many log entries are left in the log store on disk after a snapshot is made. `default: 10000`
+```yaml
+spec:
+ backend:
+ raft:
+ trailingLogs: 10000
+```
+
+### raft.snapshotThreshold
+
+This controls the minimum number of raft commit entries between snapshots that are saved to disk. `default: 8192`
+```yaml
+spec:
+ backend:
+ raft:
+ snapshotThreshold: 8192
+```
+
+### raft.maxEntrySize
+
+This configures the maximum number of bytes for a raft entry. It applies to both Put operations and transactions. `default: 1048576`
+```yaml
+spec:
+ backend:
+ raft:
+ maxEntrySize: 1048576
+```
+
+### raft.autoPilotReconcileInterval
+
+This is the interval after which autopilot will pick up any state changes. `default: ""`
+```yaml
+spec:
+ backend:
+ raft:
+ autoPilotReconcileInterval: ""
+```
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/s3.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/s3.md
new file mode 100644
index 000000000..2ef9afe6c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/s3.md
@@ -0,0 +1,154 @@
+---
+title: AWS S3 | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: s3-storage
+ name: AWS S3
+ parent: storage-vault-server-crds
+ weight: 45
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# AWS S3
+
+In S3 storage backend, Vault data will be stored in [AWS S3](https://aws.amazon.com/s3/) bucket. Vault documentation for S3 storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/s3.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-s3
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ s3:
+ bucket: "my-vault-bucket"
+ region: "us-west-1"
+ credentialSecret: "aws-credential"
+```
+
+## spec.backend.s3
+
+To use S3 as backend storage in Vault specify `spec.backend.s3` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ s3:
+ bucket:
+ endpoint:
+ region:
+ credentialSecret:
+ sessionTokenSecret:
+ maxParallel:
+ forcePathStyle:
+ disableSSL:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.s3` field.
+
+### s3.bucket
+
+`s3.bucket` is a required field that specifies the name of the bucket to use for storage.
+
+```yaml
+spec:
+ backend:
+ s3:
+ bucket: "my-vault-storage"
+```
+
+### s3.endpoint
+
+`s3.endpoint` is an optional field that specifies an alternative, AWS compatible, S3 endpoint.
+
+```yaml
+spec:
+ backend:
+ s3:
+ endpoint: "endpoint.com"
+```
+
+### s3.region
+
+`s3.region` is an optional field that specifies the AWS region. If this field is not specified, then Vault will set value to `us-east-1`.
+
+```yaml
+spec:
+ backend:
+ s3:
+ region: "us-east-1"
+```
+
+### s3.credentialSecret
+
+`s3.credentialSecret` is an optional field that specifies the secret name containing AWS access key and AWS secret key. The secret contains the following keys:
+
+- `access_key`
+- `secret_key`
+
+Leaving the `access_key` and `secret_key` fields empty will cause Vault to attempt to retrieve credentials from the AWS metadata service.
+
+```yaml
+spec:
+ backend:
+ s3:
+ credentialSecret: "aws-credential"
+```
+
+### s3.sessionTokenSecret
+
+`s3.sessionTokenSecret` is an optional field that specifies the secret name containing the AWS session token. The secret contains the following key:
+
+- `session_token`
+
+```yaml
+spec:
+ backend:
+ s3:
+ sessionTokenSecret: "aws-session-token"
+```
+
+### s3.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ s3:
+ maxParallel: 124
+```
+
+### s3.forcePathStyle
+
+`s3.forcePathStyle` is an optional field that specifies whether to use host bucket-style domains with the configured endpoint. This field accepts boolean value. The default value is `false`.
+
+```yaml
+spec:
+ backend:
+ s3:
+ forcePathStyle: true
+```
+
+### s3.disableSSL
+
+`s3.disableSSL` is an optional field that specifies if SSL should be used for the endpoint connection. This field accepts boolean value. The default value is `false`.
+
+```yaml
+spec:
+ backend:
+ s3:
+ disableSSL: true
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/storage/swift.md b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/swift.md
new file mode 100644
index 000000000..a810a9e06
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/storage/swift.md
@@ -0,0 +1,198 @@
+---
+title: OpenStack Swift | Vault Server Storage
+menu:
+ docs_v2025.11.21:
+ identifier: swift-storage
+ name: OpenStack Swift
+ parent: storage-vault-server-crds
+ weight: 50
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Swift
+
+In Swift storage backend, Vault data will be stored in [OpenStack Swift Container](http://docs.openstack.org/developer/swift/). Vault documentation for Swift storage can be found in [here](https://www.vaultproject.io/docs/configuration/storage/swift.html).
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault-with-swift
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ swift:
+ authURL: "https://auth.cloud.ovh.net/v2.0/"
+ container: "my-vault-container"
+ credentialSecret: "os-credential"
+ region: "BHS1"
+ tenant: "123456789999"
+```
+
+## spec.backend.swift
+
+To use Swift as backend storage in Vault specify `spec.backend.swift` in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD.
+
+```yaml
+spec:
+ backend:
+ swift:
+ authURL:
+ container:
+ credentialSecret:
+ region:
+ tenant:
+ tenantID:
+ domain:
+ projectDomain:
+ storageURL:
+ authTokenSecret:
+```
+
+Here, we are going to describe the various attributes of the `spec.backend.swift` field.
+
+### swift.authURL
+
+`swift.authURL` is a required field that specifies the OpenStack authentication endpoint.
+
+```yaml
+spec:
+ backend:
+ swift:
+ authURL: "https://auth.cloud.ovh.net/v2.0/"
+```
+
+### swift.container
+
+`swift.container` is a required field that specifies the name of the Swift container.
+
+```yaml
+spec:
+ backend:
+ swift:
+ container: "my-vault-container"
+```
+
+### swift.credentialSecret
+
+`swift.credentialSecret` is a required field that specifies the name of the secret containing the OpenStack account/username and password. The secret contains the following keys:
+
+- `username`
+- `password`
+
+```yaml
+spec:
+ backend:
+ swift:
+ credentialSecret: "os-credential"
+```
+
+### swift.tenant
+
+`swift.tenant` is an optional field that specifies the name of the tenant. If it is not specified, then Vault will set the value to the default tenant of the username.
+
+```yaml
+spec:
+ backend:
+ swift:
+ tenant: "123456789"
+```
+
+### swift.region
+
+`swift.region` is an optional field that specifies the name of the region.
+
+```yaml
+spec:
+ backend:
+ swift:
+ region: "BHS1"
+```
+
+### swift.tenantID
+
+`swift.tenantID` is an optional field that specifies the id of the tenant.
+
+```yaml
+spec:
+ backend:
+ swift:
+ tenantID: "11111111"
+```
+
+### swift.domain
+
+`swift.domain` is an optional field that specifies the name of the user domain.
+
+```yaml
+spec:
+ backend:
+ swift:
+ domain: "my-domain"
+```
+
+### swift.projectDomain
+
+`swift.domain` is an optional field that specifies the name of the project's domain.
+
+```yaml
+spec:
+ backend:
+ swift:
+ projectDomain: "my-project-domain"
+```
+
+### swift.trustID
+
+`swift.trustID` is an optional field that specifies the id of the trust.
+
+```yaml
+spec:
+ backend:
+ swift:
+ trustID: "trust-id"
+```
+
+### swift.storageURL
+
+`swift.storageURL` is an optional field that specifies the storage URL from alternate authentication.
+
+```yaml
+spec:
+ backend:
+ swift:
+ storageURL: "storage.com"
+```
+
+### swift.authTokenSecret
+
+`swift.authTokenSecret` is an optional field that specifies the name of the secret containing auth token from alternate authentication.
+
+```yaml
+spec:
+ backend:
+ swift:
+ authTokenSecret: "auth-token-secret"
+```
+
+### swift.maxParallel
+
+`maxParallel` is an optional field that specifies the maximum number of parallel operations to take place. This field accepts integer value. If this field is not specified, then Vault will set value to `128`.
+
+```yaml
+spec:
+ backend:
+ swift:
+ maxParallel: 124
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/_index.md b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/_index.md
new file mode 100755
index 000000000..1a15f124d
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Unsealer
+menu:
+ docs_v2025.11.21:
+ identifier: unsealer-vault-server-crds
+ name: Unsealer
+ parent: vault-server-crds-concepts
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/aws_kms_ssm.md b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/aws_kms_ssm.md
new file mode 100644
index 000000000..56b38c1c5
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/aws_kms_ssm.md
@@ -0,0 +1,88 @@
+---
+title: AWS KMS | Vault Unsealer
+menu:
+ docs_v2025.11.21:
+ identifier: aws-kms-ssm-unsealer
+ name: Aws KMS
+ parent: unsealer-vault-server-crds
+ weight: 1
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# mode.awsKmsSsm
+
+To use **awsKmsSsm** mode specify `mode.awsKmsSsm`. In this mode, unseal keys and root token will be stored in [AWS System Manager Parameter store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html) and they will be encrypted using AWS encryption key.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ awsKmsSsm:
+ kmsKeyID:
+ region:
+ ssmKeyPrefix:
+ credentialSecret:
+ endpoint:
+```
+
+`mode.awsKmsSsm` has the following fields:
+
+## awsKmsSsm.kmsKeyID
+
+`awsKmsSsm.kmsKeyID` is a required field that specifies the ID or ARN of the AWS KMS key to encrypt values.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ awsKmsSsm:
+ kmsKeyID: "aaaaa-bbbb-cccc-ddd-eeeeeeee"
+```
+
+## awsKmsSsm.region
+
+`awsKmsSsm.region` is a required field that specifies the AWS region.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ awsKmsSsm:
+ region: "us-east-1"
+```
+
+## awsKmsSsm.ssmKeyPrefix
+
+`awsKmsSsm.ssmKeyPrefix` is an optional field that specifies the prefix for SSM parameters. If this is not specified, then Unsealer will store parameters at the root of SSM.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ awsKmsSsm:
+ ssmKeyPrefix: "/cluster/demo"
+```
+
+## awsKmsSsm.credentialSecret
+
+`awsKmsSsm.credentialSecret` is an optional field that specifies the name of the secret containing AWS access key and AWS secret key. If this is not specified, then Unsealer will attempt to retrieve credentials from the AWS metadata service. The secret contains the following data fields:
+
+- `access_key`
+- `secret_key`
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ awsKmsSsm:
+ credentialSecret: "aws-cred"
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/azure_key_vault.md b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/azure_key_vault.md
new file mode 100644
index 000000000..2f2afa2e2
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/azure_key_vault.md
@@ -0,0 +1,118 @@
+---
+title: Azure Key Vault | Vault Unsealer
+menu:
+ docs_v2025.11.21:
+ identifier: azure-key-vault-unsealer
+ name: Azure Key Vault
+ parent: unsealer-vault-server-crds
+ weight: 1
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# mode.azureKeyVault
+
+To use **azureKeyVault** mode specify `mode.azureKeyVault`. In this mode, unseal keys and root token will be stored in [Azure Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-overview) as secret.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ vaultBaseURL:
+ tenantID:
+ clientCertSecret:
+ aadClientSecret:
+ cloud:
+```
+
+`mode.azureKeyVault` has the following fields:
+
+## azureKeyVault.vaultBaseURL
+
+`azureKeyVault.vaultBaseURL` is a required field that specifies the Azure key vault URL.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ vaultBaseURL: "https://myvault.vault.azure.net"
+```
+
+## azureKeyVault.tenantID
+
+`azureKeyVault.tenantID` is a required field that specifies Azure Active Directory tenant ID.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ tenantID: "aaa-ddd-ffff-343455"
+```
+
+## azureKeyVault.clientCertSecret
+
+`azureKeyVault.clientCertSecret` is an optional field that specifies the name of the secret containing client cert and client cert password. The secret contains the following fields:
+
+- `client-cert`
+- `client-cert-password`
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ clientCertSecret: "azure-client-cert-cred"
+```
+
+## azureKeyVault.aadClientSecret
+
+`azureKeyVault.aadClientSecret` is an optional field that specifies the name of the secret containing client id and client secret of AAD application. The secret contains the following fields:
+
+- `client-id`
+- `client-secret`
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ aadClientSecret: "azure-aad-client-cred"
+```
+
+## azureKeyVault.useManageIdentity
+
+`azureKeyVault.useManageIdentity` is an optional field that specifies to use managed service identity for the virtual machine.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ useManageIdentity: true
+```
+
+> Note: One of `azureKeyVault.clientCertSecret` or `azureKeyVault.aadClientSecret` or `azureKeyVault.useManageIdentity` has to be specified.
+
+## azureKeyVault.cloud
+
+`azureKeyVault.cloud` is an optional field that specifies the cloud environment identifier. If it is not specified, then `AZUREPUBLICCLOUD` will be used as default.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ azureKeyVault:
+ cloud: "AZUREGERMANCLOUD"
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/google_kms_gcs.md b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/google_kms_gcs.md
new file mode 100644
index 000000000..054940f80
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/google_kms_gcs.md
@@ -0,0 +1,112 @@
+---
+title: Google Cloud KMS | Vault Unsealer
+menu:
+ docs_v2025.11.21:
+ identifier: google-kms-gcs-unsealer
+ name: Google Cloud KMS
+ parent: unsealer-vault-server-crds
+ weight: 1
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# mode.googleKmsGcs
+
+To use **googleKmsGcs** mode specify `mode.googleKmsGcs`. In this mode, unseal keys and root token will be stored in [Google Cloud Storage](https://cloud.google.com/storage/docs/) and they will be encrypted using google cryptographic keys.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ bucket:
+ kmsProject:
+ kmsLocation:
+ kmsKeyRing:
+ kmsCryptoKey:
+ credentialSecret:
+```
+
+`mode.googleKmsGcs` has the following fields:
+
+## googleKmsGcs.bucket
+
+`googleKmsGcs.bucket` is a required field that specifies the name of the bucket to store keys.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ bucket: "vault-key-store"
+```
+
+## googleKmsGcs.kmsProject
+
+`googleKmsGcs.kmsProject` is a required field that specifies the name of the projects under which the keyring is created.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ kmsProject: "project"
+```
+
+## googleKmsGcs.kmsLocation
+
+`googleKmsGcs.kmsLocation` is a required field that specifies the location of the keyring.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ kmsLocation: "global"
+```
+
+## googleKmsGcs.kmsKeyRing
+
+`googleKmsGcs.kmsKeyRing` is a required field that specifies the name of the keyring.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ kmsKeyRing: "key-ring"
+```
+
+## googleKmsGcs.kmsCryptoKey
+
+`googleKmsGcs.kmsCryptoKey` is a required field that specifies the name of the crypto key.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ kmsCryptoKey: "key"
+```
+
+## googleKmsGcs.credentialSecret
+
+`googleKmsGcs.credentialSecret` is an optional field that specifies the name of the secret containing google credentials. If this is not specified, then the instance service account will be used (if it is running on google cloud). The secret contains the following field:
+
+- `sa.json`
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ googleKmsGcs:
+ credentialSecret: "google-cred"
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/kubernetes_secret.md b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/kubernetes_secret.md
new file mode 100644
index 000000000..7950cd3a7
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/kubernetes_secret.md
@@ -0,0 +1,45 @@
+---
+title: Kubernetes Secret | Vault Unsealer
+menu:
+ docs_v2025.11.21:
+ identifier: kubernetes-secret-unsealer
+ name: Kubernetes Secret
+ parent: unsealer-vault-server-crds
+ weight: 1
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# mode.kubernetesSecret
+
+To use **kubernetesSecret** mode specify `mode.kubernetesSecret`. In this mode, unseal keys and root token will be stored in a Kubernetes secret.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ kubernetesSecret:
+ secretName:
+```
+
+`mode.kubernetesSecret` has the following fields:
+
+## kubernetesSecret.secretName
+
+`kubernetesSecret.secretName` is a required field that specifies the name of the Kubernetes secret. If this secret does not exist, then Unsealer will create it. The secret will be created in the same namespace of [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver).
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ kubernetesSecret:
+ secretName: "vault-keys"
+```
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview.md b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview.md
new file mode 100644
index 000000000..f0128a684
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview.md
@@ -0,0 +1,102 @@
+---
+title: Overview
+menu:
+ docs_v2025.11.21:
+ identifier: unsealer-overview
+ name: Overview
+ parent: unsealer-vault-server-crds
+ weight: 1
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Unsealer
+
+[Unsealer](https://github.com/kubevault/unsealer) automates the process of [initializing](https://www.vaultproject.io/docs/commands/operator/init.html) and [unsealing](https://www.vaultproject.io/docs/concepts/seal.html#unsealing) Vault running in Kubernetes cluster. Also, it provides facilities to store unseal keys and root token in a secure way.
+
+## Configuring Unsealer
+
+To use Unsealer, configure `spec.unsealer` field in [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD .
+
+```yaml
+spec:
+ unsealer:
+ secretShares:
+ secretThresold:
+ retryPeriodSeconds:
+ overwriteExisting:
+ mode:
+ ...
+```
+
+Here, we are going to describe the various attributes of the `spec.unsealer` field.
+
+### unsealer.secretShares
+
+`unsealer.secretShares` is an optional field that specifies the number of shares to split the master key into. It accepts integer value. The default vault is `5`.
+
+```yaml
+spec:
+ unsealer:
+ secretShares: 5
+```
+
+> Note: `unsealer.secretShares` must be greater than 1.
+
+### unsealer.secretThreshold
+
+`unsealer.secretThreshold` is an optional field that specifies the number of keys required to unseal vault. It accepts integer value. The default vault is `3`.
+
+```yaml
+spec:
+ unsealer:
+ secretThreshold: 2
+```
+
+> Note: `unsealer.secretThreshold` must be a positive integer and less than or equal to `unsealer.secretShares`.
+
+### unsealer.retryPeriodSeconds
+
+`unsealer.retryPeriodSeconds` is an optional field that specifies how often Unsealer will attempt to unseal the vault instance. It accepts integer value. The default vault is `10`.
+
+```yaml
+spec:
+ unsealer:
+ retryPeriodSeconds: 15
+```
+
+### unsealer.overwriteExisting
+
+`unsealer.overwriteExisting` is an optional field that specifies Unsealer will overwrite existing unseal keys and root token(if have any). It accepts boolean value. Default vault is `false`.
+
+```yaml
+spec:
+ unsealer:
+ overwriteExisting: true
+```
+
+### unsealer.mode
+
+`unsealer.mode` is a required field that specifies which mode to use to store unseal keys and root token.
+
+```yaml
+spec:
+ unsealer:
+ mode:
+ ...
+```
+
+List of supported modes:
+
+- [kubernetesSecret](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/kubernetes_secret)
+- [googleKmsGcs](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/google_kms_gcs)
+- [awsKmsSsm](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/aws_kms_ssm)
+- [azureKeyVault](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/azure_key_vault)
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/vaultserver.md b/content/docs/v2025.11.21/concepts/vault-server-crds/vaultserver.md
new file mode 100644
index 000000000..4c9dc448c
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/vaultserver.md
@@ -0,0 +1,363 @@
+---
+title: Vault Server | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: vaultserver-vault-server-crds
+ name: Vault Server
+ parent: vault-server-crds-concepts
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# VaultServer
+
+## What is VaultServer
+
+A `VaultServer` is a Kubernetes `CustomResourceDefinition` (CRD) which is used to deploy a HashiCorp Vault server on Kubernetes clusters in a Kubernetes native way.
+
+When a `VaultServer` is created, the KubeVault operator will deploy a Vault server and create necessary Kubernetes resources required for the Vault server.
+
+
+
+## VaultServer CRD Specification
+
+Like any official Kubernetes resource, a `VaultServer` object has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections.
+
+A sample `VaultServer` object is shown below:
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ tls:
+ issuerRef:
+ apiGroup: "cert-manager.io"
+ kind: Issuer
+ name: vault-issuer
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ secretEngines:
+ - mysql
+ version: 1.10.3
+ replicas: 3
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
+```
+
+Here, we are going to describe the various sections of the `VaultServer` crd.
+
+### VaultServer Spec
+
+VaultServer Spec contains the configuration about how to deploy Vault in the Kubernetes cluster. It also covers automate unsealing of Vault.
+
+The `spec` section has following parts:
+
+#### spec.replicas
+
+`spec.replicas` specifies the number of Vault nodes to deploy. It has to be a positive number.
+
+```yaml
+spec:
+ replicas: 3 # 3 vault server will be deployed in Kubernetes cluster
+```
+
+#### spec.version
+
+Specifies the name of the `VaultServerVersion` CRD. This CRD holds the image name and version of the Vault, Unsealer, and Exporter. To know more information about `VaultServerVersion` CRD see [here](/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion).
+
+```yaml
+spec:
+ version: "1.10.3"
+```
+
+#### spec.tls
+
+`spec.tls` is an optional field that specifies the TLS policy of Vault nodes. If this is not specified, the KubeVault operator will run in `insecure` mode.
+
+```yaml
+spec:
+ tls:
+ issuerRef:
+ apiGroup: "cert-manager.io"
+ kind: Issuer
+ name: vault-issuer
+```
+
+The server certificate must allow the following wildcard domains:
+- `localhost`
+- `*..pod`
+- `..svc`
+
+ The server certificate must allow the following IP:
+- `127.0.0.1`
+
+#### spec.configSecret
+
+`spec.configSecret` is an optional field that allows the user to provide extra configuration for Vault. This field accepts a [VolumeSource](https://github.com/kubernetes/api/blob/release-1.11/core/v1/types.go#L47). You can use any Kubernetes supported volume source such as configMap, secret, azureDisk, etc.
+
+> Please note that the config file name must be `vault.hcl` to work.
+
+```yaml
+spec:
+ configSecret:
+ : # for example `configSecret`
+ name:
+```
+
+### spec.dataSources
+
+`spec.dataSources` is an `optional` field that allows the user to provide a list of [VolumeSources](https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes) (i.e. secrets, configmaps, etc.) which will be mounted into the VaultServer pods. These volumes will be mounted into `/etc/vault/data/` directory. The first data will be named as `data-0`, the second one will be named as `data-1` and so on.
+
+```yaml
+spec:
+ dataSources:
+ - secret: # mounted on /etc/vault/data/data-0
+ secretName: custom-cert
+ - configMap: # mounted on /etc/vault/data/data-1
+ name: special-config
+```
+
+### spec.monitor
+`spec.monitor` is an optional field that is used to monitor the `vaultserver` instances.
+```yaml
+monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+```
+
+### spec.terminationPolicy
+`spec.terminationPolicy` is an optional field that gives flexibility whether to nullify(reject) the delete operation of VaultServer crd or which resources KubeVault operator should keep or delete when you delete VaultServer crd. KubeVault provides following four termination policies:
+- DoNotTerminate
+- Halt
+- Delete (Default)
+- WipeOut
+
+When, `terminationPolicy` is `DoNotTerminate`, KubeVault takes advantage of ValidationWebhook feature in Kubernetes 1.9.0 or later clusters to provide safety from accidental deletion of VaultServer. If admission webhook is enabled, KubeVault prevents users from deleting the VaultServer as long as the spec.terminationPolicy is set to DoNotTerminate.
+
+### spec.backend
+
+`spec.backend` is a required field that specifies the Vault backend storage configuration. KubeVault operator generates storage configuration according to this `spec.backend`.
+
+```yaml
+spec:
+ backend:
+ ...
+```
+List of supported backends:
+
+- [Azure](/docs/v2025.11.21/concepts/vault-server-crds/storage/azure)
+- [Consul](/docs/v2025.11.21/concepts/vault-server-crds/storage/consul)
+- [DynamoDB](/docs/v2025.11.21/concepts/vault-server-crds/storage/dynamodb)
+- [Etcd](/docs/v2025.11.21/concepts/vault-server-crds/storage/etcd)
+- [GCS](/docs/v2025.11.21/concepts/vault-server-crds/storage/gcs)
+- [In Memory](/docs/v2025.11.21/concepts/vault-server-crds/storage/inmem)
+- [MySQL](/docs/v2025.11.21/concepts/vault-server-crds/storage/mysql)
+- [PosgreSQL](/docs/v2025.11.21/concepts/vault-server-crds/storage/postgresql)
+- [AWS S3](/docs/v2025.11.21/concepts/vault-server-crds/storage/s3)
+- [Swift](/docs/v2025.11.21/concepts/vault-server-crds/storage/swift)
+- [Filesystem](/docs/v2025.11.21/concepts/vault-server-crds/storage/filesystem)
+- [Raft](/docs/v2025.11.21/concepts/vault-server-crds/storage/raft)
+
+#### spec.unsealer
+
+`spec.unsealer` is an optional field that specifies [Unsealer](https://github.com/kubevault/unsealer) configuration. Unsealer handles automatic initializing and unsealing of Vault. See [here](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview) for Unsealer documentation.
+
+```yaml
+spec:
+ unsealer:
+ secretShares:
+ secretThresold:
+ retryPeriodSeconds:
+ overwriteExisting:
+ mode:
+ ...
+```
+
+#### spec.serviceTemplates
+
+You can also provide a list of templates for the services created by KubeVault operator for VaultServer through `spec.serviceTemplates`. This will allow you to set the type and other properties of the services. `spec.serviceTemplates` is an optional field.
+
+```yaml
+spec:
+ serviceTemplates:
+ - alias: stats
+ spec:
+ type: ClusterIP
+```
+
+VaultServer allows following fields to be set in `spec.serviceTemplates`:
+
+- metadata:
+ - annotations (set as annotations on Vault service)
+- spec:
+ - type
+ - ports
+ - clusterIP
+ - externalIPs
+ - loadBalancerIP
+ - loadBalancerSourceRanges
+ - externalTrafficPolicy
+ - healthCheckNodePort
+ - sessionAffinityConfig
+
+#### spec.podTemplate
+
+VaultServer allows providing a template for Vault pod through `spec.podTemplate`. KubeVault operator will pass the information provided in `spec.podTemplate` to the Deployment created for Vault. `spec.podTemplate` is an optional field.
+
+```yaml
+spec:
+ podTemplate:
+ spec:
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "250m"
+ limits:
+ memory: "128Mi"
+ cpu: "500m"
+```
+
+VaultServer accepts the following fields to set in `spec.podTemplate:`
+
+- metadata:
+ - annotations (set as annotations on Vault pods)
+- controller:
+ - annotations (set as annotations on Vault statefulset)
+- spec:
+ - resources
+ - imagePullSecrets
+ - nodeSelector
+ - affinity
+ - schedulerName
+ - tolerations
+ - priorityClassName
+ - priority
+ - securityContext
+
+You can find the full list of fields [here](https://github.com/kmodules/offshoot-api/blob/kubernetes-1.16.3/api/v1/types.go). Some of the fields of `spec.podTemplate` are described below:
+
+##### spec.podTemplate.spec.imagePullSecret
+
+`spec.podTemplate.spec.imagePullSecrets` is an optional field that points to secrets to be used for pulling docker images if you are using a private docker registry.
+
+##### spec.podTemplate.spec.nodeSelector
+
+`spec.podTemplate.spec.nodeSelector` is an optional field that specifies a map of key-value pairs. For the pod to be eligible to run on a node, the node must have each of the indicated key-value pairs as labels (it can have additional labels as well). To learn more, see [here](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) .
+
+##### spec.podTemplate.spec.resources
+
+`spec.podTemplate.spec.resources` is an optional field. This can be used to request compute resources required by Vault pods. To learn more, visit [here](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/).
+
+#### spec.authMethods
+
+`spec.authMethods` is an optional field that specifies the list of auth methods to enable in Vault.
+
+```yaml
+spec:
+ authMethods:
+ - type: kubernetes
+ path: k8s
+ - type: aws
+ path: aws
+```
+
+`spec.authMethods` has following fields:
+
+##### spec.authMethods[].type
+
+`spec.authMethods[].type` is a required field that specifies the name of the authentication method type.
+
+##### spec.authMethods[].path
+
+`spec.authMethods[].path` is a required field that specifies the path where to enable the auth method.
+
+##### spec.authMethods[].description
+
+`spec.authMethods[].description` is an optional field that specifies a human-friendly description of the auth method.
+
+##### spec.authMethods[].pluginName
+
+`spec.authMethods[].pluginName` is an optional field that specifies the name of the auth plugin to use based on the name in the plugin catalog.
+
+##### spec.authMethods[].local
+
+`spec.authMethods[].local` is an optional field that specifies if the auth method is local only. Local auth methods are not replicated nor (if a secondary) removed by replication.
+
+##### spec.authMethods[].config
+
+`spec.authMethods[].config` is an optional field that specifies configuration options for auth method.
+
+`spec.authMethods[].config` has following fields:
+
+- `defaultLeaseTTL` : `Optional`. Specifies the default lease duration.
+
+- `maxLeaseTTL` : `Optional`. Specifies the maximum lease duration.
+
+- `pluginName` : `Optional`. Specifies the name of the plugin in the plugin catalog to use.
+
+- `auditNonHMACRequestKeys` : `Optional`. Specifies the list of keys that will not be HMAC'd by audit devices in the request data object.
+
+- `auditNonHMACResponseKeys`: `Optional`. Specifies the list of keys that will not be HMAC'd by audit devices in the response data object.
+
+- `listingVisibility`: `Optional`. Specifies whether to show this is mount in the UI-specific listing endpoint.
+
+- `passthroughRequestHeaders`: `Optional`. Specifies a list of headers to whitelist and pass from the request to the backend.
+
+### VaultServer Status
+
+VaultServer Status shows the status of a Vault deployment. The status of the Vault is monitored and updated by the KubeVault operator.
+
+```yaml
+status:
+ phase:
+```
+
+- `phase`: Indicates the phase Vault is currently in. Possible values of `status.phase`:
+ - Initializing
+ - Sealed
+ - Unsealing
+ - Critical
+ - NotReady
+ - Ready
+
+- `authMethodStatus` : Indicates the status of the auth methods specified in `spec.authMethods`. It has the following fields:
+
+ - `type`: Specifies the name of the authentication method type
+
+ - `path`: Specifies the path in which the auth method is enabled.
+
+ - `status`: Specifies whether the auth method is enabled or not.
+
+ - `reason`: Specifies the reason why failed to enable the auth method.
diff --git a/content/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion.md b/content/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion.md
new file mode 100644
index 000000000..89de83612
--- /dev/null
+++ b/content/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion.md
@@ -0,0 +1,101 @@
+---
+title: Vault Server Version | KubeVault Concepts
+menu:
+ docs_v2025.11.21:
+ identifier: vaultserverversion-vault-server-crds
+ name: Vault Server Version
+ parent: vault-server-crds-concepts
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: concepts
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# VaultServerVersion
+
+## What is VaultServerVersion
+
+`VaultServerVersion` is a Kubernetes `Custom Resource Definitions` (CRD). It is a **non-namespaced** CRD. The name of this CRD will be used in `.spec.version` field of [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver) CRD. It provides a way to specify the docker images for Vault, Unsealer, and Exporter.
+
+Using a separate CRD for specifying respective docker images allows us to modify the images independently of the KubeVault operator. This also allows users to use their custom images.
+
+```yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: '1.10.3'
+spec:
+ version: 1.10.3
+ exporter:
+ image: kubevault/vault-exporter:v0.1.1
+ unsealer:
+ image: kubevault/vault-unsealer:v0.8.0
+ vault:
+ image: vault:1.10.3
+```
+
+### VaultServerVersion Spec
+
+VaultServerVersion `.spec` contains image information.
+
+```yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: '1.10.3'
+spec:
+ version: 1.10.3
+ exporter:
+ image: kubevault/vault-exporter:v0.1.1
+ unsealer:
+ image: kubevault/vault-unsealer:v0.8.0
+ vault:
+ image: vault:1.10.3
+```
+
+`.spec` contains following fields:
+
+#### spec.version
+
+`spec.version` is a required field that specifies the original version of Vault that has been used to build the docker image specified in `spec.vault.image` field.
+
+#### spec.deprecated
+
+`spec.deprecated` is an optional field that specifies whether the specified docker images are supported by the current KubeVault operator. The default value of this field is false.
+
+#### spec.vault.image
+
+`spec.vault.image` is a required field that specifies the docker image which will be used for Vault.
+
+```yaml
+spec:
+ vault:
+ image: vault:1.10.3
+```
+
+#### spec.unsealer.image
+
+`spec.unsealer.image` is a required field that specifies the docker image which will be used for Unsealer.
+
+```yaml
+spec:
+ unsealer:
+ image: kubevault/vault-unsealer:0.8.0
+```
+
+#### spec.exporter.image
+
+`spec.exporter.image` is a required field that specifies the docker image which will be used to export Prometheus metrics.
+
+```yaml
+spec:
+ exporter:
+ image: kubevault/vault-exporter:0.1.1
+```
diff --git a/content/docs/v2025.11.21/examples/guides/backup-restore/backup-configuration.yaml b/content/docs/v2025.11.21/examples/guides/backup-restore/backup-configuration.yaml
new file mode 100644
index 000000000..f508d1a7e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/backup-restore/backup-configuration.yaml
@@ -0,0 +1,26 @@
+apiVersion: stash.appscode.com/v1beta1
+kind: BackupConfiguration
+metadata:
+ name: demo-backup
+ namespace: demo
+spec:
+ driver: Restic
+ repository:
+ name: gcp-demo-repo
+ namespace: demo
+ schedule: "*/5 * * * *"
+ timeOut: 2h
+ target:
+ ref:
+ apiVersion: appcatalog.appscode.com/v1alpha1
+ kind: AppBinding
+ name: vault
+ runtimeSettings:
+ container:
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ retentionPolicy:
+ name: 'keep-last-5'
+ keepLast: 5
+ prune: true
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/backup-restore/repository.yaml b/content/docs/v2025.11.21/examples/guides/backup-restore/repository.yaml
new file mode 100644
index 000000000..c53e45576
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/backup-restore/repository.yaml
@@ -0,0 +1,15 @@
+apiVersion: stash.appscode.com/v1alpha1
+kind: Repository
+metadata:
+ name: gcp-demo-repo
+ namespace: demo
+spec:
+ backend:
+ gcs:
+ bucket: stash-testing
+ prefix: demo-vault
+ storageSecretName: gcs-secret
+ usagePolicy:
+ allowedNamespaces:
+ from: Same
+ wipeOut: false
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/backup-restore/restore-session.yaml b/content/docs/v2025.11.21/examples/guides/backup-restore/restore-session.yaml
new file mode 100644
index 000000000..d2c0c62df
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/backup-restore/restore-session.yaml
@@ -0,0 +1,20 @@
+apiVersion: stash.appscode.com/v1beta1
+kind: RestoreSession
+metadata:
+ name: vault-restore-session
+ namespace: demo
+spec:
+ repository:
+ name: gcp-demo-repo
+ target:
+ ref:
+ apiVersion: appcatalog.appscode.com/v1alpha1
+ kind: AppBinding
+ name: vault
+ runtimeSettings:
+ container:
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ rules:
+ - snapshots: [latest]
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/backup-restore/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/backup-restore/vaultserver.yaml
new file mode 100644
index 000000000..0df7adf4b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/backup-restore/vaultserver.yaml
@@ -0,0 +1,30 @@
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.10.3
+ replicas: 3
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: WipeOut
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/policy-management/policy-reader-role.yaml b/content/docs/v2025.11.21/examples/guides/policy-management/policy-reader-role.yaml
new file mode 100644
index 000000000..dab18a96d
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/policy-management/policy-reader-role.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: policy-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: read-only-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "demo-sa"
+ serviceAccountNamespaces:
+ - "demo"
diff --git a/content/docs/v2025.11.21/examples/guides/policy-management/read-only-policy.yaml b/content/docs/v2025.11.21/examples/guides/policy-management/read-only-policy.yaml
new file mode 100644
index 000000000..558a7b112
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/policy-management/read-only-policy.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: read-only-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "sys/policy" {
+ capabilities = ["list"]
+ }
+
+ path "sys/policy/*" {
+ capabilities = ["read"]
+ }
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/policy-management/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/policy-management/vaultserver.yaml
new file mode 100644
index 000000000..51a469a47
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/policy-management/vaultserver.yaml
@@ -0,0 +1,16 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.3"
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/policy-management/vaultserverversion.yaml b/content/docs/v2025.11.21/examples/guides/policy-management/vaultserverversion.yaml
new file mode 100644
index 000000000..2d8274907
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/policy-management/vaultserverversion.yaml
@@ -0,0 +1,13 @@
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ version: 1.2.0
+ deprecated: false
+ vault:
+ image: vault:1.2.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ exporter:
+ image: kubevault/vault-exporter:0.1.0
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/provider/aks/my-vault.yaml b/content/docs/v2025.11.21/examples/guides/provider/aks/my-vault.yaml
new file mode 100644
index 000000000..0314bad61
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/aks/my-vault.yaml
@@ -0,0 +1,21 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ azure:
+ container: demo-vault
+ accountName: vaultstorageac
+ accountKeySecret: azure-ac-key
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ azureKeyVault:
+ vaultBaseURL: https://vault-key-store.vault.azure.net/
+ tenantID: aaaaaaa-bbbb-ccc-dddd-eeeeeeeee
+ aadClientSecret: azure-ad-client-secret
diff --git a/content/docs/v2025.11.21/examples/guides/provider/aks/vaultserverversion.yaml b/content/docs/v2025.11.21/examples/guides/provider/aks/vaultserverversion.yaml
new file mode 100644
index 000000000..2d8274907
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/aks/vaultserverversion.yaml
@@ -0,0 +1,13 @@
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ version: 1.2.0
+ deprecated: false
+ vault:
+ image: vault:1.2.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ exporter:
+ image: kubevault/vault-exporter:0.1.0
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/provider/eks/my-vault.yaml b/content/docs/v2025.11.21/examples/guides/provider/eks/my-vault.yaml
new file mode 100644
index 000000000..40aac2f96
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/eks/my-vault.yaml
@@ -0,0 +1,20 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ s3:
+ bucket: "demo-vault-3"
+ region: "us-east-1"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ awsKmsSsm:
+ region: "us-east-1"
+ kmsKeyID: "218daa5f-7173-429e-a030-288b30761f79"
+ ssmKeyPrefix: "/cluster/demo"
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/demo-policy.yaml b/content/docs/v2025.11.21/examples/guides/provider/external-vault/demo-policy.yaml
new file mode 100644
index 000000000..99a2beac4
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/demo-policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: demo-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault-app
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/policy-admin-sa.yaml b/content/docs/v2025.11.21/examples/guides/provider/external-vault/policy-admin-sa.yaml
new file mode 100644
index 000000000..3ce5d5c95
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/policy-admin-sa.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: policy-admin
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/policy-admin.hcl b/content/docs/v2025.11.21/examples/guides/provider/external-vault/policy-admin.hcl
new file mode 100644
index 000000000..e34b487fd
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/policy-admin.hcl
@@ -0,0 +1,15 @@
+path "sys/policy/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
+
+path "sys/policy" {
+ capabilities = ["read", "list"]
+}
+
+path "auth/kubernetes/role" {
+ capabilities = ["read", "list"]
+}
+
+path "auth/kubernetes/role/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/token-review-binding.yaml b/content/docs/v2025.11.21/examples/guides/provider/external-vault/token-review-binding.yaml
new file mode 100644
index 000000000..d54d58ea9
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/token-review-binding.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: role-tokenreview-binding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: system:auth-delegator
+subjects:
+- kind: ServiceAccount
+ name: token-reviewer
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/token-reviewer-sa.yaml b/content/docs/v2025.11.21/examples/guides/provider/external-vault/token-reviewer-sa.yaml
new file mode 100644
index 000000000..70c550d43
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/token-reviewer-sa.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: token-reviewer
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/vault-app.yaml b/content/docs/v2025.11.21/examples/guides/provider/external-vault/vault-app.yaml
new file mode 100644
index 000000000..65c04eebb
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/vault-app.yaml
@@ -0,0 +1,15 @@
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ clientConfig:
+ url: http://vault.default.svc:8200
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes
+ vaultRole: policy-admin-role
+ kubernetes:
+ serviceAccountName: policy-admin
diff --git a/content/docs/v2025.11.21/examples/guides/provider/external-vault/vault.yaml b/content/docs/v2025.11.21/examples/guides/provider/external-vault/vault.yaml
new file mode 100644
index 000000000..26a0b043e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/external-vault/vault.yaml
@@ -0,0 +1,46 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: vault
+ namespace: default
+spec:
+ ports:
+ - name: http
+ nodePort: 30001
+ port: 8200
+ selector:
+ app: vault
+ type: NodePort
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: vault
+ namespace: default
+ labels:
+ app: vault
+spec:
+ serviceName: "vault"
+ selector:
+ matchLabels:
+ app: vault
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: vault
+ spec:
+ containers:
+ - name: vault
+ image: "vault:1.0.0"
+ args:
+ - "server"
+ - "-dev"
+ - "-dev-root-token-id=aajf-dhg-ddht-ccdf"
+ ports:
+ - name: http
+ containerPort: 8200
+ protocol: "TCP"
+ - name: server
+ containerPort: 8201
+ protocol: "TCP"
diff --git a/content/docs/v2025.11.21/examples/guides/provider/gke/my-vault.yaml b/content/docs/v2025.11.21/examples/guides/provider/gke/my-vault.yaml
new file mode 100644
index 000000000..ea784577a
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/gke/my-vault.yaml
@@ -0,0 +1,23 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ gcs:
+ bucket: "demo-vault"
+ credentialSecret: "google-cred"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ googleKmsGcs:
+ bucket: "demo-vault"
+ kmsProject: "ackube"
+ kmsLocation: "global"
+ kmsKeyRing: "vault"
+ kmsCryptoKey: "vault-key"
+ credentialSecret: "google-cred"
diff --git a/content/docs/v2025.11.21/examples/guides/provider/gke/vaultserverversion.yaml b/content/docs/v2025.11.21/examples/guides/provider/gke/vaultserverversion.yaml
new file mode 100644
index 000000000..31e040a82
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/gke/vaultserverversion.yaml
@@ -0,0 +1,12 @@
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ exporter:
+ image: kubevault/vault-exporter:v0.1.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ vault:
+ image: vault:1.2.0
+ version: 1.2.0
diff --git a/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/demo-policy-secret-admin.yaml b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/demo-policy-secret-admin.yaml
new file mode 100644
index 000000000..26767164a
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/demo-policy-secret-admin.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: demo-policy-secret-admin
+ namespace: demo
+spec:
+ vaultRef:
+ name: my-vault
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/demo-policy-secret-reader.yaml b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/demo-policy-secret-reader.yaml
new file mode 100644
index 000000000..198b37de8
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/demo-policy-secret-reader.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: demo-policy-secret-reader
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault-app
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["read", "list"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/my-vault.yaml b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/my-vault.yaml
new file mode 100644
index 000000000..9977751b2
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/my-vault.yaml
@@ -0,0 +1,34 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ gcs:
+ bucket: "demo-vault"
+ credentialSecret: "google-cred"
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: LoadBalancer
+ loadBalancerIP: 104.155.177.205
+ tls:
+ certificates:
+ - alias: ca
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ googleKmsGcs:
+ bucket: "demo-vault"
+ kmsProject: "ackube"
+ kmsLocation: "global"
+ kmsKeyRing: "vault"
+ kmsCryptoKey: "vault-key"
+ credentialSecret: "google-cred"
diff --git a/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vault-app.yaml b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vault-app.yaml
new file mode 100644
index 000000000..a6a8e814e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vault-app.yaml
@@ -0,0 +1,11 @@
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: vault-token
+ clientConfig:
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9UQXhNRGN3T1RNNE1UaGFGdzB5T1RBeE1EUXdPVE00TVRoYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdXZxWFJrMGZrMHNWMFpoMDQwd0FaVTBhCkhlRW9vUnlVMlpaaGtjS3dPS201N2pUWkJaMEkvMjg2dTNpUVFpc2tMTFNjYUtvaHp0c012RXFCU0JpNU5MNEMKVXVQbm5CZklIVVo1UDhwQWNOUXJ5SURETGxXZTFBTEVKU0N0L3daRG5mMkRPdXZGSVMybFJVZDV2WFp1dlVjWgptdml5T3VUOW9CclNwNkh5YUpRYkUrZk1qQTRvZ0ZoQWZmN1djMm1DVk1jam8wU3htK2lrVWxVZWhXdWd4T3M0Cm5GUG5pWmt3a1h0KzFweU45WjltclhwUTlZM3FvdGlmdk1aUnVhVS9hbjUxOUZqSWdzVUZtRGVoZ3c3blJwYkkKZ0NGeUNPSlc5ZTNDczNRVTViVTJYUk1leDBlTDZReTZJY2dDdGZIRmpBeGhjUHAzeEJjRW5XSEdONDM2dHdJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFUMzFuQUNpMmNySW0rWCtGZUNocjJJcnhZeGFDSlpLNW92Y1Jqem5TZFR0N2JadWoKcTVZQW5jbitESDlxUURkczFVTEdjR1ZISlpiS3RORU9GVVlJbDVXYUZBVnNBMTJoaURCZnJXc24ydUV6K0pUVwovcStLSVE0OW1LUWV1TG80bkVoQnRJYjJzaXBKMmxmUEVyUXhHQllrZ3lOT05zOTN5NEdPVXU4dVdBaUFqZ21oCmM4a1QzTVV0ZVRNUHczQ3JKU2ZtbGUxQkk0bkNPNXEreW54Zk56SXZqZU5PYnNvVTdOOVhoZTdCQjZSSzQ1akgKVW41bzBTZkkrR0dYU0l5eWFxVHlJRUJkK3Nub1pMRWQzMm9DeWJFOC9QajE3T3BDZHhhd0ZnZWJGUnNEQ2pkRQo0bUI2RmVPMi9md3VFUk5lTlZnczBHMjBPc2t4cDJoTWJRYUlJZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
+ url: https://104.155.177.205:8200
diff --git a/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vault-token.yaml b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vault-token.yaml
new file mode 100644
index 000000000..f17c211f0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vault-token.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+data:
+ token: cy43RERVOWp5UnhSN05kck1FUzBDNkNaTUs=
+kind: Secret
+metadata:
+ name: vault-token
+ namespace: demo
+type: kubevault.com/token
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vaultserverversion.yaml b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vaultserverversion.yaml
new file mode 100644
index 000000000..31e040a82
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/provider/multi-cluster/vaultserverversion.yaml
@@ -0,0 +1,12 @@
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ exporter:
+ image: kubevault/vault-exporter:v0.1.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ vault:
+ image: vault:1.2.0
+ version: 1.2.0
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/pod.yaml
new file mode 100644
index 000000000..0719ba2c8
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/aws-keys"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/policy.yaml
new file mode 100644
index 000000000..dd203e63d
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: aws-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-aws-path/creds/*" {
+ capabilities = ["read", "create"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/policybinding.yaml
new file mode 100644
index 000000000..de5954891
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: aws-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: aws-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secret-role-binding.yaml
new file mode 100644
index 000000000..e5eb70596
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secret.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secret.yaml
new file mode 100644
index 000000000..b7b3292b0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secret.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aws-cred
+ namespace: demo
+data:
+ access_key: N2I2bl==
+ secret_key: N2I2bl==
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretengine.yaml
new file mode 100644
index 000000000..ab5dd722f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretengine.yaml
@@ -0,0 +1,14 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: aws-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ aws:
+ credentialSecret: aws-cred
+ region: us-east-1
+ leaseConfig:
+ lease: 1h
+ leaseMax: 1h
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretenginerole.yaml
new file mode 100644
index 000000000..7556f1769
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretenginerole.yaml
@@ -0,0 +1,20 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AWSRole
+metadata:
+ name: aws-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: aws-secret-engine
+ credentialType: iam_user
+ policyDocument: |
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "ec2:*",
+ "Resource": "*"
+ }
+ ]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretproviderclass.yaml
new file mode 100644
index 000000000..4d777b9b5
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.aws-reader-role"
+ objects: |
+ - objectName: "access_key"
+ secretPath: "your-aws-path/creds/k8s.-.demo.aws-role"
+ secretKey: "access_key"
+ - objectName: "secret_key"
+ secretPath: "your-aws-path/creds/k8s.-.demo.aws-role"
+ secretKey: "secret_key"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/serviceaccount.yaml
new file mode 100644
index 000000000..784a86322
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/aws/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/vaultserver.yaml
new file mode 100644
index 000000000..1017c6396
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/aws/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/pod.yaml
new file mode 100644
index 000000000..a23159131
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/azure-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/policy.yaml
new file mode 100644
index 000000000..b132d7aa1
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: azure-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-azure-path/creds/*" {
+ capabilities = ["read", "create"]
+ }
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/policybinding.yaml
new file mode 100644
index 000000000..34af73767
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: azure-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: azure-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secret-role-binding.yaml
new file mode 100644
index 000000000..5714de4b9
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: AzureRole
+ name: azure-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secret.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secret.yaml
new file mode 100644
index 000000000..1868432bc
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: azure-cred
+ namespace: demo
+data:
+ client-secret: eyJtc2ciOiJleGFtcGxlIn0=
+ subscription-id: eyJtc2ciOiJleGFtcGxlIn0=
+ client-id: eyJtc2ciOiJleGFtcGxlIn0=
+ tenant-id: eyJtc2ciOiJleGFtcGxlIn0=
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretengine.yaml
new file mode 100644
index 000000000..bd0d22c01
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretengine.yaml
@@ -0,0 +1,10 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: azure-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ azure:
+ credentialSecret: azure-cred
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretenginerole.yaml
new file mode 100644
index 000000000..b0dd281ce
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretenginerole.yaml
@@ -0,0 +1,10 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AzureRole
+metadata:
+ name: azure-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: azure-secret-engine
+ applicationObjectID: e211afbc-cc4a-462f-ad6f-59e26eb5406f
+ ttl: 1h
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretproviderclass.yaml
new file mode 100644
index 000000000..668b616c8
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.azure-reader-role"
+ objects: |
+ - objectName: "client_id"
+ secretPath: "your-azure-path/creds/k8s.-.demo.azure-role"
+ secretKey: "client_id"
+ - objectName: "client_secret"
+ secretPath: "your-azure-path/creds/k8s.-.demo.azure-role"
+ secretKey: "client_secret"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/serviceaccount.yaml
new file mode 100644
index 000000000..784a86322
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/azure/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/azure/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/elasticsearch.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/elasticsearch.yaml
new file mode 100644
index 000000000..026877448
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/elasticsearch.yaml
@@ -0,0 +1,18 @@
+apiVersion: kubedb.com/v1alpha2
+kind: Elasticsearch
+metadata:
+ name: elasticsearch
+ namespace: demo
+spec:
+ version: xpack-7.17.15
+ enableSSL: false
+ replicas: 3
+ storageType: Durable
+ storage:
+ storageClassName: "standard"
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ terminationPolicy: DoNotTerminate
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/pod.yaml
new file mode 100644
index 000000000..6d292635a
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/es-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/policy.yaml
new file mode 100644
index 000000000..ba9b4cfcf
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: es-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-database-path/creds/*" {
+ capabilities = ["read"]
+ }
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/policybinding.yaml
new file mode 100644
index 000000000..0f6ad90f0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: es-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: es-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secret-role-binding.yaml
new file mode 100644
index 000000000..0ea676466
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: ElasticsearchRole
+ name: es-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretengine.yaml
new file mode 100644
index 000000000..76f2283b3
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretengine.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: es-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ elasticsearch:
+ databaseRef:
+ name: elasticsearch
+ namespace: demo
+ pluginName: "elasticsearch-database-plugin"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretenginerole.yaml
new file mode 100644
index 000000000..c3bc2658b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretenginerole.yaml
@@ -0,0 +1,12 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: ElasticsearchRole
+metadata:
+ name: es-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: es-secret-engine
+ creationStatements:
+ - '{"elasticsearch_roles": ["superuser"]}'
+ defaultTTL: 1h
+ maxTTL: 24h
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretproviderclass.yaml
new file mode 100644
index 000000000..f9faecee6
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.es-reader-role"
+ objects: |
+ - objectName: "es-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.es-superuser-role"
+ secretKey: "username"
+ - objectName: "es-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.es-superuser-role"
+ secretKey: "password"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/serviceaccount.yaml
new file mode 100644
index 000000000..ed79c6d5b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/pod.yaml
new file mode 100644
index 000000000..53b75cfcc
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/gcp-access-token"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/policy.yaml
new file mode 100644
index 000000000..4a575a19e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: gcp-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-gcp-path/token/*" {
+ capabilities = ["read"]
+ }
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/policybinding.yaml
new file mode 100644
index 000000000..ce9e22ad0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: gcp-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: gcp-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secret-role-binding.yaml
new file mode 100644
index 000000000..fed6617a5
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: GCPRole
+ name: gcp-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secret.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secret.yaml
new file mode 100644
index 000000000..cf78f5f5e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secret.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: gcp-cred
+ namespace: demo
+data:
+ sa.json: eyJtc2ciOiJleGFtcGxlIn0= ## base64 encoded google service account credential
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretengine.yaml
new file mode 100644
index 000000000..8d949a29c
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretengine.yaml
@@ -0,0 +1,10 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: gcp-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ gcp:
+ credentialSecret: gcp-cred
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretenginerole.yaml
new file mode 100644
index 000000000..d2bf01aa2
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretenginerole.yaml
@@ -0,0 +1,16 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: GCPRole
+metadata:
+ name: gcp-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: gcp-secret-engine
+ secretType: "access_token"
+ project: appscode-testing
+ bindings: |
+ resource "//cloudresourcemanager.googleapis.com/projects/appscode-testing" {
+ roles = ["roles/viewer"]
+ }
+ tokenScopes:
+ - https://www.googleapis.com/auth/cloud-platform
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretproviderclass.yaml
new file mode 100644
index 000000000..4e6cf2b1e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/secretproviderclass.yaml
@@ -0,0 +1,14 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.gcp-reader-role"
+ objects: |
+ - objectName: "gcp-token"
+ secretPath: "your-gcp-path/token/k8s.-.demo.gcp-role"
+ secretKey: "token"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/serviceaccount.yaml
new file mode 100644
index 000000000..784a86322
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/vaultserver.yaml
new file mode 100644
index 000000000..1017c6396
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/gcp/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/kv/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/pod.yaml
new file mode 100644
index 000000000..da6c9a14f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/pod.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: test-app
+ namespace: demo
+spec:
+ serviceAccountName: pod-sa
+ containers:
+ - image: jweissig/app:0.0.1
+ name: test-app
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/test"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-database"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/kv/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/policy.yaml
new file mode 100644
index 000000000..a1fb2f434
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: kv-se-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["read"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/kv/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/policybinding.yaml
new file mode 100644
index 000000000..111996f74
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: kv-se-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: kv-se-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "pod-sa"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/kv/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/secretproviderclass.yaml
new file mode 100644
index 000000000..1e6ee18d3
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/secretproviderclass.yaml
@@ -0,0 +1,14 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-database
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.kv-se-role"
+ objects: |
+ - objectName: "db-password"
+ secretPath: "secret/db-pass"
+ secretKey: "password"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/kv/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/serviceaccount.yaml
new file mode 100644
index 000000000..3eef7fb34
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: pod-sa
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/kv/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/kv/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/mariadb.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/mariadb.yaml
new file mode 100644
index 000000000..0aa7b7c91
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/mariadb.yaml
@@ -0,0 +1,16 @@
+apiVersion: kubedb.com/v1alpha2
+kind: MariaDB
+metadata:
+ name: mariadb
+ namespace: demo
+spec:
+ version: 10.6.16
+ storageType: Durable
+ storage:
+ storageClassName: "standard"
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/pod.yaml
new file mode 100644
index 000000000..d5676e694
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/mysql-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/policy.yaml
new file mode 100644
index 000000000..7bec72f34
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: mariadb-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-database-path/creds/*" {
+ capabilities = ["read"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/policybinding.yaml
new file mode 100644
index 000000000..fc71fd5e9
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: mariadb-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: mariadb-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secret-role-binding.yaml
new file mode 100644
index 000000000..3aac38ece
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: MariaDBRole
+ name: mariadb-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretengine.yaml
new file mode 100644
index 000000000..afa0ea361
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretengine.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: mariadb-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mysql:
+ databaseRef:
+ name: mariadb
+ namespace: demo
+ pluginName: "mysql-database-plugin"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretenginerole.yaml
new file mode 100644
index 000000000..36137d83a
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretenginerole.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MariaDBRole
+metadata:
+ name: mariadb-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: mariadb-secret-engine
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+ defaultTTL: 1h
+ maxTTL: 24h
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretproviderclass.yaml
new file mode 100644
index 000000000..a78c11390
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.mysql-reader-role"
+ objects: |
+ - objectName: "mariadb-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.mariadb-superuser-role"
+ secretKey: "username"
+ - objectName: "mariadb-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.mariadb-superuser-role"
+ secretKey: "password"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/serviceaccount.yaml
new file mode 100644
index 000000000..ed79c6d5b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mariadb/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/mongodb.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/mongodb.yaml
new file mode 100644
index 000000000..05208afc7
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/mongodb.yaml
@@ -0,0 +1,16 @@
+apiVersion: kubedb.com/v1alpha2
+kind: MongoDB
+metadata:
+ name: mongodb
+ namespace: demo
+spec:
+ version: "4.4.26"
+ storageType: Durable
+ storage:
+ storageClassName: "standard"
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/pod.yaml
new file mode 100644
index 000000000..0df264719
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/mongo-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/policy.yaml
new file mode 100644
index 000000000..5fdf0f937
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: mongo-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-database-path/creds/*" {
+ capabilities = ["read"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/policybinding.yaml
new file mode 100644
index 000000000..904dd1247
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: mongo-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: mongo-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretengine.yaml
new file mode 100644
index 000000000..7405c5db0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretengine.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: mongo-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mongodb:
+ databaseRef:
+ name: mongodb
+ namespace: demo
+ pluginName: "mongodb-database-plugin"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretenginerole.yaml
new file mode 100644
index 000000000..5133d7669
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretenginerole.yaml
@@ -0,0 +1,12 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MongoDBRole
+metadata:
+ name: mongo-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: mongo-secret-engine
+ creationStatements:
+ - "{ \"db\": \"admin\", \"roles\": [{ \"role\": \"readWrite\" }, {\"role\": \"read\", \"db\": \"foo\"}] }"
+ defaultTTL: 1h
+ maxTTL: 24h
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretproviderclass.yaml
new file mode 100644
index 000000000..3f5c432fe
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.mongo-reader-role"
+ objects: |
+ - objectName: "mongo-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.mongo-superuser-role"
+ secretKey: "username"
+ - objectName: "mongo-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.mongo-superuser-role"
+ secretKey: "password"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretrolebinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretrolebinding.yaml
new file mode 100644
index 000000000..bd727cd2d
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/secretrolebinding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: MongoDBRole
+ name: mongo-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/serviceaccount.yaml
new file mode 100644
index 000000000..ed79c6d5b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mongodb/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/mysql.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/mysql.yaml
new file mode 100644
index 000000000..fb71010f2
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/mysql.yaml
@@ -0,0 +1,16 @@
+apiVersion: kubedb.com/v1alpha2
+kind: MySQL
+metadata:
+ name: mysql
+ namespace: demo
+spec:
+ version: "8.0.36"
+ storageType: Durable
+ storage:
+ storageClassName: "standard"
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/pod.yaml
new file mode 100644
index 000000000..d5676e694
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/mysql-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/policy.yaml
new file mode 100644
index 000000000..a36abbcfd
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: mysql-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-database-path/creds/*" {
+ capabilities = ["read"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/policybinding.yaml
new file mode 100644
index 000000000..84f072981
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: mysql-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: mysql-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secret-role-binding.yaml
new file mode 100644
index 000000000..5e633f311
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: MySQLRole
+ name: mysql-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretengine.yaml
new file mode 100644
index 000000000..4d632e92e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretengine.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: mysql-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mysql:
+ databaseRef:
+ name: mysql
+ namespace: demo
+ pluginName: "mysql-database-plugin"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretenginerole.yaml
new file mode 100644
index 000000000..211cddf9b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretenginerole.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MySQLRole
+metadata:
+ name: mysql-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: sql-secret-engine
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+ defaultTTL: 1h
+ maxTTL: 24h
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretproviderclass.yaml
new file mode 100644
index 000000000..f64c7cf16
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.mysql-reader-role"
+ objects: |
+ - objectName: "mysql-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.mysql-superuser-role"
+ secretKey: "username"
+ - objectName: "mysql-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.mysql-superuser-role"
+ secretKey: "password"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/serviceaccount.yaml
new file mode 100644
index 000000000..ed79c6d5b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/mysql/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/pki/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/pod.yaml
new file mode 100644
index 000000000..29ce4ecfa
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/pki-assets"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/pki/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/policy.yaml
new file mode 100644
index 000000000..5335bc323
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: pki-se-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "pki/issue/*" {
+ capabilities = ["update"]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/pki/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/policybinding.yaml
new file mode 100644
index 000000000..061d8cbe4
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: pki-se-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: pki-se-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/pki/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/secretproviderclass.yaml
new file mode 100644
index 000000000..179bbbb6b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/secretproviderclass.yaml
@@ -0,0 +1,42 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.pki-se-role"
+ objects: |
+ - objectName: "certificate"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "certificate"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+
+ - objectName: "issuing_ca"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "issuing_ca"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+
+ - objectName: "private_key"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "private_key"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+
+ - objectName: "private_key_type"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "private_key_type"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/pki/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/serviceaccount.yaml
new file mode 100644
index 000000000..784a86322
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/pki/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/vaultserver.yaml
new file mode 100644
index 000000000..1017c6396
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/pki/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/pod.yaml
new file mode 100644
index 000000000..924a4e60f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/postgres-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/policy.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/policy.yaml
new file mode 100644
index 000000000..ad3134891
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/policy.yaml
@@ -0,0 +1,12 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: postgres-reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "your-database-path/creds/*" {
+ capabilities = ["read"]
+ }
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/policybinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/policybinding.yaml
new file mode 100644
index 000000000..ce3734e04
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/policybinding.yaml
@@ -0,0 +1,16 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: postgres-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: postgres-reader-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/postgres.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/postgres.yaml
new file mode 100644
index 000000000..d6283e849
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/postgres.yaml
@@ -0,0 +1,16 @@
+apiVersion: kubedb.com/v1alpha2
+kind: Postgres
+metadata:
+ name: postgres
+ namespace: demo
+spec:
+ version: "13.13"
+ storageType: Durable
+ storage:
+ storageClassName: "standard"
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretengine.yaml
new file mode 100644
index 000000000..d55e5aab4
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretengine.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: postgres-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mysql:
+ databaseRef:
+ name: postgres
+ namespace: demo
+ pluginName: "postgresql-database-plugin"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretenginerole.yaml
new file mode 100644
index 000000000..0fe69726b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretenginerole.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: PostgresRole
+metadata:
+ name: postgres-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: pg-secret-engine
+ creationStatements:
+ - "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';"
+ - "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
+ defaultTTL: 1h
+ maxTTL: 24h
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretproviderclass.yaml
new file mode 100644
index 000000000..f1139c413
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretproviderclass.yaml
@@ -0,0 +1,17 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.postgres-reader-role"
+ objects: |
+ - objectName: "postgres-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.postgres-superuser-role"
+ secretKey: "username"
+ - objectName: "postgres-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.postgres-superuser-role"
+ secretKey: "password"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretrolebinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretrolebinding.yaml
new file mode 100644
index 000000000..9805cf1c0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/secretrolebinding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: PostgresRole
+ name: postgres-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/serviceaccount.yaml
new file mode 100644
index 000000000..ed79c6d5b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/vaultserver.yaml
new file mode 100644
index 000000000..52d6a78a0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/postgres/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/pod.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/pod.yaml
new file mode 100644
index 000000000..ec1bf8b27
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/pod.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/redis-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/redis.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/redis.yaml
new file mode 100644
index 000000000..ff388aa45
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/redis.yaml
@@ -0,0 +1,17 @@
+apiVersion: kubedb.com/v1alpha2
+kind: Redis
+metadata:
+ name: redis-standalone
+ namespace: demo
+spec:
+ version: 6.2.14
+ storageType: Durable
+ storage:
+ storageClassName: "standard"
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+ terminationPolicy: WipeOut
+
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/redisaccessrequest.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/redisaccessrequest.yaml
new file mode 100644
index 000000000..dc742d667
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/redisaccessrequest.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: write-read-access-req
+ namespace: demo
+spec:
+ roleRef:
+ kind: RedisRole
+ name: write-read-role
+ subjects:
+ - kind: ServiceAccount
+ name: write-read-user
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secret-role-binding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secret-role-binding.yaml
new file mode 100644
index 000000000..5faf5849e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secret-role-binding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: RedisRole
+ name: write-read-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo⏎
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretengine.yaml
new file mode 100644
index 000000000..aef131581
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretengine.yaml
@@ -0,0 +1,14 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: redis-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ namespace: demo
+ redis:
+ databaseRef:
+ name: redis-standalone
+ namespace: demo
+ pluginName: "redis-database-plugin"
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretenginerole.yaml
new file mode 100644
index 000000000..5b4ceafc0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretenginerole.yaml
@@ -0,0 +1,12 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: RedisRole
+metadata:
+ name: write-read-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: redis-secret-engine
+ creationStatements:
+ - '["~*", "+@read","+@write"]'
+ defaultTTL: 1h
+ maxTTL: 24h
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretproviderclass.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretproviderclass.yaml
new file mode 100644
index 000000000..7b60133fe
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/secretproviderclass.yaml
@@ -0,0 +1,19 @@
+apiVersion: secrets-store.csi.x-k8s.io/v1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: k8s.kubevault.com.demo.srb-demo-secret-role-binding
+ objects: |
+ - objectName: "redis-creds-username"
+ secretPath: "/k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role"
+ #secretPath: "your-database-path/creds/your-role-name"
+ secretKey: "username"
+ - objectName: "redis-creds-password"
+ secretPath: "/k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role"
+ #secretPath: "your-database-path/creds/your-role-name"
+ secretKey: "password"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/serviceaccount.yaml
new file mode 100644
index 000000000..ed79c6d5b
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/redis/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/vaultserver.yaml
new file mode 100644
index 000000000..8f8979e5e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/redis/vaultserver.yaml
@@ -0,0 +1,27 @@
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 3
+ version: 1.10.3
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ secretEngines:
+ - redis
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ terminationPolicy: WipeOut
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secret.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secret.yaml
new file mode 100644
index 000000000..b7b3292b0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secret.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aws-cred
+ namespace: demo
+data:
+ access_key: N2I2bl==
+ secret_key: N2I2bl==
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretaccessrequest.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretaccessrequest.yaml
new file mode 100644
index 000000000..a354e378c
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretaccessrequest.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: aws-cred-req
+ namespace: dev
+spec:
+ roleRef:
+ kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: test
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretengine.yaml
new file mode 100644
index 000000000..ab5dd722f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretengine.yaml
@@ -0,0 +1,14 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: aws-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ aws:
+ credentialSecret: aws-cred
+ region: us-east-1
+ leaseConfig:
+ lease: 1h
+ leaseMax: 1h
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretenginerole.yaml
new file mode 100644
index 000000000..7556f1769
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/secretenginerole.yaml
@@ -0,0 +1,20 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AWSRole
+metadata:
+ name: aws-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: aws-secret-engine
+ credentialType: iam_user
+ policyDocument: |
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "ec2:*",
+ "Resource": "*"
+ }
+ ]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/serviceaccount.yaml
new file mode 100644
index 000000000..66bac1f05
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: test
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/vaultserver.yaml
new file mode 100644
index 000000000..1017c6396
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-access-request/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secret.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secret.yaml
new file mode 100644
index 000000000..b7b3292b0
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secret.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aws-cred
+ namespace: demo
+data:
+ access_key: N2I2bl==
+ secret_key: N2I2bl==
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretengine.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretengine.yaml
new file mode 100644
index 000000000..ab5dd722f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretengine.yaml
@@ -0,0 +1,14 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: aws-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ aws:
+ credentialSecret: aws-cred
+ region: us-east-1
+ leaseConfig:
+ lease: 1h
+ leaseMax: 1h
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretenginerole.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretenginerole.yaml
new file mode 100644
index 000000000..7556f1769
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretenginerole.yaml
@@ -0,0 +1,20 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AWSRole
+metadata:
+ name: aws-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: aws-secret-engine
+ credentialType: iam_user
+ policyDocument: |
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "ec2:*",
+ "Resource": "*"
+ }
+ ]
+ }
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretrolebinding.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretrolebinding.yaml
new file mode 100644
index 000000000..68c03a003
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/secretrolebinding.yaml
@@ -0,0 +1,13 @@
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-r-binding
+ namespace: dev
+spec:
+ roles:
+ - kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/serviceaccount.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/serviceaccount.yaml
new file mode 100644
index 000000000..66bac1f05
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/serviceaccount.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: test
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/vaultserver.yaml
new file mode 100644
index 000000000..1017c6396
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/secret-engines/secret-role-binding/vaultserver.yaml
@@ -0,0 +1,38 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.7.3
+ replicas: 3
+ backend:
+ raft:
+ path: "/vault/data"
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: DoNotTerminate
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/issuer.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/issuer.yaml
new file mode 100644
index 000000000..88017ab5e
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/issuer.yaml
@@ -0,0 +1,8 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: issuer
+ namespace: demo
+spec:
+ ca:
+ secretName: vault-ca
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/new-issuer.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/new-issuer.yaml
new file mode 100644
index 000000000..af1c94465
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/new-issuer.yaml
@@ -0,0 +1,8 @@
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: new-issuer
+ namespace: demo
+spec:
+ ca:
+ secretName: vault-new-ca
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-add-tls.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-add-tls.yaml
new file mode 100644
index 000000000..9ded24c05
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-add-tls.yaml
@@ -0,0 +1,21 @@
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-add-tls
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ issuerRef:
+ name: issuer
+ kind: Issuer
+ apiGroup: "cert-manager.io"
+ certificates:
+ - alias: client
+ subject:
+ organizations:
+ - appscode
+ organizationalUnits:
+ - client
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-change-issuer.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-change-issuer.yaml
new file mode 100644
index 000000000..18e94fec9
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-change-issuer.yaml
@@ -0,0 +1,14 @@
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-change-issuer
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ issuerRef:
+ name: new-issuer
+ kind: Issuer
+ apiGroup: "cert-manager.io"
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-remove.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-remove.yaml
new file mode 100644
index 000000000..053cf91e8
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-remove.yaml
@@ -0,0 +1,11 @@
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-remove
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ remove: true
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-rotate.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-rotate.yaml
new file mode 100644
index 000000000..529e69c1a
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vault-ops-rotate.yaml
@@ -0,0 +1,11 @@
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-rotate
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ rotateCertificates: true
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-ops-request/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vaultserver.yaml
new file mode 100644
index 000000000..79d331f92
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-ops-request/vaultserver.yaml
@@ -0,0 +1,32 @@
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.10.3
+ replicas: 3
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ secretEngines:
+ - gcp
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: WipeOut
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/appBinding.yaml b/content/docs/v2025.11.21/examples/guides/vault-server/appBinding.yaml
new file mode 100644
index 000000000..a2b1f3c00
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/appBinding.yaml
@@ -0,0 +1,17 @@
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ clientConfig:
+ url: https://e2a3839b.ngrok.io
+ insecureSkipTLSVerify: true
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes ## Kubernetes auth is enabled in this path
+ vaultRole: vault-role ## auth-role name against which login will be done
+ kubernetes:
+ serviceAccountName: vault ## service account name
+ usePodServiceAccountForCSIDriver: true ## required while using CSI driver
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/ca.crt b/content/docs/v2025.11.21/examples/guides/vault-server/ca.crt
new file mode 100644
index 000000000..d67be76be
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/ca.crt
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICyDCCAbCgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
+cm5ldGVzMB4XDTE5MTExNDEyMDkxOFoXDTI5MTExMTEyMDkxOFowFTETMBEGA1UE
+AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgc
+UHarPqlczLlcUqNUHHM5yIyuE36S0EjSwqinHmRWcJIM5k+ktYkN6+9OQ+4SiQWf
+cmUlnP7nx+vvL8H122zt6PJ+TZEfw1/qPZ5m3lsFeDtfSjf9tWv4Us/0cd8A2XrV
+O6DlqyUARCN2dI8eUOGcVHblMeZeKQh7zxNVkHainijuPwTQwDnrTMz/zEap9m2G
+upaAlk0fBQUkMB6D/seuL/XcrKKa7Rq5zDotZQBkowMaYfJzVK0Dz0dp4t42V7M2
+rkyRW0RNi96s1WMxxh+HNpK7RvPdXhTH6k5n8ls/qfi493sc1j4v6AQN3dnlRXJi
+jw+vdurYtuATxFND528CAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABXnF+ugf2n4jGEF/H9U2Mnv7s29
+T6C7jrwGE8aIMSxKN5e4/+Xn7EY2c1yxv5Djju6doh8re+pf9ZBgYaUlD3TueuN2
+f5X1kcoQLWlFmMOb+7VNVmttUID9g9Ep6RJo3V2j2ru3jGe3sVLFQFKUFPyAyZV2
+wDAbNZW7PfsUxL3GfxUycOjzs83Y/+Mr9F4m+p9QCGV/fvjix1U9WV7z8dJo3W/i
+p3J1VhQTVUoS/bMoXVKn6tFP5Ns/KSvKJNdvYN7uG1bAqmtLcaLWecImOb1fS/dP
+y67FPCX16KVZtHcngvUDj+eYl81RVay7gVsbIkkOvxVkdWY8DWr32OF0P0A=
+-----END CERTIFICATE-----
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/clusterRoleBinding.yaml b/content/docs/v2025.11.21/examples/guides/vault-server/clusterRoleBinding.yaml
new file mode 100644
index 000000000..d54d58ea9
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/clusterRoleBinding.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: role-tokenreview-binding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: system:auth-delegator
+subjects:
+- kind: ServiceAccount
+ name: token-reviewer
+ namespace: demo
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/secret-policy.yaml b/content/docs/v2025.11.21/examples/guides/vault-server/secret-policy.yaml
new file mode 100644
index 000000000..940152454
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/secret-policy.yaml
@@ -0,0 +1,17 @@
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: custom-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "sys/policy" {
+ capabilities = ["read", "list", "create", "update"]
+ }
+
+ path "sys/policy/*" {
+ capabilities = ["read"]
+ }
+
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/vault.hcl b/content/docs/v2025.11.21/examples/guides/vault-server/vault.hcl
new file mode 100644
index 000000000..1725073c2
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/vault.hcl
@@ -0,0 +1,27 @@
+path "sys/mounts" {
+ capabilities = ["read", "list"]
+}
+path "sys/mounts/*" {
+ capabilities = ["create", "read", "update", "delete"]
+}
+path "sys/leases/revoke/*" {
+ capabilities = ["update"]
+}
+path "sys/policy/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
+path "sys/policy" {
+ capabilities = ["read", "list"]
+}
+path "sys/policies" {
+ capabilities = ["read", "list"]
+}
+path "sys/policies/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
+path "auth/kubernetes/role" {
+ capabilities = ["read", "list"]
+}
+path "auth/kubernetes/role/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/vaultserver.yaml b/content/docs/v2025.11.21/examples/guides/vault-server/vaultserver.yaml
new file mode 100644
index 000000000..c0218c98c
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/vaultserver.yaml
@@ -0,0 +1,23 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.3"
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/guides/vault-server/vaultserverversion.yaml b/content/docs/v2025.11.21/examples/guides/vault-server/vaultserverversion.yaml
new file mode 100644
index 000000000..6d4061a52
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/guides/vault-server/vaultserverversion.yaml
@@ -0,0 +1,12 @@
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.2
+spec:
+ exporter:
+ image: kubevault/vault-exporter:v0.1.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ vault:
+ image: vault:1.2.2
+ version: 1.2.2
diff --git a/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-builtin-conf.yaml b/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-builtin-conf.yaml
new file mode 100644
index 000000000..f133b62d8
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-builtin-conf.yaml
@@ -0,0 +1,102 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: prometheus-config
+ labels:
+ name: prometheus-config
+ namespace: monitoring
+data:
+ prometheus.yml: |-
+ global:
+ scrape_interval: 5s
+ evaluation_interval: 5s
+ scrape_configs:
+ - job_name: 'csi-vault-controller'
+ honor_labels: true
+ kubernetes_sd_configs:
+ - role: endpoints
+ # Kubernetes apiserver serve metrics on a TLS secure endpoints. so, we have to use "https" scheme
+ scheme: https
+ # we have to provide certificate to establish tls secure connection
+ tls_config:
+ ca_file: /etc/prometheus/secret/csi-vault-apiserver-cert/tls.crt
+ server_name: csi-vault-controller.kube-system.svc
+ # bearer_token_file is required for authorizating prometheus server to Kubernetes apiserver
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_label_app]
+ separator: ;
+ regex: csi-vault
+ replacement: $1
+ action: keep
+ - source_labels: [__meta_kubernetes_service_label_component]
+ separator: ;
+ regex: controller
+ replacement: $1
+ action: keep
+ - source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name]
+ separator: ;
+ regex: Node;(.*)
+ target_label: node
+ replacement: ${1}
+ action: replace
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: kube-system;csi-vault-controller;api
+ - separator: ;
+ regex: (.*)
+ target_label: endpoint
+ replacement: api
+ action: replace
+ - source_labels: [__meta_kubernetes_service_name]
+ separator: ;
+ regex: (.*)
+ target_label: job
+ replacement: ${1}
+ action: replace
+
+ - job_name: 'csi-vault-node'
+ honor_labels: true
+ kubernetes_sd_configs:
+ - role: endpoints
+ # Kubernetes apiserver serve metrics on a TLS secure endpoints. so, we have to use "https" scheme
+ scheme: https
+ # we have to provide certificate to establish tls secure connection
+ tls_config:
+ ca_file: /etc/prometheus/secret/csi-vault-apiserver-cert/tls.crt
+ server_name: csi-vault-node.kube-system.svc
+ # bearer_token_file is required for authorizating prometheus server to Kubernetes apiserver
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_label_app]
+ separator: ;
+ regex: csi-vault
+ replacement: $1
+ action: keep
+ - source_labels: [__meta_kubernetes_service_label_component]
+ separator: ;
+ regex: node
+ replacement: $1
+ action: keep
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: kube-system;csi-vault-node;api
+ - source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name]
+ separator: ;
+ regex: Node;(.*)
+ target_label: node
+ replacement: ${1}
+ action: replace
+ - source_labels: [__meta_kubernetes_service_name]
+ separator: ;
+ regex: (.*)
+ target_label: job
+ replacement: ${1}
+ action: replace
+ - separator: ;
+ regex: (.*)
+ target_label: endpoint
+ replacement: api
+ action: replace
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-builtin-deployment.yaml b/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-builtin-deployment.yaml
new file mode 100644
index 000000000..74b246643
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-builtin-deployment.yaml
@@ -0,0 +1,49 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: prometheus-demo
+ name: prometheus
+ namespace: monitoring
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ labels:
+ app: prometheus
+ spec:
+ containers:
+ - args:
+ - --config.file=/etc/prometheus/prometheus.yml
+ - --storage.tsdb.path=/prometheus/
+ image: prom/prometheus:v2.5.0
+ imagePullPolicy: IfNotPresent
+ name: prometheus
+ ports:
+ - containerPort: 9090
+ protocol: TCP
+ volumeMounts:
+ - mountPath: /etc/prometheus/
+ name: prometheus-config
+ - mountPath: /prometheus/
+ name: prometheus-storage
+ - mountPath: /etc/prometheus/secret/csi-vault-apiserver-cert
+ name: csi-vault-apiserver-cert
+ serviceAccountName: prometheus
+ volumes:
+ - configMap:
+ defaultMode: 420
+ name: prometheus-config
+ name: prometheus-config
+ - emptyDir: {}
+ name: prometheus-storage
+ - name: csi-vault-apiserver-cert
+ secret:
+ defaultMode: 420
+ secretName: csi-vault-apiserver-cert
+ items:
+ - path: tls.crt
+ key: tls.crt
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-coreos-crd.yaml b/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-coreos-crd.yaml
new file mode 100644
index 000000000..d963a6256
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/csi-driver/prom-coreos-crd.yaml
@@ -0,0 +1,18 @@
+apiVersion: monitoring.coreos.com/v1
+kind: Prometheus
+metadata:
+ name: prometheus
+ namespace: monitoring
+ labels:
+ k8s-app: prometheus
+spec:
+ replicas: 1
+ serviceAccountName: prometheus
+ serviceMonitorSelector:
+ matchLabels:
+ k8s-app: prometheus
+ secrets:
+ - csi-vault-apiserver-cert
+ resources:
+ requests:
+ memory: 400Mi
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/grafana/dashboard.json b/content/docs/v2025.11.21/examples/monitoring/grafana/dashboard.json
new file mode 100644
index 000000000..35c361b24
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/grafana/dashboard.json
@@ -0,0 +1,3390 @@
+{
+ "__inputs": [
+ {
+ "name": "DS_PROMETHEUS",
+ "label": "Prometheus",
+ "description": "",
+ "type": "datasource",
+ "pluginId": "prometheus",
+ "pluginName": "Prometheus"
+ }
+ ],
+ "__requires": [
+ {
+ "type": "grafana",
+ "id": "grafana",
+ "name": "Grafana",
+ "version": "5.1.0"
+ },
+ {
+ "type": "panel",
+ "id": "graph",
+ "name": "Graph",
+ "version": "5.0.0"
+ },
+ {
+ "type": "datasource",
+ "id": "prometheus",
+ "name": "Prometheus",
+ "version": "5.0.0"
+ },
+ {
+ "type": "panel",
+ "id": "singlestat",
+ "name": "Singlestat",
+ "version": "5.0.0"
+ },
+ {
+ "type": "panel",
+ "id": "table",
+ "name": "Table",
+ "version": "5.0.0"
+ }
+ ],
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": "-- Grafana --",
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "gnetId": null,
+ "graphTooltip": 0,
+ "id": null,
+ "iteration": 1525183847469,
+ "links": [],
+ "panels": [
+ {
+ "cacheTimeout": null,
+ "colorBackground": false,
+ "colorPostfix": false,
+ "colorValue": true,
+ "colors": [
+ "#962d82",
+ "rgb(113, 165, 208)",
+ "#d44a3a"
+ ],
+ "datasource": null,
+ "decimals": null,
+ "format": "none",
+ "gauge": {
+ "maxValue": 100,
+ "minValue": 0,
+ "show": false,
+ "thresholdLabels": false,
+ "thresholdMarkers": true
+ },
+ "gridPos": {
+ "h": 3,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 83,
+ "interval": null,
+ "links": [],
+ "mappingType": 1,
+ "mappingTypes": [
+ {
+ "name": "value to text",
+ "value": 1
+ },
+ {
+ "name": "range to text",
+ "value": 2
+ }
+ ],
+ "maxDataPoints": 100,
+ "nullPointMode": "connected",
+ "nullText": null,
+ "postfix": "",
+ "postfixFontSize": "50%",
+ "prefix": "",
+ "prefixFontSize": "50%",
+ "rangeMaps": [
+ {
+ "from": "null",
+ "text": "N/A",
+ "to": "null"
+ }
+ ],
+ "sparkline": {
+ "fillColor": "rgba(31, 118, 189, 0.18)",
+ "full": false,
+ "lineColor": "rgb(31, 120, 193)",
+ "show": false
+ },
+ "tableColumn": "",
+ "targets": [
+ {
+ "expr": "sum(vault_info) by (vault_cluster, kubernetes_namespace)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Vault Cluser : {{ kubernetes_namespace }}/{{vault_cluster}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": "",
+ "title": "Vault Cluster",
+ "transparent": false,
+ "type": "singlestat",
+ "valueFontSize": "80%",
+ "valueMaps": [
+ {
+ "op": "=",
+ "text": "N/A",
+ "value": "2"
+ }
+ ],
+ "valueName": "name"
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "decimals": 0,
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 3
+ },
+ "id": 69,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "hideEmpty": false,
+ "hideZero": true,
+ "max": false,
+ "min": false,
+ "rightSide": true,
+ "show": true,
+ "sort": null,
+ "sortDesc": null,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "{vault_cluster=\"example\"}",
+ "yaxis": 1
+ }
+ ],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(vault_up) by ( vault_cluster, pod_name, kubernetes_namespace)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ pod_name }}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Up Instances",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": 1
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "decimals": 0,
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 8,
+ "y": 3
+ },
+ "id": 74,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "hideEmpty": false,
+ "hideZero": true,
+ "max": false,
+ "min": false,
+ "rightSide": true,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "{vault_cluster=\"example\"}",
+ "yaxis": 1
+ }
+ ],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(1 - vault_up) by ( vault_cluster, pod_name, kubernetes_namespaces)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ pod_name }}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Down Instances",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": 1
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "decimals": 0,
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 16,
+ "y": 3
+ },
+ "id": 71,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "hideZero": true,
+ "max": false,
+ "min": false,
+ "rightSide": true,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(vault_initialized) by ( vault_cluster, pod_name, kubernetes_namespace)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ pod_name }}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Initialized Instances",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "decimals": 0,
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 10
+ },
+ "id": 75,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "hideZero": true,
+ "max": false,
+ "min": false,
+ "rightSide": true,
+ "show": true,
+ "sort": "current",
+ "sortDesc": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(1 - vault_sealed) by (vault_cluster, pod_name, kubernetes_namespace)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ pod_name }}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Unsealed Instances",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 8,
+ "y": 10
+ },
+ "id": 73,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "hideZero": true,
+ "max": false,
+ "min": false,
+ "rightSide": true,
+ "show": true,
+ "sort": "current",
+ "sortDesc": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(vault_sealed) by (vault_cluster, pod_name)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{pod_name}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Sealed Instances",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 16,
+ "y": 10
+ },
+ "id": 7,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [
+ {
+ "alias": "/.*sys_bytes.*/",
+ "dashes": true,
+ "fill": 0
+ },
+ {
+ "alias": "/.*total_bytes.*/",
+ "fill": 0
+ }
+ ],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "max(vault_runtime_alloc_bytes) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "allocated_bytes : {{ vault_cluster }}",
+ "refId": "A"
+ },
+ {
+ "expr": "max(vault_runtime_sys_bytes) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "system_bytes : {{ vault_cluster }}",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Runtime Memory",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "decbytes",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 0,
+ "y": 17
+ },
+ "id": 67,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "avg(vault_runtime_total_gc_pause_ns / 1000000 ) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{vault_cluster}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "GC Pause Time",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 8,
+ "y": 17
+ },
+ "id": 79,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(rate(vault_route_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{vault_cluster}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "QPS",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 16,
+ "y": 17
+ },
+ "id": 77,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "max(vault_route{quantile=\"0.99\"}) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "99th Percentile : {{vault_cluster}}",
+ "refId": "A"
+ },
+ {
+ "expr": "max(vault_route{quantile=\"0.5\"}) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "50th Percentile : {{vault_cluster}}",
+ "refId": "B"
+ },
+ {
+ "expr": "sum(rate(vault_route_sum[5m])) by (vault_cluster) / sum(rate(vault_route_count[5m])) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Average : {{vault_cluster}}",
+ "refId": "C"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Latency",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "cacheTimeout": null,
+ "colorBackground": false,
+ "colorValue": true,
+ "colors": [
+ "#299c46",
+ "rgba(237, 129, 40, 0.89)",
+ "#d44a3a"
+ ],
+ "datasource": "prom",
+ "format": "none",
+ "gauge": {
+ "maxValue": 100,
+ "minValue": 0,
+ "show": false,
+ "thresholdLabels": false,
+ "thresholdMarkers": true
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 4,
+ "x": 0,
+ "y": 23
+ },
+ "id": 65,
+ "interval": null,
+ "links": [],
+ "mappingType": 1,
+ "mappingTypes": [
+ {
+ "name": "value to text",
+ "value": 1
+ },
+ {
+ "name": "range to text",
+ "value": 2
+ }
+ ],
+ "maxDataPoints": 100,
+ "nullPointMode": "connected",
+ "nullText": null,
+ "postfix": "",
+ "postfixFontSize": "50%",
+ "prefix": "",
+ "prefixFontSize": "50%",
+ "rangeMaps": [
+ {
+ "from": "null",
+ "text": "N/A",
+ "to": "null"
+ }
+ ],
+ "sparkline": {
+ "fillColor": "rgba(31, 118, 189, 0.18)",
+ "full": false,
+ "lineColor": "rgb(31, 120, 193)",
+ "show": true
+ },
+ "tableColumn": "",
+ "targets": [
+ {
+ "expr": "sum(vault_runtime_num_goroutines)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "vault_cluster : {{vault_cluster}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": "1000, 10000",
+ "title": "Goroutines",
+ "type": "singlestat",
+ "valueFontSize": "80%",
+ "valueMaps": [
+ {
+ "op": "=",
+ "text": "N/A",
+ "value": "null"
+ }
+ ],
+ "valueName": "current"
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 10,
+ "x": 4,
+ "y": 23
+ },
+ "id": 62,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": true,
+ "max": true,
+ "min": true,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": false,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(idelta(vault_route_count{method=~\"create|delete|renew\"}[5m])) by (method, path)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ method }} : {{path}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Modify by Path",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 10,
+ "x": 14,
+ "y": 23
+ },
+ "id": 64,
+ "legend": {
+ "alignAsTable": true,
+ "avg": true,
+ "current": false,
+ "max": true,
+ "min": true,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": false,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(idelta(vault_route_count{method=~\"read\"}[5m])) by (method, path)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ method }} : {{path}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Read by Path",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 29
+ },
+ "id": 16,
+ "panels": [],
+ "title": "Token",
+ "type": "row"
+ },
+ {
+ "cacheTimeout": null,
+ "colorBackground": false,
+ "colorValue": true,
+ "colors": [
+ "#299c46",
+ "rgba(237, 129, 40, 0.89)",
+ "#d44a3a"
+ ],
+ "datasource": "prom",
+ "decimals": null,
+ "format": "none",
+ "gauge": {
+ "maxValue": 100,
+ "minValue": 0,
+ "show": false,
+ "thresholdLabels": false,
+ "thresholdMarkers": true
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 4,
+ "x": 0,
+ "y": 30
+ },
+ "id": 8,
+ "interval": null,
+ "links": [],
+ "mappingType": 1,
+ "mappingTypes": [
+ {
+ "name": "value to text",
+ "value": 1
+ },
+ {
+ "name": "range to text",
+ "value": 2
+ }
+ ],
+ "maxDataPoints": 100,
+ "nullPointMode": "connected",
+ "nullText": null,
+ "postfix": "",
+ "postfixFontSize": "50%",
+ "prefix": "",
+ "prefixFontSize": "50%",
+ "rangeMaps": [
+ {
+ "from": "null",
+ "text": "N/A",
+ "to": "null"
+ }
+ ],
+ "sparkline": {
+ "fillColor": "rgba(31, 118, 189, 0.18)",
+ "full": false,
+ "lineColor": "rgb(31, 120, 193)",
+ "show": true
+ },
+ "tableColumn": "",
+ "targets": [
+ {
+ "expr": "vault_token_create_count - vault_token_store_count",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "refId": "A"
+ }
+ ],
+ "thresholds": "1,3",
+ "title": "Pending Tokens",
+ "type": "singlestat",
+ "valueFontSize": "150%",
+ "valueMaps": [
+ {
+ "op": "=",
+ "text": "0",
+ "value": "null"
+ }
+ ],
+ "valueName": "current"
+ },
+ {
+ "aliasColors": {
+ "Lookup": "#0a50a1"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 10,
+ "x": 4,
+ "y": 30
+ },
+ "id": 14,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(rate(vault_token_lookup_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Lookup : {{vault_cluster}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Token Lookup",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "Create": "rgb(84, 183, 90)",
+ "Store": "#0a437c"
+ },
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 10,
+ "x": 14,
+ "y": 30
+ },
+ "id": 6,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": false,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(vault_token_create_count) by (vault_cluster)",
+ "format": "time_series",
+ "instant": false,
+ "intervalFactor": 1,
+ "legendFormat": "Create : {{vault_cluster}}",
+ "refId": "A"
+ },
+ {
+ "expr": "sum(vault_token_store_count) by (vault_cluster)",
+ "format": "time_series",
+ "instant": false,
+ "intervalFactor": 2,
+ "legendFormat": "Store : {{vault_cluster}}",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Token",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 36
+ },
+ "id": 20,
+ "panels": [],
+ "title": "Audit",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 14,
+ "x": 0,
+ "y": 37
+ },
+ "id": 4,
+ "legend": {
+ "alignAsTable": true,
+ "avg": true,
+ "current": true,
+ "hideEmpty": true,
+ "hideZero": false,
+ "max": true,
+ "min": true,
+ "rightSide": true,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(irate(vault_audit_log_request_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "instant": false,
+ "intervalFactor": 1,
+ "legendFormat": "Request : {{vault_cluster}}",
+ "refId": "A"
+ },
+ {
+ "expr": "sum(irate(vault_audit_log_response_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "instant": false,
+ "intervalFactor": 1,
+ "legendFormat": "Response : {{vault_cluster}}",
+ "refId": "B"
+ },
+ {
+ "expr": "sum(irate(vault_core_handle_request_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Handled : {{vault_cluster}}",
+ "refId": "C"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Audit Log Request",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 10,
+ "x": 14,
+ "y": 37
+ },
+ "id": 36,
+ "legend": {
+ "alignAsTable": true,
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "rightSide": true,
+ "show": false,
+ "sort": "avg",
+ "sortDesc": true,
+ "total": false,
+ "values": false
+ },
+ "lines": false,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(idelta(vault_route_count{method=~\"rollback\"}[5m])) by (method, path)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "{{ method }}:{{path}}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Auth Rollback",
+ "tooltip": {
+ "shared": true,
+ "sort": 2,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 43
+ },
+ "id": 18,
+ "panels": [],
+ "title": "Policy",
+ "type": "row"
+ },
+ {
+ "aliasColors": {
+ "set": "#629e51"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 12,
+ "x": 0,
+ "y": 44
+ },
+ "id": 10,
+ "legend": {
+ "alignAsTable": false,
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(rate(vault_policy_set_policy_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "set : {{ vault_cluster }}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Policy Set",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "transparent": false,
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "GET": "#1f78c1"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 12,
+ "x": 12,
+ "y": 44
+ },
+ "id": 12,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(rate(vault_policy_get_policy_count[1m])) by (vault_cluster)",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "get : {{ vault_cluster }}",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Policy Get",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 50
+ },
+ "id": 40,
+ "panels": [],
+ "title": "Database Secret Engine",
+ "type": "row"
+ },
+ {
+ "cacheTimeout": null,
+ "colorBackground": false,
+ "colorValue": true,
+ "colors": [
+ "#299c46",
+ "#7eb26d",
+ "#d44a3a"
+ ],
+ "datasource": null,
+ "format": "none",
+ "gauge": {
+ "maxValue": 100,
+ "minValue": 0,
+ "show": false,
+ "thresholdLabels": false,
+ "thresholdMarkers": true
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 4,
+ "x": 0,
+ "y": 51
+ },
+ "id": 42,
+ "interval": null,
+ "links": [],
+ "mappingType": 1,
+ "mappingTypes": [
+ {
+ "name": "value to text",
+ "value": 1
+ },
+ {
+ "name": "range to text",
+ "value": 2
+ }
+ ],
+ "maxDataPoints": 100,
+ "nullPointMode": "connected",
+ "nullText": null,
+ "postfix": "",
+ "postfixFontSize": "50%",
+ "prefix": "",
+ "prefixFontSize": "50%",
+ "rangeMaps": [
+ {
+ "from": "null",
+ "text": "N/A",
+ "to": "null"
+ }
+ ],
+ "sparkline": {
+ "fillColor": "rgba(31, 118, 189, 0.18)",
+ "full": false,
+ "lineColor": "rgb(31, 120, 193)",
+ "show": false
+ },
+ "tableColumn": "",
+ "targets": [
+ {
+ "expr": "vault_database_initialize_total - vault_database_close_total",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "",
+ "refId": "A"
+ }
+ ],
+ "thresholds": "",
+ "title": "Num of Databases",
+ "type": "singlestat",
+ "valueFontSize": "150%",
+ "valueMaps": [
+ {
+ "op": "=",
+ "text": "0",
+ "value": "null"
+ }
+ ],
+ "valueName": "current"
+ },
+ {
+ "aliasColors": {
+ "create_error": "#629e51"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 4,
+ "y": 51
+ },
+ "id": 46,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_database_initialize_error_total[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "create_error",
+ "refId": "A"
+ },
+ {
+ "expr": "rate(vault_database_close_error_total[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "renew_error",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Database Initialize and Close Error",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "cacheTimeout": null,
+ "colorBackground": false,
+ "colorValue": true,
+ "colors": [
+ "#299c46",
+ "#7eb26d",
+ "#d44a3a"
+ ],
+ "datasource": null,
+ "format": "none",
+ "gauge": {
+ "maxValue": 100,
+ "minValue": 0,
+ "show": false,
+ "thresholdLabels": false,
+ "thresholdMarkers": true
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 4,
+ "x": 12,
+ "y": 51
+ },
+ "id": 45,
+ "interval": null,
+ "links": [],
+ "mappingType": 1,
+ "mappingTypes": [
+ {
+ "name": "value to text",
+ "value": 1
+ },
+ {
+ "name": "range to text",
+ "value": 2
+ }
+ ],
+ "maxDataPoints": 100,
+ "nullPointMode": "connected",
+ "nullText": null,
+ "postfix": "",
+ "postfixFontSize": "50%",
+ "prefix": "",
+ "prefixFontSize": "50%",
+ "rangeMaps": [
+ {
+ "from": "null",
+ "text": "N/A",
+ "to": "null"
+ }
+ ],
+ "sparkline": {
+ "fillColor": "rgba(31, 118, 189, 0.18)",
+ "full": false,
+ "lineColor": "rgb(31, 120, 193)",
+ "show": false
+ },
+ "tableColumn": "",
+ "targets": [
+ {
+ "expr": "vault_database_user_create_total - vault_database_user_revoke_total",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "refId": "A"
+ }
+ ],
+ "thresholds": "",
+ "title": "Active User",
+ "type": "singlestat",
+ "valueFontSize": "150%",
+ "valueMaps": [
+ {
+ "op": "=",
+ "text": "0",
+ "value": "null"
+ }
+ ],
+ "valueName": "current"
+ },
+ {
+ "aliasColors": {
+ "create_error": "#629e51"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": null,
+ "fill": 1,
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 16,
+ "y": 51
+ },
+ "id": 44,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_database_user_create_error_total[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "create_error",
+ "refId": "A"
+ },
+ {
+ "expr": "rate(vault_database_user_renew_error_total[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "renew_error",
+ "refId": "B"
+ },
+ {
+ "expr": "rate(vault_database_user_revoke_error_total[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "revoke_error",
+ "refId": "C"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "User Create, Renew and Revoke Error",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 57
+ },
+ "id": 32,
+ "panels": [],
+ "title": "Google Cloud Storage",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 0,
+ "y": 58
+ },
+ "id": 27,
+ "legend": {
+ "alignAsTable": false,
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "rightSide": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "round(irate(vault_gcs_list_count[10m]))",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "list",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Cloud Storage List",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": false
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "GET": "#1f78c1"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 6,
+ "y": 58
+ },
+ "id": 28,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_gcs_get_count[10m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "GET",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Cloud Storage GET",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "Delete": "#e24d42"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 12,
+ "y": 58
+ },
+ "id": 29,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_gcs_delete_count[10m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Delete",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Cloud Storage Delete",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 18,
+ "y": 58
+ },
+ "id": 30,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "irate(vault_gcs_put_sum[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "PUT",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Cloud Storage PUT",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 63
+ },
+ "id": 54,
+ "panels": [],
+ "title": "Amazon S3",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 0,
+ "y": 64
+ },
+ "id": 47,
+ "legend": {
+ "alignAsTable": false,
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "rightSide": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "round(irate(vault_s3_list_count[10m]))",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "list",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "S3 Storage List",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": false
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "GET": "#1f78c1"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 6,
+ "y": 64
+ },
+ "id": 48,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_s3_get_count[10m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "GET",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "S3 Storage GET",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "Delete": "#e24d42"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 12,
+ "y": 64
+ },
+ "id": 49,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_s3_delete_count[10m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Delete",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "S3 Storage Delete",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 18,
+ "y": 64
+ },
+ "id": 50,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "irate(vault_s3_put_sum[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "PUT",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "S3 Storage PUT",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 69
+ },
+ "id": 56,
+ "panels": [],
+ "title": "Microsoft Azure Storage",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 0,
+ "y": 70
+ },
+ "id": 57,
+ "legend": {
+ "alignAsTable": false,
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "rightSide": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null as zero",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "round(irate(vault_azure_list_count[10m]))",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "list",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Azure Storage List",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": false
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "GET": "#1f78c1"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 6,
+ "y": 70
+ },
+ "id": 58,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_azure_get_count[10m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "GET",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Azure Storage GET",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {
+ "Delete": "#e24d42"
+ },
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 12,
+ "y": 70
+ },
+ "id": 59,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "rate(vault_azure_delete_count[10m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "Delete",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Azure Storage Delete",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "prom",
+ "fill": 1,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 18,
+ "y": 70
+ },
+ "id": 60,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "irate(vault_azure_put_sum[5m])",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "PUT",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Azure Storage PUT",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ }
+ ],
+ "refresh": false,
+ "schemaVersion": 16,
+ "style": "dark",
+ "tags": [],
+ "time": {
+ "from": "now-12h",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ]
+ },
+ "timezone": "",
+ "title": "Vault Cluster Health",
+ "uid": "1HJSjizmkdd",
+ "version": 24
+}
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-builtin-deployment.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-builtin-deployment.yaml
new file mode 100644
index 000000000..24508c5de
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-builtin-deployment.yaml
@@ -0,0 +1,49 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: prometheus-demo
+ name: prometheus
+ namespace: monitoring
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ labels:
+ app: prometheus
+ spec:
+ containers:
+ - args:
+ - --config.file=/etc/prometheus/prometheus.yml
+ - --storage.tsdb.path=/prometheus/
+ image: prom/prometheus:v2.5.0
+ imagePullPolicy: IfNotPresent
+ name: prometheus
+ ports:
+ - containerPort: 9090
+ protocol: TCP
+ volumeMounts:
+ - mountPath: /etc/prometheus/
+ name: prometheus-config
+ - mountPath: /prometheus/
+ name: prometheus-storage
+ - mountPath: /etc/prometheus/secret/vault-operator-apiserver-cert
+ name: vault-operator-apiserver-cert
+ serviceAccountName: prometheus
+ volumes:
+ - configMap:
+ defaultMode: 420
+ name: prometheus-config
+ name: prometheus-config
+ - emptyDir: {}
+ name: prometheus-storage
+ - name: vault-operator-apiserver-cert
+ secret:
+ defaultMode: 420
+ secretName: vault-operator-apiserver-cert
+ items:
+ - path: tls.crt
+ key: tls.crt
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-coreos-crd.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-coreos-crd.yaml
new file mode 100644
index 000000000..db296bc89
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-coreos-crd.yaml
@@ -0,0 +1,18 @@
+apiVersion: monitoring.coreos.com/v1
+kind: Prometheus
+metadata:
+ name: prometheus
+ namespace: monitoring
+ labels:
+ k8s-app: prometheus
+spec:
+ replicas: 1
+ serviceAccountName: prometheus
+ serviceMonitorSelector:
+ matchLabels:
+ k8s-app: prometheus
+ secrets:
+ - vault-operator-apiserver-cert
+ resources:
+ requests:
+ memory: 400Mi
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-server-conf.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-server-conf.yaml
new file mode 100644
index 000000000..4e270fe16
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prom-server-conf.yaml
@@ -0,0 +1,52 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: prometheus-config
+ labels:
+ name: prometheus-config
+ namespace: monitoring
+data:
+ prometheus.yml: |-
+ global:
+ scrape_interval: 5s
+ evaluation_interval: 5s
+ scrape_configs:
+ - job_name: 'vault-apiservers'
+ honor_labels: true
+ kubernetes_sd_configs:
+ - role: endpoints
+ # Kubernetes apiserver serve metrics on a TLS secure endpoints. so, we have to use "https" scheme
+ scheme: https
+ # we have to provide certificate to establish tls secure connection
+ tls_config:
+ ca_file: /etc/prometheus/secret/vault-operator-apiserver-cert/tls.crt
+ server_name: vault-operator.kube-system.svc
+ # bearer_token_file is required for authorizating prometheus server to Kubernetes apiserver
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_label_app]
+ separator: ;
+ regex: vault-operator
+ replacement: $1
+ action: keep
+ - source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name]
+ separator: ;
+ regex: Node;(.*)
+ target_label: node
+ replacement: ${1}
+ action: replace
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: kube-system;vault-operator;api
+ - separator: ;
+ regex: (.*)
+ target_label: endpoint
+ replacement: api
+ action: replace
+ - source_labels: [__meta_kubernetes_service_name]
+ separator: ;
+ regex: (.*)
+ target_label: job
+ replacement: ${1}
+ action: replace
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-builtin.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-builtin.yaml
new file mode 100644
index 000000000..fbe9920cb
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-builtin.yaml
@@ -0,0 +1,100 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: prometheus-server
+rules:
+- apiGroups: [""]
+ resources:
+ - nodes
+ - nodes/proxy
+ - services
+ - endpoints
+ - pods
+ verbs: ["get", "list", "watch"]
+- apiGroups:
+ - extensions
+ resources:
+ - ingresses
+ verbs: ["get", "list", "watch"]
+- nonResourceURLs: ["/metrics"]
+ verbs: ["get"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: prometheus-server
+ namespace: demo
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: prometheus-server
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: prometheus-server
+subjects:
+- kind: ServiceAccount
+ name: prometheus-server
+ namespace: demo
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: prometheus-demo
+ name: prometheus
+ namespace: monitoring
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ labels:
+ app: prometheus
+ spec:
+ containers:
+ - args:
+ - --config.file=/etc/prometheus/prometheus.yml
+ - --storage.tsdb.path=/prometheus/
+ image: prom/prometheus:v2.5.0
+ imagePullPolicy: IfNotPresent
+ name: prometheus
+ ports:
+ - containerPort: 9090
+ protocol: TCP
+ volumeMounts:
+ - mountPath: /etc/prometheus/
+ name: prometheus-config
+ - mountPath: /prometheus/
+ name: prometheus-storage
+ - mountPath: /etc/prometheus/secret/vault-operator-apiserver-cert
+ name: vault-operator-apiserver-cert
+ serviceAccountName: prometheus
+ volumes:
+ - configMap:
+ defaultMode: 420
+ name: prometheus-config
+ name: prometheus-config
+ - emptyDir: {}
+ name: prometheus-storage
+ - name: vault-operator-apiserver-cert
+ secret:
+ defaultMode: 420
+ secretName: vault-operator-apiserver-cert
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus-service
+ namespace: demo
+spec:
+ selector:
+ app: prometheus-server
+ type: NodePort
+ ports:
+ - port: 9090
+ targetPort: 9090
+ nodePort: 30901
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-coreos-operator.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-coreos-operator.yaml
new file mode 100644
index 000000000..036e76a6d
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-coreos-operator.yaml
@@ -0,0 +1,108 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: demo
+spec:
+ finalizers:
+ - kubernetes
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: prometheus-operator
+rules:
+- apiGroups:
+ - extensions
+ resources:
+ - thirdpartyresources
+ verbs:
+ - "*"
+- apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - "*"
+- apiGroups:
+ - monitoring.coreos.com
+ resources:
+ - alertmanagers
+ - prometheuses
+ - servicemonitors
+ verbs:
+ - "*"
+- apiGroups:
+ - apps
+ resources:
+ - statefulsets
+ verbs: ["*"]
+- apiGroups: [""]
+ resources:
+ - configmaps
+ - secrets
+ verbs: ["*"]
+- apiGroups: [""]
+ resources:
+ - pods
+ verbs: ["list", "delete"]
+- apiGroups: [""]
+ resources:
+ - services
+ - endpoints
+ verbs: ["get", "create", "update"]
+- apiGroups: [""]
+ resources:
+ - nodes
+ verbs: ["list", "watch"]
+- apiGroups: [""]
+ resources:
+ - namespaces
+ verbs: ["list"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: prometheus-operator
+ namespace: demo
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: prometheus-operator
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: prometheus-operator
+subjects:
+- kind: ServiceAccount
+ name: prometheus-operator
+ namespace: demo
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: prometheus-operator
+ namespace: demo
+ labels:
+ operator: prometheus
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ labels:
+ operator: prometheus
+ spec:
+ serviceAccountName: prometheus-operator
+ containers:
+ - name: prometheus-operator
+ image: quay.io/coreos/prometheus-operator:v0.16.0
+ resources:
+ requests:
+ cpu: 100m
+ memory: 50Mi
+ limits:
+ cpu: 200m
+ memory: 100Mi
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-coreos.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-coreos.yaml
new file mode 100644
index 000000000..c722424c4
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-coreos.yaml
@@ -0,0 +1,68 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: prometheus
+rules:
+- apiGroups: [""]
+ resources:
+ - nodes
+ - services
+ - endpoints
+ - pods
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources:
+ - configmaps
+ verbs: ["get"]
+- nonResourceURLs: ["/metrics"]
+ verbs: ["get"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: prometheus
+ namespace: demo
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: prometheus
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: prometheus
+subjects:
+- kind: ServiceAccount
+ name: prometheus
+ namespace: demo
+---
+apiVersion: monitoring.coreos.com/v1
+kind: Prometheus
+metadata:
+ name: prometheus
+ namespace: demo
+spec:
+ serviceAccountName: prometheus
+ serviceMonitorSelector:
+ matchLabels:
+ app: vault
+ version: v1.7.0
+ resources:
+ requests:
+ memory: 400Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus
+ namespace: demo
+spec:
+ type: LoadBalancer
+ ports:
+ - name: web
+ nodePort: 30900
+ port: 9090
+ protocol: TCP
+ targetPort: web
+ selector:
+ prometheus: prometheus
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-service.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-service.yaml
new file mode 100644
index 000000000..bf9b1c75f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/prometheus-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus
+ namespace: monitoring
+spec:
+ type: ClusterIP
+ ports:
+ - name: web
+ port: 9090
+ protocol: TCP
+ targetPort: 9090
+ selector:
+ app: prometheus
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/vault-server-builtin.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/vault-server-builtin.yaml
new file mode 100644
index 000000000..ba4610306
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/vault-server-builtin.yaml
@@ -0,0 +1,32 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.2.0
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: "WipeOut"
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-operator/vault-server-coreos.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-operator/vault-server-coreos.yaml
new file mode 100644
index 000000000..067ee6a82
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-operator/vault-server-coreos.yaml
@@ -0,0 +1,32 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.2.0
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: "WipeOut"
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/prom-server-conf.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/prom-server-conf.yaml
new file mode 100644
index 000000000..3b108ad84
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/prom-server-conf.yaml
@@ -0,0 +1,46 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: prometheus-config
+ labels:
+ name: prometheus-config
+ namespace: monitoring
+data:
+ prometheus.yml: |-
+ global:
+ scrape_interval: 5s
+ evaluation_interval: 5s
+ scrape_configs:
+ - job_name: 'kubernetes-service-endpoints'
+
+ kubernetes_sd_configs:
+ - role: endpoints
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
+ action: keep
+ regex: true
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
+ action: replace
+ target_label: __scheme__
+ regex: (https?)
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
+ action: replace
+ target_label: __metrics_path__
+ regex: (.+)
+ - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
+ action: replace
+ target_label: __address__
+ regex: ([^:]+)(?::\d+)?;(\d+)
+ replacement: $1:$2
+ - action: labelmap
+ regex: __meta_kubernetes_service_label_(.+)
+ - source_labels: [__meta_kubernetes_namespace]
+ action: replace
+ target_label: kubernetes_namespace
+ - source_labels: [__meta_kubernetes_service_name]
+ action: replace
+ target_label: kubernetes_name
+ - source_labels: [__meta_kubernetes_pod_name]
+ action: replace
+ target_label: pod_name
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-builtin.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-builtin.yaml
new file mode 100644
index 000000000..41d558137
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-builtin.yaml
@@ -0,0 +1,90 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: prometheus-server
+rules:
+- apiGroups: [""]
+ resources:
+ - nodes
+ - nodes/proxy
+ - services
+ - endpoints
+ - pods
+ verbs: ["get", "list", "watch"]
+- apiGroups:
+ - extensions
+ resources:
+ - ingresses
+ verbs: ["get", "list", "watch"]
+- nonResourceURLs: ["/metrics"]
+ verbs: ["get"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: prometheus-server
+ namespace: demo
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: prometheus-server
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: prometheus-server
+subjects:
+- kind: ServiceAccount
+ name: prometheus-server
+ namespace: demo
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: prometheus-server
+ namespace: demo
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus-server
+ template:
+ metadata:
+ labels:
+ app: prometheus-server
+ spec:
+ serviceAccountName: prometheus-server
+ containers:
+ - name: prometheus
+ image: prom/prometheus:v2.1.0
+ args:
+ - "--config.file=/etc/prometheus/prometheus.yml"
+ - "--storage.tsdb.path=/prometheus/"
+ ports:
+ - containerPort: 9090
+ volumeMounts:
+ - name: prometheus-config-volume
+ mountPath: /etc/prometheus/
+ - name: prometheus-storage-volume
+ mountPath: /prometheus/
+ volumes:
+ - name: prometheus-config-volume
+ configMap:
+ defaultMode: 420
+ name: prometheus-server-conf
+ - name: prometheus-storage-volume
+ emptyDir: {}
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus-service
+ namespace: demo
+spec:
+ selector:
+ app: prometheus-server
+ type: NodePort
+ ports:
+ - port: 9090
+ targetPort: 9090
+ nodePort: 30901
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-coreos-operator.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-coreos-operator.yaml
new file mode 100644
index 000000000..036e76a6d
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-coreos-operator.yaml
@@ -0,0 +1,108 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: demo
+spec:
+ finalizers:
+ - kubernetes
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: prometheus-operator
+rules:
+- apiGroups:
+ - extensions
+ resources:
+ - thirdpartyresources
+ verbs:
+ - "*"
+- apiGroups:
+ - apiextensions.k8s.io
+ resources:
+ - customresourcedefinitions
+ verbs:
+ - "*"
+- apiGroups:
+ - monitoring.coreos.com
+ resources:
+ - alertmanagers
+ - prometheuses
+ - servicemonitors
+ verbs:
+ - "*"
+- apiGroups:
+ - apps
+ resources:
+ - statefulsets
+ verbs: ["*"]
+- apiGroups: [""]
+ resources:
+ - configmaps
+ - secrets
+ verbs: ["*"]
+- apiGroups: [""]
+ resources:
+ - pods
+ verbs: ["list", "delete"]
+- apiGroups: [""]
+ resources:
+ - services
+ - endpoints
+ verbs: ["get", "create", "update"]
+- apiGroups: [""]
+ resources:
+ - nodes
+ verbs: ["list", "watch"]
+- apiGroups: [""]
+ resources:
+ - namespaces
+ verbs: ["list"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: prometheus-operator
+ namespace: demo
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: prometheus-operator
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: prometheus-operator
+subjects:
+- kind: ServiceAccount
+ name: prometheus-operator
+ namespace: demo
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: prometheus-operator
+ namespace: demo
+ labels:
+ operator: prometheus
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ labels:
+ operator: prometheus
+ spec:
+ serviceAccountName: prometheus-operator
+ containers:
+ - name: prometheus-operator
+ image: quay.io/coreos/prometheus-operator:v0.16.0
+ resources:
+ requests:
+ cpu: 100m
+ memory: 50Mi
+ limits:
+ cpu: 200m
+ memory: 100Mi
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-coreos.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-coreos.yaml
new file mode 100644
index 000000000..c722424c4
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-coreos.yaml
@@ -0,0 +1,68 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ name: prometheus
+rules:
+- apiGroups: [""]
+ resources:
+ - nodes
+ - services
+ - endpoints
+ - pods
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources:
+ - configmaps
+ verbs: ["get"]
+- nonResourceURLs: ["/metrics"]
+ verbs: ["get"]
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: prometheus
+ namespace: demo
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: prometheus
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: prometheus
+subjects:
+- kind: ServiceAccount
+ name: prometheus
+ namespace: demo
+---
+apiVersion: monitoring.coreos.com/v1
+kind: Prometheus
+metadata:
+ name: prometheus
+ namespace: demo
+spec:
+ serviceAccountName: prometheus
+ serviceMonitorSelector:
+ matchLabels:
+ app: vault
+ version: v1.7.0
+ resources:
+ requests:
+ memory: 400Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus
+ namespace: demo
+spec:
+ type: LoadBalancer
+ ports:
+ - name: web
+ nodePort: 30900
+ port: 9090
+ protocol: TCP
+ targetPort: web
+ selector:
+ prometheus: prometheus
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-service.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-service.yaml
new file mode 100644
index 000000000..bf9b1c75f
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/prometheus-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus
+ namespace: monitoring
+spec:
+ type: ClusterIP
+ ports:
+ - name: web
+ port: 9090
+ protocol: TCP
+ targetPort: 9090
+ selector:
+ app: prometheus
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/vault-server-builtin.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/vault-server-builtin.yaml
new file mode 100644
index 000000000..067ee6a82
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/vault-server-builtin.yaml
@@ -0,0 +1,32 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.2.0
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: "WipeOut"
diff --git a/content/docs/v2025.11.21/examples/monitoring/vault-server/vault-server-coreos.yaml b/content/docs/v2025.11.21/examples/monitoring/vault-server/vault-server-coreos.yaml
new file mode 100644
index 000000000..067ee6a82
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/monitoring/vault-server/vault-server-coreos.yaml
@@ -0,0 +1,32 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.2.0
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: "WipeOut"
diff --git a/content/docs/v2025.11.21/examples/vaultserver_inmem_k8s_unsealer.yaml b/content/docs/v2025.11.21/examples/vaultserver_inmem_k8s_unsealer.yaml
new file mode 100644
index 000000000..c88fca894
--- /dev/null
+++ b/content/docs/v2025.11.21/examples/vaultserver_inmem_k8s_unsealer.yaml
@@ -0,0 +1,16 @@
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: example
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
diff --git a/content/docs/v2025.11.21/guides/README.md b/content/docs/v2025.11.21/guides/README.md
new file mode 100644
index 000000000..baa647188
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/README.md
@@ -0,0 +1,59 @@
+---
+title: Table of Contents | Guides
+description: Table of Contents | Guides
+menu:
+ docs_v2025.11.21:
+ identifier: guides-readme
+ name: Readme
+ parent: guides
+ weight: -1
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+url: /docs/v2025.11.21/guides/
+aliases:
+- /docs/v2025.11.21/guides/README/
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Guides
+
+Guides show you how to perform tasks with KubeVault operator and Vault CSI driver.
+
+## Using KubeVault operator
+
+- To deploy Vault in AWS EKS see [here](/docs/v2025.11.21/guides/platforms/eks).
+- To deploy Vault in Google GKE see [here](/docs/v2025.11.21/guides/platforms/gke).
+- To deploy Vault in Azure AKS see [here](/docs/v2025.11.21/guides/platforms/aks).
+- To manage Vault policy see [here](/docs/v2025.11.21/guides/policy-management/overview).
+- To manage Vault AWS secret engine see [here](/docs/v2025.11.21/guides/secret-engines/aws/overview).
+- To manage Vault GCP secret engine see [here](/docs/v2025.11.21/guides/secret-engines/gcp/overview).
+- To manage Vault Azure secret engine see [here](/docs/v2025.11.21/guides/secret-engines/azure/overview).
+- To manage Vault MongoDB Database secret engine] see [here](/docs/v2025.11.21/guides/secret-engines/mongodb/overview).
+- To manage Vault MySQL Database secret engine see [here](/docs/v2025.11.21/guides/secret-engines/mysql/overview).
+- To manage Vault PostgreSQL Database secret engine see [here](/docs/v2025.11.21/guides/secret-engines/postgres/overview).
+- To manage Vault Elasticsearch Database secret engine see [here](/docs/v2025.11.21/guides/secret-engines/elasticsearch/overview).
+- To manage Vault MariaDB Database secret engine see [here](/docs/v2025.11.21/guides/secret-engines/mariadb/overview).
+- To manage Vault Redis Database secret engine see [here](/docs/v2025.11.21/guides/secret-engines/redis/overview).
+- To set up monitoring see [here](/docs/v2025.11.21/guides/monitoring/overview).
+- To use KubeVault operator for external Vault see [here](/docs/v2025.11.21/guides/platforms/external-vault).
+- To use KubeVault operator in multiple cluster for same Vault see [here](/docs/v2025.11.21/guides/platforms/multi-cluster-vault).
+
+## Using Vault CSI driver
+
+- To mount Azure secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/azure/csi-driver).
+- To mount AWS secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/aws/csi-driver).
+- To mount GCP secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/gcp/csi-driver).
+- To mount KV secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/kv/csi-driver).
+- To mount MongoDB Database secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/mongodb/csi-driver).
+- To mount MySQL Database secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/mysql/csi-driver).
+- To mount PostgreSQL Database secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/postgres/csi-driver).
+- To mount Elasticsearch Database secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/elasticsearch/csi-driver).
+- To mount MariaDB Database secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/mariadb/csi-driver).
+- To mount Redis Database secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/redis/csi-driver).
+- To mount PKI secret engine secret in pod see [here](/docs/v2025.11.21/guides/secret-engines/pki/csi-driver).
+- To set up monitoring see [here](/docs/v2025.11.21/guides/monitoring/overview).
diff --git a/content/docs/v2025.11.21/guides/_index.md b/content/docs/v2025.11.21/guides/_index.md
new file mode 100755
index 000000000..c5a334523
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/_index.md
@@ -0,0 +1,16 @@
+---
+title: Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: guides
+ name: Guides
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/backup-restore/_index.md b/content/docs/v2025.11.21/guides/backup-restore/_index.md
new file mode 100644
index 000000000..b2adfee12
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/backup-restore/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Backup Restore Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: backup-restore-guides
+ name: Backup & Restore (Stash)
+ parent: guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/backup-restore/backup.md b/content/docs/v2025.11.21/guides/backup-restore/backup.md
new file mode 100644
index 000000000..967c40c8c
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/backup-restore/backup.md
@@ -0,0 +1,371 @@
+---
+title: Vault Backup Restore Overview
+menu:
+ docs_v2025.11.21:
+ identifier: backup-backup-restore-guides
+ name: Backup
+ parent: backup-restore-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Backup Vault Cluster using Stash
+
+This guide will show you how you can take backup of your Vault cluster with Stash.
+
+## Before You Begin
+
+- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.
+- Install KubeVault in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+- Install Stash in your cluster following the steps [here](https://stash.run/docs/latest/setup).
+- Install Stash `kubectl` plugin following the steps [here](https://stash.run/docs/latest/setup/install/kubectl-plugin/).
+- If you are not familiar with how Stash backup and restore Vault cluster, please check the following concept section [here](/docs/v2025.11.21/concepts/backup-restore/overview).
+
+You have to be familiar with following custom resources:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/appbinding)
+- [Function](https://stash.run/docs/latest/concepts/crds/function/)
+- [Task](https://stash.run/docs/latest/concepts/crds/task/)
+- [BackupConfiguration](https://stash.run/docs/latest/concepts/crds/backupconfiguration/)
+- [RestoreSession](https://stash.run/docs/latest/concepts/crds/restoresession/)
+
+
+## Deploy Vault using KubeVault
+
+To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+````bash
+# create demo namespace
+$ kubectl create ns demo
+namespace/demo created
+````
+
+We're going to use Kubernetes secret to store the unseal-keys & root-token. A sample `VaultServer` manifest file may look like this:
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.10.3
+ replicas: 3
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: WipeOut
+```
+
+Now, let's deploy the `VaultServer`:
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/backup-restore/vaultserver.yaml
+vaultserver.kubevault.com/vault created
+```
+
+`KubeVault` operator will create a `AppBinding` CRD on `VaultServer` deployment, which contains the necessary information
+to take backup of the Vault instances. It'll have the same name & be created on the same namespace as the `Vault`.
+Read more about `AppBinding` [here](/docs/v2025.11.21/concepts/vault-server-crds/appbinding).
+
+```bash
+$ kubectl get appbinding -n demo vault -oyaml
+```
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ appRef:
+ apiGroup: kubevault.com
+ kind: VaultServer
+ name: vault
+ namespace: demo
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ backend: raft
+ backupTokenSecretRef:
+ name: vault-backup-token
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ unsealer:
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ secretShares: 5
+ secretThreshold: 3
+ vaultRole: vault-policy-controller
+```
+
+Now, let's wait until all the vault pods come up & `VaultServer` phase becomes `Ready`.
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+vault-0 2/2 Running 0 2m8s
+vault-1 2/2 Running 0 91s
+vault-2 2/2 Running 0 65s
+```
+
+```bash
+$ kubectl get vaultserver -n demo
+NAME REPLICAS VERSION STATUS AGE
+vault 3 1.10.3 Ready 2m50s
+```
+
+At this stage, we've successfully deployed `Vault` using `KubeVault` operator & ready for taking `Backup`.
+
+Before, taking the backup, let's write some data in a `KV` secret engine. Let's export the necessary environment variables & port-forward from `vault` service
+or exec into the vault pod in order to interact with it.
+
+```bash
+$ export VAULT_TOKEN=(kubectl vault root-token get vaultserver vault -n demo --value-only)
+$ export VAULT_ADDR='http://127.0.0.1:8200'
+$ kubectl port-forward -n demo svc/vault 8200
+```
+
+We can see the currently enabled list of secret engines.
+
+```bash
+$ vault secrets list
+Path Type Accessor Description
+---- ---- -------- -----------
+cubbyhole/ cubbyhole cubbyhole_bb7c56f9 per-token private secret storage
+identity/ identity identity_fa8431fa identity store
+k8s.kubevault.com.kv.demo.vault-health/ kv kv_5129d194 n/a
+sys/ system system_c7e0879a system endpoints used for control, policy and debugging
+```
+
+Let's enable a `KV` type secret engine:
+
+```bash
+$ vault secrets enable kv
+Success! Enabled the kv secrets engine at: kv/
+```
+
+Write some dummy data in the secret engine path:
+
+```bash
+$ vault kv put kv/name name=appscode
+Success! Data written to: kv/name
+```
+
+Verify data written in `KV` secret engine:
+
+```bash
+$ vault kv get kv/name
+==== Data ====
+Key Value
+--- -----
+name appscode
+```
+
+### Prepare Backend
+
+We are going to store our backed up data into a GCS bucket. We have to create a Secret with necessary credentials and a Repository crd to use this backend. If you want to use a different backend,
+please read the respective backend configuration doc from [here](https://stash.run/docs/v2022.12.11/guides/backends/overview/).
+
+#### Create Secret
+
+Let’s create a secret called `gcs-secret` with access credentials to our desired GCS bucket,
+
+```bash
+$ echo -n 'restic-pass' > RESTIC_PASSWORD
+$ echo -n 'project-id' > GOOGLE_PROJECT_ID
+$ cat sa.json > GOOGLE_SERVICE_ACCOUNT_JSON_KEY
+
+$ kubectl create secret generic -n demo gcs-secret \
+ --from-file=./RESTIC_PASSWORD \
+ --from-file=./GOOGLE_PROJECT_ID \
+ --from-file=./GOOGLE_SERVICE_ACCOUNT_JSON_KEY
+```
+
+Now, we are ready to backup our workload’s data to our desired backend.
+
+#### Create Repository
+
+Now, create a `Repository` using this secret. Below is the YAML of Repository crd we are going to create,
+
+```yaml
+apiVersion: stash.appscode.com/v1alpha1
+kind: Repository
+metadata:
+ name: gcp-demo-repo
+ namespace: demo
+spec:
+ backend:
+ gcs:
+ bucket: stash-testing
+ prefix: demo-vault
+ storageSecretName: repository-creds
+ usagePolicy:
+ allowedNamespaces:
+ from: Same
+ wipeOut: false
+```
+
+```bash
+$ kbuectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/backup-restore/repository.yaml
+```
+
+Now, we are ready to backup our sample data into this backend.
+
+### Backup
+
+We have to create a BackupConfiguration crd targeting the stash-demo StatefulSet that we have deployed earlier.
+Stash will inject a sidecar container into the target. It will also create a CronJob to take periodic
+backup of /source/data directory of the target.
+
+#### Create BackupConfiguration
+
+Below is the YAML of the BackupConfiguration crd that we are going to create,
+
+```yaml
+apiVersion: stash.appscode.com/v1beta1
+kind: BackupConfiguration
+metadata:
+ name: demo-backup
+ namespace: demo
+spec:
+ driver: Restic
+ repository:
+ name: gcp-demo-repo
+ namespace: demo
+ schedule: "*/5 * * * *"
+ timeOut: 2h
+ target:
+ ref:
+ apiVersion: appcatalog.appscode.com/v1alpha1
+ kind: AppBinding
+ name: vault
+ runtimeSettings:
+ container:
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ retentionPolicy:
+ name: 'keep-last-5'
+ keepLast: 5
+ prune: true
+```
+
+Here,
+- `spec.repository` refers to the Repository object gcs-repo that holds backend information.
+- `spec.schedule` is a cron expression that indicates `BackupSession` will be created at 5 minute interval.
+- `spec.target.ref` refers to the `AppBinding` of the `VaultServer`.
+
+Let’s create the BackupConfiguration crd we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/backup-restore/backup-configuration.yaml
+```
+
+#### Verify Backup Setup Successful
+
+If everything goes well, the phase of the BackupConfiguration should be Ready.
+The Ready phase indicates that the backup setup is successful. Let’s verify the Phase of the
+BackupConfiguration,
+
+```bash
+$ kubectl get backupconfiguration -n demo
+
+NAME TASK SCHEDULE PAUSED PHASE AGE
+demo-backup vault-backup-1.10.3 */5 * * * * true Ready 92m
+
+```
+
+#### Verify Cronjob
+
+```bash
+$ kubectl get cronjob -n demo
+
+NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
+stash-trigger--demo-backup */5 * * * * True 0 93m
+```
+
+#### Wait for BackupSession
+
+The demo-backup CronJob will trigger a backup on each scheduled slot by creating a BackupSession crd.
+The sidecar container watches for the BackupSession crd. When it finds one, it will take backup immediately.
+
+Wait for the next schedule for backup. Run the following command to watch BackupSession crd,
+
+```bash
+kubectl get backupsession -n demo
+
+NAME INVOKER-TYPE INVOKER-NAME PHASE DURATION AGE
+demo-backup-s2kwg BackupConfiguration demo-backup Succeeded 39s 58s
+```
+
+#### Verify Backup
+
+Once a backup is complete, Stash will update the respective Repository crd to reflect the backup.
+Check that the repository gcs-repo has been updated by the following command,
+
+```bash
+kubectl get repository -n demo
+
+NAME INTEGRITY SIZE SNAPSHOT-COUNT LAST-SUCCESSFUL-BACKUP AGE
+gcp-demo-repo true 75.867 KiB 1 11m 11m
+```
+
+
+Now, if we navigate to the GCS bucket, we are going to see backed up data is uploaded successfully:
+
+
+
+ Fig: Vault Backup
+
+
+
+Up next:
+- Read about step-by-step Restore procedure [here](/docs/v2025.11.21/guides/backup-restore/restore)
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/backup-restore/overview.md b/content/docs/v2025.11.21/guides/backup-restore/overview.md
new file mode 100644
index 000000000..53752e460
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/backup-restore/overview.md
@@ -0,0 +1,201 @@
+---
+title: Vault Backup Restore Overview
+menu:
+ docs_v2025.11.21:
+ identifier: overview-backup-restore-guides
+ name: Overview
+ parent: backup-restore-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Vault Backup Restore Overview
+
+`Vault` provides a set of standard operating procedures `(SOP)` for backing up a Vault cluster. It protects your Vault cluster
+against data corruption or sabotage of which Disaster Recovery Replication might not be able to protect against.
+
+`KubeVault` supports number of different [Storage Backend](/docs/v2025.11.21/concepts/vault-server-crds/storage/overview) types. Therefore, the exact steps to backup Vault will depend on your
+selected storage backend. The two recommended storage backend types are Consul and Integrated Storage
+(also known as Raft).
+
+`KubeVault` currently supports Backup & Restore for `Raft` storage backend. So, this document assumes that `Raft` storage backend is being used.
+
+## Backup & Restore process for Raft
+
+Your `VaultServer` must be in `Ready` state for Backup & Restore process to work. This will take the snapshot
+using a consistent mode that forwards the request to the cluster leader, and the leader will verify it is still
+in power before taking the snapshot.
+
+A simple `VaultServer` YAML with `Raft` storage backend may look like this:
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.10.3
+ replicas: 3
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ terminationPolicy: WipeOut
+```
+
+Let's take a look at some relevant fields:
+
+`spec.backend` contains the Backend storage information, `Raft` in this case:
+
+```yaml
+backend:
+ raft:
+ storage:
+ resources:
+ requests:
+ storage: 1Gi
+ storageClassName: standard
+```
+
+`spec.unsealer` contains `VaultServer` unsealing option. In this case which is `Kubernetes` Secret. So, on Vault deployment
+a Secret will be created on the same namespace, which will create the Vault unseal-keys & root-token.
+
+```yaml
+unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+```
+
+`KubeVault` operator will create an `AppBinding` with all the necessary information for backup & restore.
+`AppBinding` has the information about the Unsealer option of the `VaultServer`. During the Backup,
+Vault `unseal-keys` & `root-token` will also be backed-up for the completeness of the Backup process.
+
+`KubeVault` created `AppBinding` YAML may look like this:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ appRef:
+ apiGroup: kubevault.com
+ kind: VaultServer
+ name: vault
+ namespace: demo
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ backend: raft
+ backupTokenSecretRef:
+ name: vault-backup-token
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ unsealer:
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ secretShares: 5
+ secretThreshold: 3
+ vaultRole: vault-policy-controller
+```
+
+Read more about `AppBinding` [here](/docs/v2025.11.21/concepts/vault-server-crds/appbinding).
+
+Here:
+- `spec.parameters.stash` section contains the stash parameters for Backup & Restore tasks.
+- `spec.parameters.stash.addon` contains the information about the `Task` for backup & restore.
+It also contains the `params` which indicates the `keyPrefix` that is prepended with the name of vault `unseal-keys` & `root-token`, e.g. `k8s.kubevault.com.demo.vault-root-token`,
+`k8s.kubevault.com.demo.vault-root-token-unseal-key-0`, `k8s.kubevault.com.demo.vault-root-token-unseal-key-1`, etc.
+
+```yaml
+stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+```
+
+
+`KubeVault` operator will create a `K8s Secret` containing a `token` during the Vault deployment, which contains the necessary permission
+for the Backup & Restore process. This information is available in the `AppBinding` created by the operator. AppBinding
+`spec.parameters.backupTokenSecretRef` contains the reference of that secret.
+
+```yaml
+spec:
+ parameters:
+ backupTokenSecretRef:
+ name: vault-backup-token
+
+```
+
+A sample policy document / permission may look like this:
+
+```hcl
+path "sys/storage/raft/snapshot" {
+ capabilities = ["read"]
+}
+
+path "sys/storage/raft/snapshot-force" {
+ capabilities = ["read"]
+}
+```
+
+If your `Vault` deployment isn't managed by `KubeVault`, then you'll need to create the `AppBinding` & `Secret` containing
+the permissions required for backup & restore separately.
+
+Up next:
+- Read about step-by-step Backup procedure [here](/docs/v2025.11.21/guides/backup-restore/backup)
+- Read about step-by-step Restore procedure [here](/docs/v2025.11.21/guides/backup-restore/restore)
+
diff --git a/content/docs/v2025.11.21/guides/backup-restore/restore.md b/content/docs/v2025.11.21/guides/backup-restore/restore.md
new file mode 100644
index 000000000..b585b4e6a
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/backup-restore/restore.md
@@ -0,0 +1,188 @@
+---
+title: Vault Backup Restore Overview
+menu:
+ docs_v2025.11.21:
+ identifier: restore-backup-restore-guides
+ name: Restore
+ parent: backup-restore-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Restore Vault Cluster using Stash
+
+This guide will show you how you can restore your Vault cluster with Stash.
+
+## Before You Begin
+
+- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube.
+- Install KubeVault in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+- Install Stash in your cluster following the steps [here](https://stash.run/docs/latest/setup/).
+- Install Stash `kubectl` plugin following the steps [here](https://stash.run/docs/latest/setup/install/kubectl-plugin/).
+- If you are not familiar with how Stash backup and restore Vault cluster, please check the following concept section [here](/docs/v2025.11.21/concepts/backup-restore/overview).
+
+You have to be familiar with following custom resources:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/appbinding)
+- [Function](https://stash.run/docs/latest/concepts/crds/function/)
+- [Task](https://stash.run/docs/latest/concepts/crds/task/)
+- [BackupConfiguration](https://stash.run/docs/latest/concepts/crds/backupconfiguration/)
+- [RestoreSession](https://stash.run/docs/latest/concepts/crds/restoresession/)
+
+You may restore a Vault snapshot into the same Vault cluster from which snapshot was taken or into a
+completely new Vault deployment.
+
+### Restore Snapshot for same Vault
+
+Follow this guideline, if you want to restore a snapshot into the same Vault cluster.
+Vault cluster must be `Initialized` & `Unsealed` before trying to restore the snapshot.
+
+Then, simply you can create a `RestoreSession` to restore the snapshot. A sample `RestoreSession` YAML may look like this:
+
+```yaml
+apiVersion: stash.appscode.com/v1beta1
+kind: RestoreSession
+metadata:
+ name: vault-restore-session
+ namespace: demo
+spec:
+ repository:
+ name: gcp-demo-repo
+ target:
+ ref:
+ apiVersion: appcatalog.appscode.com/v1alpha1
+ kind: AppBinding
+ name: vault
+ runtimeSettings:
+ container:
+ securityContext:
+ runAsUser: 0
+ runAsGroup: 0
+ rules:
+ - snapshots: [latest]
+
+```
+
+#### Create RestoreSession
+
+Create the `RestoreSession` for restore the snapshot:
+
+```yaml
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/backup-restore/restore-session.yaml
+```
+
+Now, wait for `RestoreSession` to succeed:
+
+```bash
+$ kubectl get restoresession -n demo
+
+NAME REPOSITORY PHASE DURATION AGE
+vault-restore-session gcp-demo-repo Succeeded 19s 27s
+
+```
+
+Once the `RestoreSession` is Succeeded, snapshot will be successfully restored into the Vault cluster.
+
+### Restore Snapshot for different Vault
+
+Follow this guideline, if you want to restore a snapshot into a different Vault cluster.
+
+You need to deploy the new `Vault` cluster & it must be `Initialized` & `Unsealed`. This `Vault` has a
+completely different set of `unseal keys` & `root token` from the `Vault` from which the snapshot was taken.
+
+`Vault` snapshot carries the signature of `unseal keys`. So, we need to restore the snapshot forcefully & to bypass
+this, we need to modify our restore `function` accordingly. A `Function` CRD may look like this:
+
+```yaml
+apiVersion: stash.appscode.com/v1beta1
+kind: Function
+metadata:
+ name: vault-restore-1.10.3
+spec:
+ args:
+ - restore-vault
+ - --provider=${REPOSITORY_PROVIDER:=}
+ - --bucket=${REPOSITORY_BUCKET:=}
+ - --endpoint=${REPOSITORY_ENDPOINT:=}
+ - --region=${REPOSITORY_REGION:=}
+ - --path=${REPOSITORY_PREFIX:=}
+ - --storage-secret-name=${REPOSITORY_SECRET_NAME:=}
+ - --storage-secret-namespace=${REPOSITORY_SECRET_NAMESPACE:=}
+ - --scratch-dir=/tmp
+ - --enable-cache=${ENABLE_CACHE:=true}
+ - --max-connections=${MAX_CONNECTIONS:=0}
+ - --wait-timeout=${waitTimeout:=300}
+ - --hostname=${HOSTNAME:=}
+ - --source-hostname=${SOURCE_HOSTNAME:=}
+ - --interim-data-dir=${INTERIM_DATA_DIR}
+ - --namespace=${NAMESPACE:=default}
+ - --appbinding=${TARGET_NAME:=}
+ - --appbinding-namespace=${TARGET_NAMESPACE:=}
+ - --snapshot=${RESTORE_SNAPSHOTS:=}
+ - --vault-args=${args:=}
+ - --output-dir=${outputDir:=}
+ - --license-apiservice=${LICENSE_APISERVICE:=}
+ - --force=${force:=false}
+ - --key-prefix=${keyPrefix:=}
+ - --old-key-prefix=${oldKeyPrefix:=}
+ image: stashed/stash-vault:1.10.3
+```
+
+Let's take a look at some of the more relevant flags, that we can set to override the existing flags:
+
+```bash
+- --force=${force:=false}
+- --key-prefix=${keyPrefix:=}
+- --old-key-prefix=${oldKeyPrefix:=}
+```
+
+By default, the `--force` flag is `false`, so in order to restoring the snapshot into a differnt Vault cluster,
+this must be set to `true`.
+
+Moreover, once the snapshot will be restored, the newly `Vault` will be expecting the older `unseal keys` to unseal itself &
+the new `unseal keys` will not be required/valid anymore. So, we'll also migrate the older `unseal keys` & `root token` in place of
+the new `unseal keys` & `root token`.
+
+Since, `Stash` will also take backup of the Vault `unseal keys` & `root token` along with the snapshot, we can get the
+older `unseal keys` & `root token`. To correctly get those, we must set the `--old-key-prefix` flag properly.
+
+```bash
+- --force=${force:=true}
+- --key-prefix=${keyPrefix:=}
+- --old-key-prefix=${oldKeyPrefix:=}
+```
+
+`KeyPrefix` will be generated by the following structure by `KubeVault` operator:
+`k8s.{kubevault.com or cluster UID}.{vault-namespace}.{vault-name}`. In case of Vault deployment using Vault Helm-chart
+or if you want to save it with a different prefix, you need to override the `KeyPrefix` section.
+
+The default `key-prefix`, associated `Task` for `Backup` & `Restore` can be found in the Vault `AppBinding` YAML:
+
+```yaml
+stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+
+```
+
+Now, we need to apply the changes in our restore `Function` CRD. Now, we can create the `RestoreSession`
+to restore the Vault cluster by the similar way mentioned above.
+
+Up next:
+- Read about step-by-step Backup procedure [here](/docs/v2025.11.21/guides/backup-restore/backup)
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/monitoring/_index.md b/content/docs/v2025.11.21/guides/monitoring/_index.md
new file mode 100644
index 000000000..b127b6531
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/_index.md
@@ -0,0 +1,17 @@
+---
+title: Guides Monitoring
+menu:
+ docs_v2025.11.21:
+ identifier: monitoring-guides
+ name: Monitoring
+ parent: guides
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/monitoring/overview.md b/content/docs/v2025.11.21/guides/monitoring/overview.md
new file mode 100644
index 000000000..9da896346
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/overview.md
@@ -0,0 +1,86 @@
+---
+title: Monitoring Overview | KubeVault
+description: A General Overview of Monitoring KubeVault Components
+menu:
+ docs_v2025.11.21:
+ identifier: overview-monitoring
+ name: Overview
+ parent: monitoring-guides
+ weight: 5
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Monitoring KubeVault Components
+
+KubeVault operator has native support for monitoring via [Prometheus](https://prometheus.io/). You can use builtin [Prometheus](https://github.com/prometheus/prometheus) scraper or [Prometheus Operator](https://github.com/coreos/prometheus-operator) to monitor KubeVault operator. This tutorial will show you how this monitoring works with KubeVault operator and how to enable them.
+
+## Vault Server Metrics
+
+By default the KubeVault operator will configure each vault pod to publish [statsd](https://www.vaultproject.io/docs/configuration/telemetry.html) metrics. The KubeVault operator runs a [statsd-exporter](https://github.com/kubevault/vault_exporter) container as sidecar to convert and expose those metrics in Prometheus format. Following diagram shows the logical structure of KubeVault operator monitoring flow.
+
+
+
+
+
+Each pod provides metrics at `/metrics` endpoint on port `9102`. Following metrics are available for Vault server.
+
+- vault_audit
+- vault_audit_file
+- vault_barrier
+- vault_core
+- vault_runtime
+- vault_expire
+- vault_merkle_flushdirty
+- vault_merkle_savecheckpoint
+- vault_policy
+- vault_token
+- vault_wal
+- vault_rollback_attempt
+- logshipper_streamWALs
+- replication
+- database
+- database_error
+- database_name
+- database_named_error
+- vault_storage_backend
+- vault_provider_lock
+- vault_consul
+- vault_route
+- vault_expire_num_leases
+- vault_runtime_alloc_bytes
+- vault_runtime_free_count
+- vault_runtime_heap_objects
+- vault_runtime_malloc_count
+- vault_runtime_num_goroutines
+- vault_runtime_sys_bytes
+- vault_runtime_total_gc_pause_ns
+- vault_runtime_total_gc_runs
+- vault_runtime_gc_pause_ns
+
+## KubeVault Operator Metrics
+
+You can enable monitoring for the KubeVault operator while installing or upgrading the operator. You can chose which monitoring agent to use for monitoring. KubeVault operator will configure respective resources accordingly. Here are the list of available flags and their usage:
+
+| Script Flag | Helm Values | Acceptable Values | Default | Description |
+| ------------------------ | ---------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `--monitoring-agent` | `monitoring.agent` | `prometheus.io/builtin` or `prometheus.io/coreos-operator` | `none` | Specify which monitoring agent to use for monitoring KubeVault operator. |
+| `--monitor-operator` | `monitoring.operator` | `true` or `false` | `false` | Specify whether to monitor KubeVault operator. |
+| `--prometheus-namespace` | `monitoring.prometheus.namespace` | any namespace | same namespace as KubeVault operator | Specify the namespace where Prometheus server is running or will be deployed |
+| `--servicemonitor-label` | `monitoring.serviceMonitor.labels` | any label | For Helm installation, `app: ` and `release: `. For script installation, `app: vault-operator` | Specify the labels for ServiceMonitor. Prometheus crd will select ServiceMonitor using these labels. Only usable when monitoring agent is `prometheus.io/coreos-operator`. |
+
+## Next Steps
+
+- Learn how to monitor Vault server using built-in Prometheus from [here](/docs/v2025.11.21/guides/monitoring/vault-server/builtin).
+- Learn how to monitor Vault server using CoreOS Prometheus operator from [here](/docs/v2025.11.21/guides/monitoring/vault-server/coreos).
+- Learn how to use Grafana dashboard to visualize monitoring data from [here](/docs/v2025.11.21/guides/monitoring/vault-server/grafana).
+- Learn how to monitor KubeVault operator using built-in Prometheus from [here](/docs/v2025.11.21/guides/monitoring/vault-operator/builtin).
+- Learn how to monitor KubeVault operator using CoreOS Prometheus operator from [here](/docs/v2025.11.21/guides/monitoring/vault-operator/coreos).
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-operator/_index.md b/content/docs/v2025.11.21/guides/monitoring/vault-operator/_index.md
new file mode 100755
index 000000000..7ed202510
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-operator/_index.md
@@ -0,0 +1,17 @@
+---
+title: Monitoring KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: vault-operator-monitoring
+ name: KubeVault operator
+ parent: monitoring-guides
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-operator/builtin.md b/content/docs/v2025.11.21/guides/monitoring/vault-operator/builtin.md
new file mode 100644
index 000000000..37264628a
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-operator/builtin.md
@@ -0,0 +1,308 @@
+---
+title: Monitor KubeVault operator using Builtin Prometheus Discovery
+menu:
+ docs_v2025.11.21:
+ identifier: builtin-prometheus-vault-operator-monitoring
+ name: Builtin Prometheus
+ parent: vault-operator-monitoring
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Monitor KubeVault operator with builtin Prometheus
+
+This tutorial will show you how to configure builtin [Prometheus](https://github.com/prometheus/prometheus) scraper to monitor KubeVault operator.
+
+## Before You Begin
+
+At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
+
+To keep Prometheus resources isolated, we are going to use a separate namespace to deploy Prometheus server.
+
+```bash
+$ kubectl create ns monitoring
+namespace/monitoring created
+```
+
+## Enable Monitoring in KubeVault operator
+
+Enable Prometheus monitoring using `prometheus.io/builtin` annotations while install KubeVault operator. To know details about how to enable monitoring see [here](/docs/v2025.11.21/guides/monitoring/overview#how-to-enable-monitoring)
+
+Here, we are going to enable monitoring for `operator` metrics.
+
+**Using Helm 3:**
+
+```bash
+$ helm install kubevault oci://ghcr.io/appscode-charts/kubevault \
+ --version {{< param "info.version" >}} \
+ --namespace kubevault --create-namespace \
+ --set monitoring.agent=prometheus.io/builtin \
+ --set monitoring.operator=true \
+ --set monitoring.prometheus.namespace=monitoring
+```
+
+**Using YAML (with Helm 3):**
+
+```bash
+$ helm template kubevault oci://ghcr.io/appscode-charts/kubevault \
+ --version {{< param "info.version" >}} \
+ --namespace kubevault --create-namespace \
+ --no-hooks \
+ --set monitoring.agent=prometheus.io/builtin \
+ --set monitoring.operator=true \
+ --set monitoring.prometheus.namespace=monitoring | kubectl apply -f -
+```
+
+This will add necessary annotations to `vault-operator` service. Prometheus server will scrap metrics using those annotations. Let's check which annotations are added to the service,
+
+```yaml
+$ kubectl get svc vault-operator -n kube-system -o yaml
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ prometheus.io/path: /metrics
+ prometheus.io/port: "8443"
+ prometheus.io/scheme: https
+ prometheus.io/scrape: "true"
+ creationTimestamp: "2018-12-26T06:12:51Z"
+ labels:
+ app: vault-operator
+ chart: vault-operator-{{< param "info.version" >}}
+ heritage: Tiller
+ release: vault-operator
+ name: vault-operator
+ namespace: kube-system
+ resourceVersion: "10030"
+ selfLink: /api/v1/namespaces/kube-system/services/vault-operator
+ uid: 469d2c8f-08d5-11e9-852c-080027857726
+spec:
+ clusterIP: 10.110.168.15
+ ports:
+ - name: api
+ port: 443
+ protocol: TCP
+ targetPort: 8443
+ selector:
+ app: vault-operator
+ release: vault-operator
+ sessionAffinity: None
+ type: ClusterIP
+status:
+ loadBalancer: {}
+```
+
+Here, `prometheus.io/scrape: "true"` annotation indicates that Prometheus should scrap metrics for this service.
+
+The following three annotations point to api endpoints which provides operator specific metrics.
+
+```bash
+prometheus.io/path: /metrics
+prometheus.io/port: "8443"
+prometheus.io/scheme: https
+```
+
+Now, we are ready to configure our Prometheus server to scrap those metrics.
+
+## Deploy Prometheus Server
+
+We have deployed KubeVault operator in `kube-system` namespace. KubeVault operator exports operator metrics via TLS secured `api` endpoint. So, Prometheus server need to provide certificate while scraping metrics from this endpoint. KubeVault operator has created a secret named `vault-operator-apiserver-cert` with this certificate in `monitoring` namespaces as we have specified that we are going to deploy Prometheus in that namespace through `--prometheus-namespace` or `monitoring.prometheus.namespace` flag. We have to mount this secret in Prometheus deployment.
+
+Let's check `vault-operator-apiserver-cert` secret has been created in `monitoring` namespace.
+
+```bash
+$ kubectl get secrets -n monitoring -l=app.kubernetes.io/name=vault-operator
+NAME TYPE DATA AGE
+vault-operator-apiserver-cert kubernetes.io/tls 2 107m
+```
+
+#### Create `RBAC`
+
+If you are using a `RBAC` enabled cluster, you have to provide necessary `RBAC` permissions for Prometheus. Following [this](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/builtin/README.md#deploy-prometheus-server), let's create `RBAC` stuffs for Prometheus by running:
+
+```bash
+$ kubectl apply -f https://github.com/appscode/third-party-tools/raw/master/monitoring/prometheus/builtin/artifacts/rbac.yaml
+clusterrole.rbac.authorization.k8s.io/prometheus created
+serviceaccount/prometheus created
+clusterrolebinding.rbac.authorization.k8s.io/prometheus created
+```
+> YAML for RBAC resources can be found [here](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/builtin/artifacts/rbac.yaml).
+
+#### Create `ConfigMap`
+
+As we are monitoring KubeVault operator, we should follow [this](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/builtin/README.md#kubernetes-apiservers) to create a ConfigMap. Bellow the YAML of ConfigMap that we are going to create in this tutorial
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: prometheus-config
+ labels:
+ name: prometheus-config
+ namespace: monitoring
+data:
+ prometheus.yml: |-
+ global:
+ scrape_interval: 5s
+ evaluation_interval: 5s
+ scrape_configs:
+ - job_name: 'vault-apiservers'
+ honor_labels: true
+ kubernetes_sd_configs:
+ - role: endpoints
+ # Kubernetes apiserver serve metrics on a TLS secure endpoints. so, we have to use "https" scheme
+ scheme: https
+ # we have to provide certificate to establish tls secure connection
+ tls_config:
+ ca_file: /etc/prometheus/secret/vault-operator-apiserver-cert/tls.crt
+ server_name: vault-operator.kube-system.svc
+ # bearer_token_file is required for authorizating prometheus server to Kubernetes apiserver
+ bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_label_app]
+ separator: ;
+ regex: vault-operator
+ replacement: $1
+ action: keep
+ - source_labels: [__meta_kubernetes_endpoint_address_target_kind, __meta_kubernetes_endpoint_address_target_name]
+ separator: ;
+ regex: Node;(.*)
+ target_label: node
+ replacement: ${1}
+ action: replace
+ - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
+ action: keep
+ regex: kube-system;vault-operator;api
+ - separator: ;
+ regex: (.*)
+ target_label: endpoint
+ replacement: api
+ action: replace
+ - source_labels: [__meta_kubernetes_service_name]
+ separator: ;
+ regex: (.*)
+ target_label: job
+ replacement: ${1}
+ action: replace
+```
+
+Look at the `tls_config` field of `vault-apiservers` job. We have provided certificate file through `ca_file` field. This certificate comes from `vault-operator-apiserver-cert` that we are going to mount in Prometheus deployment. Here, `server_name` is used to verify hostname. In our case, the certificate is valid for hostname server and `vault-operator.kube-system.svc`.
+
+In `relabel_configs` section we added `..svc:443` as the value of `replacement`.
+
+Let's create the ConfigMap we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-operator/prom-server-conf.yaml
+configmap/prometheus-config created
+```
+
+#### Deploy Prometheus
+
+Now, we are ready to deploy Prometheus server. YAML for the deployment that we are going to create for Prometheus is shown below.
+
+```yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: prometheus-demo
+ name: prometheus
+ namespace: monitoring
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: prometheus
+ template:
+ metadata:
+ labels:
+ app: prometheus
+ spec:
+ containers:
+ - args:
+ - --config.file=/etc/prometheus/prometheus.yml
+ - --storage.tsdb.path=/prometheus/
+ image: prom/prometheus:v2.5.0
+ imagePullPolicy: IfNotPresent
+ name: prometheus
+ ports:
+ - containerPort: 9090
+ protocol: TCP
+ volumeMounts:
+ - mountPath: /etc/prometheus/
+ name: prometheus-config
+ - mountPath: /prometheus/
+ name: prometheus-storage
+ - mountPath: /etc/prometheus/secret/vault-operator-apiserver-cert
+ name: vault-operator-apiserver-cert
+ serviceAccountName: prometheus
+ volumes:
+ - configMap:
+ defaultMode: 420
+ name: prometheus-config
+ name: prometheus-config
+ - emptyDir: {}
+ name: prometheus-storage
+ - name: vault-operator-apiserver-cert
+ secret:
+ defaultMode: 420
+ secretName: vault-operator-apiserver-cert
+ items:
+ - path: tls.crt
+ key: tls.crt
+```
+
+Notice that, we have mounted vault-operator-apiserver-cert secret as a volume at `/etc/prometheus/secret/vault-operator-apiserver-cert` directory.
+
+Now, let's create the deployment,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-operator/prom-builtin-deployment.yaml
+deployment.apps "prometheus" deleted
+```
+
+#### Verify Monitoring Metrics
+
+Prometheus server is running on port 9090. We are going to use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) to access Prometheus dashboard. Run following commands on a separate terminal,
+
+```bash
+$ kubectl get pod -n monitoring -l=app=prometheus
+NAME READY STATUS RESTARTS AGE
+prometheus-8568c86d86-vpzx5 1/1 Running 0 102s
+
+$ kubectl port-forward -n monitoring prometheus-8568c86d86-vpzx5 9090
+Forwarding from 127.0.0.1:9090 -> 9090
+Forwarding from [::1]:9090 -> 9090
+```
+
+Now, we can access the dashboard at localhost:9090. Open [http://localhost:9090](http://localhost:9090) in your browser. You should see the configured jobs as target and they are in UP state which means Prometheus is able collect metrics from them.
+
+
+
+
+
+
+
+## Cleaning up
+
+To uninstall Prometheus server follow [this](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/builtin/README.md#cleanup)
+
+To uninstall KubeVault operator follow [this](https://github.com/kubevault/kubevault/blob/master/docs/setup/operator/uninstall.md#uninstall-vault-operator)
+
+To cleanup the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns monitoring
+```
+
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-operator/coreos.md b/content/docs/v2025.11.21/guides/monitoring/vault-operator/coreos.md
new file mode 100644
index 000000000..80604d63e
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-operator/coreos.md
@@ -0,0 +1,210 @@
+---
+title: Monitor KubeVault operator using Prometheus Operator
+menu:
+ docs_v2025.11.21:
+ identifier: coreos-vault-operator-monitoring
+ name: Prometheus Operator
+ parent: vault-operator-monitoring
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Monitoring KubeVault operator Using Prometheus Operator
+
+CoreOS [prometheus-operator](https://github.com/coreos/prometheus-operator) provides simple and Kubernetes native way to deploy and configure Prometheus server. This tutorial will show you how to use CoreOS Prometheus operator for monitoring KubeVault operator.
+
+## Before You Begin
+
+- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
+
+- To keep Prometheus resources isolated, we are going to use a separate namespace to deploy Prometheus operator and respective resources.
+
+```bash
+$ kubectl create ns monitoring
+namespace/monitoring created
+```
+
+- We need a CoreOS prometheus-operator instance running. If you already don't have a running instance, deploy one following the docs from [here](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/coreos-operator/README.md).
+
+## Enable Monitoring in KubeVault operator
+
+Enable Prometheus monitoring using `prometheus.io/coreos-operator` agent while installing KubeVault operator. To know details about how to enable monitoring see [here](/docs/v2025.11.21/guides/monitoring/overview#how-to-enable-monitoring)
+
+Here, we are going to enable monitoring for `operator` metrics.
+
+**Using Helm 3:**
+
+```bash
+$ helm install kubevault oci://ghcr.io/appscode-charts/kubevault \
+ --version {{< param "info.version" >}} \
+ --namespace kubevault --create-namespace \
+ --set monitoring.agent=prometheus.io/coreos-operator \
+ --set monitoring.operator=true \
+ --set monitoring.prometheus.namespace=monitoring \
+ --set monitoring.serviceMonitor.labels.k8s-app=prometheus
+```
+
+**Using YAML (with Helm 3):**
+
+```bash
+$ helm template kubevault oci://ghcr.io/appscode-charts/kubevault \
+ --version {{< param "info.version" >}} \
+ --namespace kubevault --create-namespace \
+ --no-hooks \
+ --set monitoring.agent=prometheus.io/coreos-operator \
+ --set monitoring.operator=true \
+ --set monitoring.prometheus.namespace=monitoring \
+ --set monitoring.serviceMonitor.labels.k8s-app=prometheus | kubectl apply -f -
+```
+
+This will create a `ServiceMonitor` crd with name `vault-operator-servicemonitor` in `monitoring` namespace for monitoring endpoints of `vault-operator` service. This ServiceMonitor will have label `k8s-app: prometheus` provided by `--servicemonitor-label` flag. This label will be used by Prometheus crd to select this ServiceMonitor.
+
+Let's check the ServiceMonitor crd using following command,
+
+```yaml
+$ kubectl get servicemonitors -n monitoring vault-operator-servicemonitor -o yaml
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ creationTimestamp: "2018-12-26T11:13:25Z"
+ generation: 1
+ labels:
+ k8s-app: prometheus
+ name: vault-operator-servicemonitor
+ namespace: monitoring
+ resourceVersion: "32902"
+ selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/servicemonitors/vault-operator-servicemonitor
+ uid: 438a7cb5-08ff-11e9-852c-080027857726
+spec:
+ endpoints:
+ - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
+ port: api
+ scheme: https
+ tlsConfig:
+ caFile: /etc/prometheus/secrets/vault-operator-apiserver-cert/tls.crt
+ serverName: vault-operator.kube-system.svc
+ namespaceSelector:
+ matchNames:
+ - kube-system
+ selector:
+ matchLabels:
+ app: vault-operator
+ release: vault-operator
+```
+
+Here, `api` endpoint exports operator metrics.
+
+KubeVault operator exports operator metrics via TLS secured `api` endpoint. So, Prometheus server need to provide certificate while scraping metrics from this endpoint. KubeVault operator has created a secret named `vault-operator-apiserver-certs` with this certificate in `monitoring` namespace as we have specified that we are going to deploy Prometheus in that namespace through `--prometheus-namespace` flag. We have to specify this secret in Prometheus crd through `spec.secrets` field. Prometheus operator will mount this secret at `/etc/prometheus/secrets/vault-operator-apiserver-cert` directory of respective Prometheus pod. So, we need to configure `tlsConfig` field to use that certificate. Here, `caFile` indicates the certificate to use and serverName is used to verify hostname. In our case, the certificate is valid for hostname server and `vault-operator.kube-system.svc`.
+
+Let's check secret vault-operator-apiserver-cert has been created in monitoring namespace.
+
+```bash
+$ kubectl get secret -n monitoring -l=app.kubernetes.io/name=vault-operator
+NAME TYPE DATA AGE
+vault-operator-apiserver-cert kubernetes.io/tls 2 8m27s
+```
+
+Also note that, there is a bearerTokenFile field. This file is token for the serviceaccount that will be created while creating RBAC stuff for Prometheus crd. This is required for authorizing Prometheus to scrape KubeVault operator API server.
+
+Now, we are ready to deploy Prometheus server.
+
+## Deploy Prometheus Server
+
+In order to deploy Prometheus server, we have to create Prometheus crd. Prometheus crd defines a desired Prometheus server setup. For more details about Prometheus crd, please visit [here](https://github.com/coreos/prometheus-operator/blob/master/Documentation/design.md#prometheus).
+
+If you are using a RBAC enabled cluster, you have to give necessary permissions to Prometheus. Check the documentation to see required RBAC permission from [here](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/coreos-operator/README.md#deploy-prometheus-server).
+
+#### Create Prometheus:
+
+Below is the YAML of Prometheus crd that we are going to create for this tutorial,
+
+```yaml
+apiVersion: monitoring.coreos.com/v1
+kind: Prometheus
+metadata:
+ name: prometheus
+ namespace: monitoring
+ labels:
+ k8s-app: prometheus
+spec:
+ replicas: 1
+ serviceAccountName: prometheus
+ serviceMonitorSelector:
+ matchLabels:
+ k8s-app: prometheus
+ secrets:
+ - vault-operator-apiserver-cert
+ resources:
+ requests:
+ memory: 400Mi
+```
+
+Here, `spec.serviceMonitorSelector` is used to select the ServiceMonitor crd that is created by KubeVault operator. We have provided `vault-operator-apiserver-cert` secret in `spec.secrets` field. This will be mounted in Prometheus pod.
+
+Let's create the Prometheus object we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-operator/prom-coreos-crd.yaml
+prometheus.monitoring.coreos.com/prometheus created
+```
+
+Prometheus operator watches for Prometheus `crd`. Once a Prometheus crd is created, Prometheus operator generates respective configuration and creates a `StatefulSet` to run Prometheus server.
+
+Let's check `StatefulSet` has been created,
+
+```bash
+$ kubectl get statefulset -n monitoring
+NAME READY AGE
+prometheus-prometheus 1/1 31m
+```
+
+Check StatefulSet's pod is running,
+
+```bash
+$ kubectl get pod prometheus-prometheus-0 -n monitoring
+NAME READY STATUS RESTARTS AGE
+prometheus-prometheus-0 3/3 Running 1 31m
+```
+
+Now, we are ready to access Prometheus dashboard.
+
+#### Verify Monitoring Metrics
+
+Prometheus server is running on port 9090. We are going to use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) to access Prometheus dashboard. Run following commands on a separate terminal,
+
+```bash
+$ kubectl port-forward -n monitoringprometheus-prometheus-0 9090
+Forwarding from 127.0.0.1:9090 -> 9090
+Forwarding from [::1]:9090 -> 9090
+```
+
+Now, we can access the dashboard at localhost:9090. Open [http://localhost:9090](http://localhost:9090) in your browser. You should see the configured jobs as target and they are in UP state which means Prometheus is able collect metrics from them.
+
+
+
+
+
+
+
+## Cleaning up
+
+To uninstall KubeVault operator follow [this](https://github.com/kubevault/kubevault/blob/master/docs/setup/operator/uninstall.md#uninstall-vault-operator).
+
+To cleanup the Kubernetes resources created by this tutorial, run:
+
+```bash
+# cleanup Prometheus resources
+kubectl delete -n monitoring prometheus prometheus
+kubectl delete -n monitoring secret vault-operator-apiserver-cert
+
+$ kubectl delete ns monitoring
+```
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-server/_index.md b/content/docs/v2025.11.21/guides/monitoring/vault-server/_index.md
new file mode 100755
index 000000000..f5d84a526
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-server/_index.md
@@ -0,0 +1,17 @@
+---
+title: Monitoring Vault Server
+menu:
+ docs_v2025.11.21:
+ identifier: vault-server-monitoring
+ name: Vault Server
+ parent: monitoring-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-server/builtin.md b/content/docs/v2025.11.21/guides/monitoring/vault-server/builtin.md
new file mode 100644
index 000000000..eae2896db
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-server/builtin.md
@@ -0,0 +1,229 @@
+---
+title: Monitor Vault Server using Builtin Prometheus Discovery
+menu:
+ docs_v2025.11.21:
+ identifier: builtin-prometheus-vault-server-monitoring
+ name: Builtin Prometheus
+ parent: vault-server-monitoring
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Monitor Vault server with builtin Prometheus scraper
+
+This tutorial will show you how to configure builtin [Prometheus](https://github.com/prometheus/prometheus) scraper to monitor Vault server provisioned by the KubeVault operator.
+
+The prometheus server is needed to configure so that it can discover endpoints of Kubernetes services. If a Prometheus server is already running in cluster and if it is configured in a way that it can discover service endpoints, no extra configuration will be needed.Otherwise, read this [tutorial](https://github.com/appscode/third-party-tools/tree/master/monitoring/prometheus/builtin/README.md) to deploy a Prometheus server with appropriate configuration.
+
+Create the following configmap with Prometheus configuration and pass it to a Prometheus server.
+
+```yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: prometheus-server-conf
+ labels:
+ name: prometheus-server-conf
+ namespace: demo
+data:
+ prometheus.yml: |-
+ global:
+ scrape_interval: 5s
+ evaluation_interval: 5s
+ scrape_configs:
+ - job_name: 'kubernetes-service-endpoints'
+
+ kubernetes_sd_configs:
+ - role: endpoints
+
+ relabel_configs:
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
+ action: keep
+ regex: true
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
+ action: replace
+ target_label: __scheme__
+ regex: (https?)
+ - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
+ action: replace
+ target_label: __metrics_path__
+ regex: (.+)
+ - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
+ action: replace
+ target_label: __address__
+ regex: ([^:]+)(?::\d+)?;(\d+)
+ replacement: $1:$2
+ - action: labelmap
+ regex: __meta_kubernetes_service_label_(.+)
+ - source_labels: [__meta_kubernetes_namespace]
+ action: replace
+ target_label: kubernetes_namespace
+ - source_labels: [__meta_kubernetes_service_name]
+ action: replace
+ target_label: kubernetes_name
+ - source_labels: [__meta_kubernetes_pod_name]
+ action: replace
+ target_label: pod_name
+```
+
+You can create above ConfigMap by running
+
+```bash
+$ kubectl create -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-server/prom-server-conf.yaml
+configmap/prometheus-server-conf created
+```
+
+> Note: YAML files used in this tutorial are stored in [docs/examples](/docs/v2025.11.21/examples)
+
+## Monitor Vault server
+
+To enable monitoring, configure `spec.monitor` field in a `VaultServer` custom resource. Below is an example:
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.2.0
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: "WipeOut"
+```
+
+Here,
+
+- `spec.monitor` specifies that built-in [prometheus](https://github.com/prometheus/prometheus) is used to monitor this Vault server instance.
+- `monitor.prometheus` specifies the information for monitoring by Prometheus.
+ - `prometheus.port` indicates the port for Vault statsd exporter endpoint (default is `56790`)
+ - `prometheus.interval` indicates the scraping interval (eg, '10s')
+
+Run the following command to create it.
+
+```bash
+$ kubectl create -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-server/vault-server-builtin.yaml
+vaultserver.kubevault.com/example created
+```
+
+KubeVault operator will configure its service once the Vault server is successfully running.
+
+```bash
+$ kubectl get vs -n demo
+NAME NODES VERSION STATUS AGE
+example 1 0.11.1 Running 3h
+```
+
+Let's describe Service `example-stats`
+
+```bash
+$ kubectl get svc -n demo example -o yaml
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ monitoring.appscode.com/agent: prometheus.io/builtin
+ prometheus.io/path: /metrics
+ prometheus.io/port: "9102"
+ prometheus.io/scrape: "true"
+ creationTimestamp: "2018-12-24T11:27:28Z"
+ labels:
+ app: vault
+ vault_cluster: example
+ name: example
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ controller: true
+ kind: VaultServer
+ name: example
+ uid: e42c20cd-076e-11e9-b586-0800274de81b
+ resourceVersion: "1828"
+ selfLink: /api/v1/namespaces/demo/services/example
+ uid: e5064216-076e-11e9-b586-0800274de81b
+spec:
+ clusterIP: 10.107.246.170
+ externalTrafficPolicy: Cluster
+ ports:
+ - name: client
+ nodePort: 31528
+ port: 8200
+ protocol: TCP
+ targetPort: 8200
+ - name: cluster
+ nodePort: 32245
+ port: 8201
+ protocol: TCP
+ targetPort: 8201
+ - name: prom-http
+ nodePort: 30292
+ port: 9102
+ protocol: TCP
+ targetPort: 9102
+ selector:
+ app: vault
+ vault_cluster: example
+ sessionAffinity: None
+ type: NodePort
+status:
+ loadBalancer: {}
+
+```
+
+You can see that the service contains following annotations.
+
+```bash
+monitoring.appscode.com/agent: prometheus.io/builtin
+prometheus.io/path: /metrics
+prometheus.io/port: "9102"
+prometheus.io/scrape: "true"
+```
+
+The Prometheus server will discover the Vault service endpoint and will scrape metrics from the exporter sidecar.
+
+
+
+
+
+
+
+## Cleaning up
+
+To cleanup the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete -n demo vs/example
+$ kubectl delete ns demo
+```
+
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-server/coreos.md b/content/docs/v2025.11.21/guides/monitoring/vault-server/coreos.md
new file mode 100644
index 000000000..b43b7bf8c
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-server/coreos.md
@@ -0,0 +1,104 @@
+---
+title: Monitor Vault Server using Prometheus Operator
+menu:
+ docs_v2025.11.21:
+ identifier: coreos-vault-server-monitoring
+ name: Prometheus Operator
+ parent: vault-server-monitoring
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Monitoring Vault Server Using Prometheus Operator
+
+CoreOS [prometheus-operator](https://github.com/coreos/prometheus-operator) provides simple and Kubernetes native way to deploy and configure Prometheus server. This tutorial will show you how to monitor Vault server using Prometheus via Prometheus Operator).
+
+## Monitor Vault server
+
+To enable monitoring, configure `spec.monitor` field in a `VaultServer` custom resource. Below is an example:
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.2.0
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ - alias: stats
+ spec:
+ type: ClusterIP
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: "WipeOut"
+```
+
+Here,
+
+- `monitor.agent` indicates the monitoring agent `coreos-prometheus-operator`.
+- `monitor.prometheus` specifies the information for monitoring by Prometheus.
+ - `prometheus.namespace` specifies the namespace where ServiceMonitor is created.
+ - `prometheus.labels` specifies the labels applied to ServiceMonitor.
+ - `prometheus.port` indicates the port for Vault statsd exporter endpoint (default is `56790`)
+ - `prometheus.interval` indicates the scraping interval (eg, '10s')
+
+Now create Vault server with the monitoring spec
+
+```bash
+$ kubectl create -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-server/vault-server-coreos.yaml
+
+```
+
+KubeVault operator will create a ServiceMonitor object once the Vault server is successfully running.
+
+```bash
+$ kubectl get servicemonitor -n demo
+NAME AGE
+vault-demo-exampleco 23s
+```
+
+Now, if you go the Prometheus Dashboard, you should see that this Vault endpoint as one of the targets.
+
+
+
+
+
+
+
+## Cleaning up
+
+To cleanup the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete -n demo vs/coreos-prom-postgres
+
+$ kubectl delete ns demo
+```
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/monitoring/vault-server/grafana.md b/content/docs/v2025.11.21/guides/monitoring/vault-server/grafana.md
new file mode 100644
index 000000000..fcac99564
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/monitoring/vault-server/grafana.md
@@ -0,0 +1,118 @@
+---
+title: Grafana dashboard for Vault Server
+menu:
+ docs_v2025.11.21:
+ identifier: grafana-vault-server-monitoring
+ name: Grafana Dashboard
+ parent: vault-server-monitoring
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Visualize Vault server data using Grafana dashboard
+
+Grafana provides an elegant graphical user interface to visualize data. You can create beautiful dashboard easily with a meaningful representation of your Prometheus metrics.
+
+If there is no grafana instance running on your cluster, then you can [read this tutorial](https://github.com/appscode/third-party-tools/blob/master/monitoring/grafana/README.md) to deploy one.
+
+
+## Add Prometheus Data Source
+
+We have to add our Prometheus server `prometheus-prometheus-0` as data source of grafana. We are going to use a `ClusterIP` service to connect Prometheus server with grafana. Let's create a service to select Prometheus server `prometheus-prometheus-0`,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/monitoring/vault-server/prometheus-service.yaml
+service/prometheus created
+```
+
+Below the YAML for the service we have created above,
+
+```yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: prometheus
+ namespace: monitoring
+spec:
+ type: ClusterIP
+ ports:
+ - name: web
+ port: 9090
+ protocol: TCP
+ targetPort: 9090
+ selector:
+ app: prometheus
+```
+
+Now, follow these steps to add the Prometheus server as data source of Grafana UI.
+
+1. From Grafana UI, go to `Configuration` option from sidebar and click on `Data Sources`.
+
+
+
+
+
+2. Then, click on `Add data source`.
+
+
+
+
+
+3. Now, configure `Name`, `Type` and `URL` fields as specified below and keep rest of the configuration to their default value then click `Save&Test` button.
+ - *Name: Vault-Operator* (you can give any name)
+ - *Type: Prometheus*
+ - *URL: http://prometheus.monitoring.svc:9090*
+ (url format: http://{prometheus service name}.{namespace}.svc:{port})
+
+
+
+
+
+Once you have added Prometheus data source successfully, you are ready to create a dashboard to visualize the metrics.
+
+## Import Vault server Dashboard
+
+Vault server comes with a pre-configured Grafana dashboard. You can download json configuration of the dashboard from [here](/docs/v2025.11.21/examples/monitoring/grafana/dashboard.json).
+
+Follow these steps to import the preconfigured stash dashboard,
+
+1. From Grafana UI, go to `Create` option from sidebar and click on `import`.
+
+
+
+
+
+2. Then, paste `json` from [here](/docs/v2025.11.21/examples/monitoring/grafana/dashboard.json) or upload `json` configuration file of the dashboard using `Upload .json File` button.
+
+
+
+
+
+3. Now on `prometheus-infra` field, select the data source name that we have given to our Prometheus data source earlier. Then click on `Import` button.
+
+
+
+
+
+Once you have imported the dashboard successfully, you will be greeted with dashboard.
+
+
+
+
+
+
+## Cleanup
+To cleanup the Kubernetes resources created by this tutorial, run:
+
+```bash
+kubectl delete -n demo service prometheus
+```
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/platforms/_index.md b/content/docs/v2025.11.21/guides/platforms/_index.md
new file mode 100755
index 000000000..dc4a2c5fd
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/platforms/_index.md
@@ -0,0 +1,17 @@
+---
+title: Platform Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: platform-guides
+ name: Platforms
+ parent: guides
+ weight: 50
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/platforms/aks.md b/content/docs/v2025.11.21/guides/platforms/aks.md
new file mode 100644
index 000000000..7c97024cd
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/platforms/aks.md
@@ -0,0 +1,366 @@
+---
+title: Deploy Vault on Azure Kubernetes Service (AKS)
+menu:
+ docs_v2025.11.21:
+ identifier: aks-platform
+ name: AKS
+ parent: platform-guides
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Deploy Vault on Azure Kubernetes Service (AKS)
+
+Here, we are going to deploy Vault in AKS using KubeVault operator. We are going to use [Azure Storage Container](https://azure.microsoft.com/en-us/services/storage/) as Vault backend and `azureKeyVault` unsealer mode for automatically unsealing the Vault.
+
+## Before You Begin
+
+At first, you need to have an AKS cluster. If you don't already have a cluster, create one from [here](https://azure.microsoft.com/en-us/services/kubernetes-service/).
+
+- Install KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+- You should be familiar with the following CRD:
+ - [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+ - [Unsealer](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview)
+ - [azureKeyVault](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/azure_key_vault)
+
+- You will need a storage account. Guides to create a storage account can be found [here](https://docs.microsoft.com/en-us/azure/storage/common/storage-create-storage-account#create-a-storage-account). In this tutorial, we are going to use `vaultstorageac` storage account.
+
+- You will need a [Azure Storage Container](https://azure.microsoft.com/en-us/services/storage/) to use it as Vault backend storage. In this tutorial, we are going to use `demo-vault` blob container in `vaultstorageac` storage account.
+
+- You will need a Azure Key Vault for unsealer. Guides to create key vault can be found [here](https://docs.microsoft.com/en-us/azure/key-vault/key-vault-get-started). In this tutorial, we are going to use `vault-key-store` key vault.
+### Provision Cluster
+
+We are going to provision Kubernetes cluster using AKS.
+
+
+
+Configure `.kube/config`
+
+```bash
+$ az aks get-credentials --resource-group vault-aks --name vault
+Merged "vault" as current context in /home/ac/.kube/config
+```
+
+```bash
+$ kubectl get pods --all-namespaces
+NAMESPACE NAME READY STATUS RESTARTS AGE
+kube-system heapster-5d6f9b846c-69fvm 2/2 Running 0 47m
+kube-system kube-dns-v20-7c7d7d4c66-8r7st 4/4 Running 0 48m
+kube-system kube-dns-v20-7c7d7d4c66-vzg6n 4/4 Running 0 48m
+kube-system kube-proxy-82c8t 1/1 Running 0 45m
+kube-system kube-svc-redirect-hl6gz 2/2 Running 0 45m
+kube-system kubernetes-dashboard-68f468887f-5knhd 1/1 Running 1 47m
+kube-system metrics-server-5cbc77f79f-jc8b4 1/1 Running 1 47m
+kube-system omsagent-rs-ddc44b8cd-m42b2 1/1 Running 0 47m
+kube-system omsagent-s82s2 1/1 Running 0 45m
+kube-system tunnelfront-8475548867-xvddt 1/1 Running 0 47m
+```
+
+We are going to create a `web app/api` type Azure Active Directory Application `vault-app`. Guides to create an Azure AD application can be found [here](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal#create-an-azure-active-directory-application). We will use the application id and key of this `vault-app` as credential. We are going to give `vault-app` application access to the secret in key vault `vault-key-store`.
+
+ 
+
+### Install KubeVault operator
+
+See [here](/docs/v2025.11.21/setup/README).
+
+```bash
+$ kubectl get pods -n kube-system
+NAMESPACE NAME READY STATUS RESTARTS AGE
+kube-system vault-operator-576b7867cb-tmz2j 1/1 Running 0 7m
+```
+
+### Deploy Vault
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+We will deploy `my-vault` on `demo` namespace. We will configure it for Azure Container backend. We will use `azureKeyVault` for auto initializing and unsealing.
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ azure:
+ container: demo-vault
+ accountName: vaultstorageac
+ accountKeySecret: azure-ac-key
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ azureKeyVault:
+ vaultBaseURL: https://vault-key-store.vault.azure.net/
+ tenantID: aaaaaaa-bbbb-ccc-dddd-eeeeeeeee
+ aadClientSecret: azure-ad-client-secret
+```
+
+Here, `spec.version` specifies the name of the [VaultServerVersion](/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion) CRD. If that does not exist, then create one.
+
+```bash
+$ kubectl get vaultserverversions
+NAME VERSION VAULT_IMAGE DEPRECATED AGE
+1.2.0 1.2.0 vault:1.2.0 false 1m
+
+$ kubectl get vaultserverversions/1.2.0 -o yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ version: 1.2.0
+ deprecated: false
+ vault:
+ image: vault:1.2.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ exporter:
+ image: kubevault/vault-exporter:0.1.0
+```
+
+`spec.backend.azure.accountKeySecret` specifies the name of the Kubernetes secret containing `vaultstorageac` storage account key.
+
+```bash
+$ kubectl get secrets azure-ac-key -n demo -o yaml
+apiVersion: v1
+data:
+ account_key: QW5EOHhvQ1pWZ...
+kind: Secret
+metadata:
+ name: azure-ac-key
+ namespace: demo
+type: Opaque
+```
+
+`spec.unsealer.mode.azureKeyVault.aadClientSecret` specifies the name of Kubernetes secret containing credential of `vault-app` Azure AD application.
+
+```bash
+$ kubectl get secrets azure-ad-client-secret -n demo -o yaml
+apiVersion: v1
+data:
+ client-id: NzUw...
+ client-secret: clllWmNPd...
+kind: Secret
+metadata:
+ name: azure-ad-client-secret
+ namespace: demo
+type: Opaque
+
+```
+
+`spec.unsealer.mode.azureKeyVault.vaultBaseURL` is the DNS name of the `vault-key-store` key vault.
+
+
+
+Now, we are going to create `my-vault` in `demo` namespace.
+
+```bash
+$ cat examples/guides/provider/aks/my-vault.yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ azure:
+ container: demo-vault
+ accountName: vaultstorageac
+ accountKeySecret: azure-ac-key
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ azureKeyVault:
+ vaultBaseURL: https://vault-key-store.vault.azure.net/
+ tenantID: aaaaaaa-bbbb-ccc-dddd-eeeeeeeee
+ aadClientSecret: azure-ad-client-secret
+
+$ kubectl apply -f docs/examples/guides/provider/aks/my-vault.yaml
+vaultserver.kubevault.com/my-vault created
+```
+
+Check the `my-vault` status. It may take some time to reach `Running` stage.
+
+```bash
+$ kubectl get vaultserver/my-vault -n demo
+NAME NODES VERSION STATUS AGE
+my-vault 1 1.2.0 Running 2m
+```
+
+`status` field in `my-vault` will show more detail information.
+
+```bash
+$ kubectl get vaultserver/my-vault -n demo -o json | jq '.status'
+{
+ "clientPort": 8200,
+ "initialized": true,
+ "observedGeneration": "2$6206030548680361215",
+ "phase": "Running",
+ "serviceName": "my-vault",
+ "updatedNodes": [
+ "my-vault-684c485f7-7t6zs"
+ ],
+ "vaultStatus": {
+ "active": "my-vault-684c485f7-7t6zs",
+ "unsealed": [
+ "my-vault-684c485f7-7t6zs"
+ ]
+ }
+}
+
+```
+
+KubeVault operator will create a service `{metadata.name}` for `my-vault` in the same namespace. For this case, service name is `my-vault`. You can specify service configuration in [spec.serviceTemplate](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver#specservicetemplate). KubeVault operator will use that configuration to create service.
+
+```bash
+$ kubectl get services -n demo
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+my-vault ClusterIP 10.3.244.122 8200/TCP,8201/TCP,9102/TCP 4m
+```
+
+The configuration used to run Vault can be found in `{metadata.name}-vault-config` configMap. For this case, it is `my-vault-vault-config`. Confidential data are omitted in this configMap.
+
+```bash
+$ kubectl get configmaps -n demo
+NAME DATA AGE
+my-vault-vault-config 1 49m
+
+$ kubectl get configmaps/my-vault-vault-config -n demo -o yaml
+apiVersion: v1
+data:
+ vault.hcl: |2-
+
+ listener "tcp" {
+ address = "0.0.0.0:8200"
+ cluster_address = "0.0.0.0:8201"
+ tls_cert_file = "/etc/vault/tls/tls.crt"
+ tls_key_file = "/etc/vault/tls/tls.key"
+ }
+
+ storage "azure" {
+ accountName = "vaultstorageac"
+ container = "demo-vault"
+ }
+
+ telemetry {
+ statsd_address = "0.0.0.0:9125"
+ }
+
+kind: ConfigMap
+metadata:
+ name: my-vault-vault-config
+ namespace: demo
+```
+
+In this `my-vault`, KubeVault operator will use self-signed certificates for Vault and also will create `{metadata.name}-vault-tls` secret containing certificates. You can optionally specify certificates in [spec.tls](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver#spectls).
+
+```bash
+$ kubectl get secrets -n demo
+NAME TYPE DATA AGE
+my-vault-vault-tls Opaque 3 1h
+```
+
+We can see unseal keys and root token in `vault-key-store` key vault.
+
+
+
+### Using Vault
+
+Collect the root token from `vault-key-store`:
+
+
+
+
+```bash
+$ echo "cy40QTR3anQwSmt6N0p1QmlpMDM4QnprbkM=" | base64 -d
+s.4A4wjt0Jkz7JuBii038BzknC
+```
+
+> Note: Make sure you have the permission to do above operation. Also we highly recommend not to use root token for using vault.
+
+For testing purpose, we are going to port forward the active vault pod, since the service we exposed for Vault is ClusterIP type. Make sure Vault cli is installed.
+
+```bash
+$ kubectl port-forward my-vault-684c485f7-7t6zs -n demo 8200:8200
+Forwarding from 127.0.0.1:8200 -> 8200
+
+# run following commands on another terminal
+
+
+$ export VAULT_SKIP_VERIFY="true"
+
+$ export VAULT_ADDR='https://127.0.0.1:8200'
+
+$ vault status
+Key Value
+--- -----
+Seal Type shamir
+Sealed false
+Total Shares 4
+Threshold 2
+Version 1.2.0
+Cluster Name vault-cluster-0650d1f5
+Cluster ID 8a8ebf6a-a06a-0e79-cc74-a66d0d52df85
+HA Enabled false
+
+```
+
+Set Vault token for further use. In this case, we are going to use root token(not recommended).
+
+```bash
+$ $ export VAULT_TOKEN='s.4A4wjt0Jkz7JuBii038BzknC'
+
+$ vault secrets list
+Path Type Accessor Description
+---- ---- -------- -----------
+cubbyhole/ cubbyhole cubbyhole_9ce16bb9 per-token private secret storage
+identity/ identity identity_45904875 identity store
+secret/ kv kv_22970276 key/value secret storage
+sys/ system system_51cd4d05 system endpoints used for control, policy and debugging
+
+```
+
+We are going to write,read and delete a secret in Vault
+
+```bash
+$ vault kv put secret/foo A=B
+Success! Data written to: secret/foo
+
+# see written secret data
+$ vault kv get secret/foo
+== Data ==
+Key Value
+--- -----
+A B
+
+# delete the secret
+$ vault kv delete secret/foo
+Success! Data deleted (if it existed) at: secret/foo
+
+# check the secret whether it is exist or not
+$ vault kv get secret/foo
+No value found at secret/foo
+```
diff --git a/content/docs/v2025.11.21/guides/platforms/eks.md b/content/docs/v2025.11.21/guides/platforms/eks.md
new file mode 100644
index 000000000..1b7247fa6
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/platforms/eks.md
@@ -0,0 +1,390 @@
+---
+title: Deploy Vault on Amazon EKS
+menu:
+ docs_v2025.11.21:
+ identifier: eks-platform
+ name: EKS
+ parent: platform-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Deploy Vault on Amazon EKS
+
+Here, we are going to deploy Vault in Amazon EKS using KubeVault operator. We are going to use [AWS S3 bucket](https://aws.amazon.com/s3/) as Vault backend and `awsKmsSsm` unsealer mode for automatically unsealing the Vault.
+
+## Before You Begin
+
+At first, you need to have an EKS cluster. If you don't already have a cluster, create one from [here](https://aws.amazon.com/eks/). You can use [eksctl](https://github.com/weaveworks/eksctl) command line tool to create EKS cluster easily.
+
+- Install KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+- You should be familiar with the following CRD:
+ - [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+ - [Unsealer](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview)
+ - [awsKmsSsm](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/aws_kms_ssm)
+
+- You will need a [AWS S3 Bucket](https://aws.amazon.com/s3/) to use it as Vault backend storage. In this tutorial, we are going to use `demo-vault-3` S3 bucket.
+
+- You will need a [AWS KMS key](https://aws.amazon.com/kms/) to use it for Vault unsealer. In this tutorial, we are going to use `218daa5f-7173-429e-a030-288b30761f79` as KMS key id.
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+### Provision Cluster
+
+We are going to use [eksctl](https://github.com/weaveworks/eksctl) to provision a cluster.
+
+```bash
+$ eksctl create cluster --name demo-cluster --nodes 1 --region us-east-1 --version 1.11
+```
+
+
+
+### Install KubeVault operator
+
+See [here](/docs/v2025.11.21/setup/README).
+
+```bash
+$ kubectl get pods -n kube-system
+NAME READY STATUS RESTARTS AGE
+vault-operator-798b75d78-qw74f 1/1 Running 1 2h
+```
+
+### Deploy Vault
+
+We will deploy `my-vault` on `demo` namespace. We will configure it for S3 backend. We will use `awsKmsSsm` for auto initializing and unsealing. We already created a S3 bucket `demo-vault-3` in `us-east-1` region.
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ s3:
+ bucket: "demo-vault-3"
+ region: "us-east-1"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ awsKmsSsm:
+ region: "us-east-1"
+ kmsKeyID: "218daa5f-7173-429e-a030-288b30761f79"
+ ssmKeyPrefix: "/cluster/demo"
+```
+
+Here, `spec.version` specifies the name of the [VaultServerVersion](/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion) CRD. If that does not exist, then create one.
+
+```bash
+$ kubectl get vaultserverversions
+NAME VERSION VAULT_IMAGE DEPRECATED AGE
+0.11.1 0.11.1 vault:0.11.1 false 12m
+
+$ kubectl get vaultserverversions/0.11.1 -o yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ labels:
+ app: vault-operator
+ name: 0.11.1
+spec:
+ deprecated: false
+ exporter:
+ image: kubevault/vault-exporter:canary
+ unsealer:
+ image: kubevault/vault-unsealer:0.2.0
+ vault:
+ image: vault:0.11.1
+ version: 0.11.1
+```
+
+Now, we are going to create `my-vault`
+
+```bash
+$ cat examples/guides/provider/eks/my-vault.yaml
+ apiVersion: kubevault.com/v1alpha1
+ kind: VaultServer
+ metadata:
+ name: my-vault
+ namespace: demo
+ spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ s3:
+ bucket: "demo-vault-3"
+ region: "us-east-1"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ awsKmsSsm:
+ region: "us-east-1"
+ kmsKeyID: "218daa5f-7173-429e-a030-288b30761f79"
+ ssmKeyPrefix: "/cluster/demo"
+
+$ kubectl apply -f docs/examples/guides/provider/eks/my-vault.yaml
+vaultserver.kubevault.com/my-vault created
+```
+
+> **Note**: Here, vault will attempt to retrieve credentials from the AWS metadata service. Please, make sure that it's has permission for s3 bucket, encryption key and amazon ssm. Also, you can specify dedicated credential for this using `s3.credentialSecret` and `awsKmsSsm.credentialSecret`. AWS policy are given at bottom of this tutorial.
+
+Check the `my-vault` status. It may take some time to reach `Running` stage.
+
+```bash
+$ kubectl get vaultserver/my-vault -n demo
+NAME NODES VERSION STATUS AGE
+my-vault 1 0.11.1 Running 3m
+```
+
+`status` field in `my-vault` will show more detail information.
+
+```bash
+$ kubectl get vaultserver/my-vault -n demo -o json | jq '.status'
+{
+ "initialized": true,
+ "observedGeneration": "1$6208915667192219204",
+ "phase": "Running",
+ "updatedNodes": [
+ "my-vault-6f48b4d96f-mzvgm"
+ ],
+ "vaultStatus": {
+ "active": "my-vault-6f48b4d96f-mzvgm",
+ "unsealed": [
+ "my-vault-6f48b4d96f-mzvgm"
+ ]
+ }
+}
+
+```
+
+KubeVault operator will create a service `{metadata.name}` for `my-vault` in the same namespace. For this case, service name is `my-vault`. You can specify service configuration in [spec.serviceTemplate](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver#specservicetemplate). KubeVault operator will use that configuration to create service.
+
+```bash
+$ kubectl get services -n demo
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+my-vault ClusterIP 10.100.237.152 8200/TCP,8201/TCP,9102/TCP 46m
+```
+
+The configuration used to run Vault can be found in `{metadata.name}-vault-config` configMap. For this case, it is `my-vault-vault-config`. Confidential data are omitted in this configMap.
+
+```bash
+$ kubectl get configmaps -n demo
+NAME DATA AGE
+my-vault-vault-config 1 49m
+
+$ kubectl get configmaps/my-vault-vault-config -n demo -o yaml
+apiVersion: v1
+data:
+ vault.hcl: |2-
+
+ listener "tcp" {
+ address = "0.0.0.0:8200"
+ cluster_address = "0.0.0.0:8201"
+ tls_cert_file = "/etc/vault/tls/server.crt"
+ tls_key_file = "/etc/vault/tls/server.key"
+ }
+
+ storage "s3" {
+ bucket = "demo-vault-3"
+ region = "us-east-1"
+ }
+
+ telemetry {
+ statsd_address = "0.0.0.0:9125"
+ }
+kind: ConfigMap
+metadata:
+ creationTimestamp: 2018-12-22T04:30:07Z
+ labels:
+ app: vault
+ vault_cluster: my-vault
+ name: my-vault-vault-config
+ namespace: demo
+
+```
+
+In this `my-vault`, KubeVault operator will use self-signed certificates for Vault and also will create `{metadata.name}-vault-tls` secret containing certificates. You can optionally specify certificates in [spec.tls](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver#spectls).
+
+```bash
+$ kubectl get secrets -n demo
+NAME TYPE DATA AGE
+my-vault-vault-tls Opaque 3 1h
+```
+
+We can see unseal keys and root token in AWS System Manager Parameter Store in the `unsealer.region` region. For this case, in `us-east-1` region.
+
+
+
+### Using Vault
+
+Download and decrypt the root token:
+```bash
+$ aws ssm get-parameter --name vault-root-token --region us-east-1 --output json | jq -r '.Parameter.Value' | base64 -d - > root.enc
+
+$ tree .
+.
+└── root.enc
+
+$ aws kms decrypt --ciphertext-blob fileb://root.enc --output text --query Plaintext --encryption-context "Tool=vault-unsealer" --region us-east-1 | base64 -d -
+9116f849-2085-9c28-015f-aec3e184e90f
+```
+
+> Note: Make sure you have the permission to do above operation. Also we highly recommend not to use root token for using vault.
+
+For testing purpose, we are going to port forward the active vault pod, since the service we exposed for Vault is ClusterIP type. Make sure Vault cli is installed.
+
+```bash
+$ kubectl port-forward my-vault-6f48b4d96f-mzvgm -n demo 8200:8200
+Forwarding from 127.0.0.1:8200 -> 8200
+
+# run following commands on another terminal
+$ export VAULT_SKIP_VERIFY="true"
+
+$ export VAULT_ADDR='https://127.0.0.1:8200'
+
+$ vault status
+Key Value
+--- -----
+Seal Type shamir
+Sealed false
+Total Shares 4
+Threshold 2
+Version 0.11.1
+Cluster Name vault-cluster-e4eda2ce
+Cluster ID d05fec0c-7e09-20f6-0d88-0283ed9c7b72
+HA Enabled false
+
+```
+
+Set Vault token for further use. In this case, we are going to use root token(not recommended).
+
+```bash
+$ export VAULT_TOKEN='9116f849-2085-9c28-015f-aec3e184e90f'
+
+$ vault secrets list
+Path Type Accessor Description
+---- ---- -------- -----------
+cubbyhole/ cubbyhole cubbyhole_9ce16bb9 per-token private secret storage
+identity/ identity identity_45904875 identity store
+secret/ kv kv_22970276 key/value secret storage
+sys/ system system_51cd4d05 system endpoints used for control, policy and debugging
+
+```
+
+We are going to write,read and delete a secret in Vault
+
+```bash
+$ vault kv put secret/foo A=B
+Success! Data written to: secret/foo
+
+# see written secret data
+$ vault kv get secret/foo
+== Data ==
+Key Value
+--- -----
+A B
+
+# delete the secret
+$ vault kv delete secret/foo
+Success! Data deleted (if it existed) at: secret/foo
+
+# check the secret whether it is exist or not
+$ vault kv get secret/foo
+No value found at secret/foo
+
+```
+
+## AWS IAM Policy
+
+Policy for S3 bucket access:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "VaultListBuckets",
+ "Effect": "Allow",
+ "Action": [
+ "s3:ListAllMyBuckets",
+ "s3:HeadBucket"
+ ],
+ "Resource": "*"
+ },
+ {
+ "Sid": "VaultAccessBuckets",
+ "Effect": "Allow",
+ "Action": "s3:*",
+ "Resource": [
+ "arn:aws:s3:::",
+ "arn:aws:s3:::/*"
+ ]
+ }
+ ]
+}
+```
+
+Policy for KMS:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "VaultUnsealerEncryptDecryptKms",
+ "Effect": "Allow",
+ "Action": [
+ "kms:Decrypt",
+ "kms:Encrypt",
+ "kms:DescribeKey"
+ ],
+ "Resource": "arn:aws:kms:::key/"
+ },
+ {
+ "Sid": "VaultUnsealerGetKMS",
+ "Effect": "Allow",
+ "Action": "kms:ListKeys",
+ "Resource": "*"
+ }
+ ]
+}
+```
+
+Policy for SSM:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "VaultUnsealerParametersAccess",
+ "Effect": "Allow",
+ "Action": [
+ "ssm:PutParameter",
+ "ssm:DeleteParameter",
+ "ssm:GetParameters"
+ ],
+ "Resource": "arn:aws:ssm:*:*:parameter/*"
+ }
+ ]
+}
+```
diff --git a/content/docs/v2025.11.21/guides/platforms/external-vault.md b/content/docs/v2025.11.21/guides/platforms/external-vault.md
new file mode 100644
index 000000000..7211cf72f
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/platforms/external-vault.md
@@ -0,0 +1,214 @@
+---
+title: Manage External Vault using KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: external-vault-platform
+ name: External Vault
+ parent: platform-guides
+ weight: 25
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage External Vault using KubeVault operator
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. These Vault servers can be running outside a Kubernetes cluster or running inside a Kubernetes cluster but provisioned using a Helm chart.
+
+The KubeVault operator can perform the following operations for externally provisioned Vault servers:
+
+- Manage Vault [policy](https://www.vaultproject.io/docs/concepts/policies.html) using [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding). Guides can be found [here](/docs/v2025.11.21/guides/policy-management/overview).
+
+- Manage [AWS secret engine](https://www.vaultproject.io/docs/secrets/aws/index.html#aws-secrets-engine) using [AWSRole](/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole) and [SecretAccessRequest](/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request). Guides can be found [here](/docs/v2025.11.21/guides/secret-engines/aws/overview).
+
+- Manage [PostgreSQL Database secret engine](https://www.vaultproject.io/api/secret/databases/postgresql.html) using [PostgresRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole) and [SecretAccessRequest](/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request). Guides can be found [here](/docs/v2025.11.21/guides/secret-engines/postgres/overview).
+
+- Manage [MongoDB Database secret engine](https://www.vaultproject.io/api/secret/databases/mongodb.html) using [MongoDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb) and [SecretAccessRequest](/docs/v2025.11.21/concepts/secret-engine-crds/secret-access-request). Guides can be found [here](/docs/v2025.11.21/guides/secret-engines/mongodb/overview).
+
+In this tutorial, we are going to show how we can use KubeVault operator for Vault which is not provisioned by KubeVault operator.
+
+## Connecting with Vault
+
+We have a Vault running which can be accessible by the address `http://vault.default.svc:8200` from Kubernetes cluster. KubeVault operator use [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) to communicate with Vault. [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) provides a way of specifying Vault connection information and credential. Following authentication methods are currently supported by KubeVault operator using AppBinding:
+
+- [Token Auth Method](https://www.vaultproject.io/docs/auth/token.html#token-auth-method)
+- [Kubernetes Auth Method](https://www.vaultproject.io/docs/auth/kubernetes.html)
+- [AWS IAM Auth Method](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method)
+- [Userpass Auth Method](https://www.vaultproject.io/docs/auth/userpass.html)
+- [TLS Certificates Auth Method](https://www.vaultproject.io/docs/auth/cert.html)
+
+Vault authentication using AppBinding can be found in [here](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/overview).
+
+In this tutorial, we are going to use [Kubernetes Auth Method](https://www.vaultproject.io/docs/auth/kubernetes.html).
+
+Now, we are going to enable and configure [Kubenetes auth](https://www.vaultproject.io/docs/auth/kubernetes.html) in Vault.
+
+- Create a service account and cluster role bindings that allow that service account to authenticate with the review token API.
+
+ ```bash
+ $ cat docs/examples/guides/provider/external-vault/token-reviewer-sa.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: token-reviewer
+ namespace: demo
+
+ $ cat docs/examples/guides/provider/external-vault/token-review-binding.yaml
+ apiVersion: rbac.authorization.k8s.io/v1beta1
+ kind: ClusterRoleBinding
+ metadata:
+ name: role-tokenreview-binding
+ roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: system:auth-delegator
+ subjects:
+ - kind: ServiceAccount
+ name: token-reviewer
+ namespace: demo
+
+ $ kubectl apply -f docs/examples/guides/provider/external-vault/token-reviewer-sa.yaml
+ serviceaccount/token-reviewer created
+
+ $ kubectl apply -f docs/examples/guides/provider/external-vault/token-review-binding.yaml
+ clusterrolebinding.rbac.authorization.k8s.io/role-tokenreview-binding created
+ ```
+
+- Enable Kubernetes auth in Vault.
+
+ ```bash
+ $ vault auth enable kubernetes
+ Success! Enabled Kubernetes auth method at: kubernetes/
+ ```
+
+- Configure Kubernetes auth in Vault.
+
+ ```bash
+ $ kubectl get sa token-reviewer -n demo -o jsonpath="{.secrets[*]['name']}"
+ token-reviewer-token-fvqsv
+
+ $ export SA_JWT_TOKEN=$(kubectl get secret token-reviewer-token-fvqsv -n demo -o jsonpath="{.data.token}" | base64 --decode; echo)
+
+ $ export SA_CA_CRT=$(kubectl get secret token-reviewer-token-fvqsv -n demo -o jsonpath="{.data['ca\.crt']}" | base64 --decode; echo)
+
+ $ vault write auth/kubernetes/config \
+ token_reviewer_jwt="$SA_JWT_TOKEN" \
+ kubernetes_host="https://192.168.99.100:8443" \
+ kubernetes_ca_cert="$SA_CA_CRT"
+ Success! Data written to: auth/kubernetes/config
+ ```
+
+We are going to create a Vault [policy](https://www.vaultproject.io/docs/concepts/policies.html). It has permission to manage policy and Kubernetes role in Vault.
+
+```bash
+$ cat docs/examples/guides/provider/external-vault/policy-admin.hcl
+path "sys/policy/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
+
+path "sys/policy" {
+ capabilities = ["read", "list"]
+}
+
+path "auth/kubernetes/role" {
+ capabilities = ["read", "list"]
+}
+
+path "auth/kubernetes/role/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+}
+
+$ vault policy write policy-admin docs/examples/guides/provider/external-vault/policy-admin.hcl
+Success! Uploaded policy: policy-admin
+```
+
+We are going to assign the above policy to a service account `policy-admin` so that we can use that service account to manage policy and Kubernetes role.
+
+```bash
+$ cat docs/examples/guides/provider/external-vault/policy-admin-sa.yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: policy-admin
+ namespace: demo
+
+$ kubectl apply -f docs/examples/guides/provider/external-vault/policy-admin-sa.yaml
+serviceaccount/policy-admin created
+
+$ vault write auth/kubernetes/role/policy-admin-role \
+ bound_service_account_names=policy-admin \
+ bound_service_account_namespaces=demo \
+ policies=policy-admin \
+ ttl=24h
+Success! Data written to: auth/kubernetes/role/policy-admin-role
+```
+
+Now, we are going create AppBinding that will contain Vault information. For authentication, service account `policy-admin` and Kubernetes role `policy-admin-role` will be used.
+
+```bash
+$ cat docs/examples/guides/provider/external-vault/vault-app.yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ clientConfig:
+ url: http://vault.default.svc:8200
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9ERXlNamN3TkRVNU1qVmFGdzB5T0RFeU1qUXdORFU1TWpWYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVhid2wyQ1NNc2VQTU5RRzhMd3dUVWVOCkI1T05oSTlDNzFtdUoyZEZjTTlUc1VDQnlRRk1weUc5dWFvV3J1ZDhtSWpwMVl3MmVIUW5udmoybXRmWGcrWFcKSThCYkJUaUFKMWxMMFE5MlV0a1BLczlXWEt6dTN0SjJUR1hRRDhhbHZhZ0JrR1ViOFJYaUNqK2pnc1p6TDRvQQpNRWszSU9jS0xnMm9ldFZNQ0hwNktpWTBnQkZiUWdJZ1A1TnFwbksrbU02ZTc1ZW5hWEdBK2V1d09FT0YwV0Z2CmxGQmgzSEY5QlBGdTJKbkZQUlpHVDJKajBRR1FNeUxodEY5Tk1pZTdkQnhiTWhRVitvUXp2d1EvaXk1Q2pndXQKeDc3d29HQ2JtM0o4cXRybUg2Tjl6Tlc3WlR0YTdLd05PTmFoSUFEMSsrQm5rc3JvYi9BYWRKT0tMN2dLYndJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFXeWFsdUt3Wk1COWtZOEU5WkdJcHJkZFQyZnFTd0lEOUQzVjN5anBlaDVCOUZHN1UKSS8wNmpuRVcyaWpESXNHNkFDZzJKOXdyaSttZ2VIa2Y2WFFNWjFwZHRWeDZLVWplWTVnZStzcGdCRTEyR2NPdwpxMUhJb0NrekVBMk5HOGRNRGM4dkQ5WHBQWGwxdW5veWN4Y0VMeFVRSC9PRlc4eHJxNU9vcXVYUkxMMnlKcXNGCmlvM2lJV3EvU09Yajc4MVp6MW5BV1JSNCtSYW1KWjlOcUNjb1Z3b3R6VzI1UWJKWWJ3QzJOSkNENEFwOUtXUjUKU2w2blk3NVMybEdSRENsQkNnN2VRdzcwU25seW5mb3RaTUpKdmFzbStrOWR3U0xtSDh2RDNMMGNGOW5SOENTSgpiTjBiZzczeVlWRHgyY3JRYk0zcko4dUJnY3BsWlRpUy91SXJ2QT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes
+ vaultRole: policy-admin-role
+ kubernetes:
+ serviceAccountName: policy-admin
+
+$ kubectl apply -f docs/examples/guides/provider/external-vault/vault-app.yaml
+appbinding.appcatalog.appscode.com/vault-app created
+```
+
+If KubeVault operator uses the above AppBinding `vault-app`, then it will have the permission that is given to service account `policy-admin` by `policy-admin-role` role. Now, we are going to create [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) using `vault-app` AppBinding.
+
+```bash
+$ cat docs/examples/guides/provider/external-vault/demo-policy.yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: demo-policy
+ namespace: demo
+spec:
+ ref:
+ name: vault-app
+ namespace: demo
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+ }
+
+$ kubectl apply -f docs/examples/guides/provider/external-vault/demo-policy.yaml
+vaultpolicy.policy.kubevault.com/demo-policy created
+
+$ kubectl get vaultpolicies -n demo
+NAME STATUS AGE
+demo-policy Success 3s
+
+# To resolve the naming conflict, name of policy in Vault will follow this format: 'k8s.{clusterName}.{metadata.namespace}.{metadata.name}'. For this case, it is 'k8s.-.demo.demo-policy'.
+$ vault policy list
+default
+k8s.-.demo.demo-policy
+policy-admin
+root
+
+$ vault policy read k8s.-.demo.demo-policy
+path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+}
+```
diff --git a/content/docs/v2025.11.21/guides/platforms/gke.md b/content/docs/v2025.11.21/guides/platforms/gke.md
new file mode 100644
index 000000000..f5d9a3ddc
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/platforms/gke.md
@@ -0,0 +1,373 @@
+---
+title: Deploy Vault on Google Kubernetes Engine (GKE)
+menu:
+ docs_v2025.11.21:
+ identifier: gke-platform
+ name: GKE
+ parent: platform-guides
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Deploy Vault on Google Kubernetes Engine (GKE)
+
+Here, we are going to deploy Vault in GKE using KubeVault operator. We are going to use [GCS bucket](https://cloud.google.com/storage/docs/) as Vault backend and `googleKmsGcs` unsealer mode for automatically unsealing the Vault.
+
+## Before You Begin
+
+At first, you need to have a GKE cluster. If you don't already have a cluster, create one from [here](https://cloud.google.com/kubernetes-engine/).
+
+- Install KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+- You should be familiar with the following CRD:
+ - [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+ - [Unsealer](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/overview)
+ - [googleKmsGcs](/docs/v2025.11.21/concepts/vault-server-crds/unsealer/google_kms_gcs)
+
+- You will need a [GCS bucket](https://cloud.google.com/storage/docs/) to use it as Vault backend storage. In this tutorial, we are going to use `demo-vault` GCS bucket.
+
+- You will need a [Google KMS](https://cloud.google.com/kms/) crypto key to use it for Vault unsealer. In this tutorial, we are going to use key `vault-key` int `vault` key ring.
+
+
+### Provision Cluster
+
+We are going to use [gcloud](https://cloud.google.com/sdk/gcloud/) to provision a cluster.
+
+```bash
+$ gcloud container clusters create vault \
+ --enable-autorepair \
+ --cluster-version 1.11.4-gke.13 \
+ --machine-type n1-standard-2 \
+ --num-nodes 1 \
+ --zone us-east1-b \
+ --project ackube
+```
+
+
+
+Now, we are going to create service account and set access permission to this service account.
+
+```bash
+$ gcloud iam service-accounts create vault-sa \
+ --display-name "vault service account" \
+ --project ackube
+Created service account [vault-sa].
+```
+
+Grant access to bucket:
+
+```bash
+$ gsutil iam ch \
+ serviceAccount:vault-sa@ackube.iam.gserviceaccount.com:objectAdmin \
+ gs://demo-vault
+```
+
+```bash
+$ gsutil iam ch \
+ serviceAccount:vault-sa@ackube.iam.gserviceaccount.com:legacyBucketReader \
+ gs://demo-vault
+```
+
+Grant access to the crypto key:
+
+```bash
+$ gcloud kms keys add-iam-policy-binding \
+ vault-key \
+ --location global \
+ --keyring vault \
+ --member serviceAccount:vault-sa@ackube.iam.gserviceaccount.com \
+ --role roles/cloudkms.cryptoKeyEncrypterDecrypter \
+ --project ackube
+```
+
+### Install KubeVault operator
+
+See [here](/docs/v2025.11.21/setup/README).
+
+```bash
+$ kubectl get pods -n kube-system
+NAME READY STATUS RESTARTS AGE
+vault-operator-7cc8cdf7f6-jmhg4 1/1 Running 6 8m
+```
+
+### Deploy Vault
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+We will deploy `my-vault` on `demo` namespace. We will configure it for GCS backend. We will use `googleKmsGcs` for auto initializing and unsealing. We already created a GCS bucket `demo-vault`.
+
+```yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ gcs:
+ bucket: "demo-vault"
+ credentialSecret: "google-cred"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ googleKmsGcs:
+ bucket: "demo-vault"
+ kmsProject: "ackube"
+ kmsLocation: "global"
+ kmsKeyRing: "vault"
+ kmsCryptoKey: "vault-key"
+ credentialSecret: "google-cred"
+```
+
+Here, `spec.version` specifies the name of the [VaultServerVersion](/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion) CRD. If that does not exist, then create one.
+
+```bash
+$ kubectl get vaultserverversions
+NAME VERSION VAULT_IMAGE DEPRECATED AGE
+1.2.0 1.2.0 vault:1.2.0 false 1m
+
+$ kubectl get vaultserverversions/1.2.0 -o yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ version: 1.2.0
+ deprecated: false
+ vault:
+ image: vault:1.2.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ exporter:
+ image: kubevault/vault-exporter:0.1.0
+```
+
+`spec.backend.gcs.credentialSecret` and `spec.unsealer.mode.googleKmsGcs.credentialSecret` specifies the name of the Kubernetes secret containing `vault-sa@ackube.iam.gserviceaccount.com` credential.
+
+```bash
+$ kubectl get secrets/google-cred -n demo -o yaml
+apiVersion: v1
+data:
+ sa.json: ewogICJ0eXBlIjogIn...
+kind: Secret
+metadata:
+ name: google-cred
+ namespace: demo
+type: Opaque
+
+```
+
+Now, we are going to create `my-vault` in `demo` namespace.
+
+```bash
+$ cat examples/guides/provider/gke/my-vault.yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ gcs:
+ bucket: "demo-vault"
+ credentialSecret: "google-cred"
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ googleKmsGcs:
+ bucket: "demo-vault"
+ kmsProject: "ackube"
+ kmsLocation: "global"
+ kmsKeyRing: "vault"
+ kmsCryptoKey: "vault-key"
+ credentialSecret: "google-cred"
+
+$ kubectl apply -f docs/examples/guides/provider/gke/my-vault.yaml
+vaultserver.kubevault.com/my-vault created
+```
+
+Check the `my-vault` status. It may take some time to reach `Running` stage.
+
+```bash
+$ kubectl get vaultserver/my-vault -n demo
+NAME NODES VERSION STATUS AGE
+my-vault 1 1.2.0 Running 2m
+```
+
+`status` field in `my-vault` will show more detail information.
+
+```bash
+$ kubectl get vaultserver/my-vault -n demo -o json | jq '.status'
+{
+ "clientPort": 8200,
+ "initialized": true,
+ "observedGeneration": "1$6208915667192219204",
+ "phase": "Running",
+ "serviceName": "my-vault",
+ "updatedNodes": [
+ "my-vault-75b6f87dbb-kq4tp"
+ ],
+ "vaultStatus": {
+ "active": "my-vault-75b6f87dbb-kq4tp",
+ "unsealed": [
+ "my-vault-75b6f87dbb-kq4tp"
+ ]
+ }
+}
+
+```
+
+KubeVault operator will create a service `{metadata.name}` for `my-vault` in the same namespace. For this case, service name is `my-vault`. You can specify service configuration in [spec.serviceTemplate](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver#specservicetemplate). KubeVault operator will use that configuration to create service.
+
+```bash
+$ kubectl get services -n demo
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+my-vault ClusterIP 10.3.244.122 8200/TCP,8201/TCP,9102/TCP 4m
+```
+
+The configuration used to run Vault can be found in `{metadata.name}-vault-config` configMap. For this case, it is `my-vault-vault-config`. Confidential data are omitted in this configMap.
+
+```bash
+$ kubectl get configmaps -n demo
+NAME DATA AGE
+my-vault-vault-config 1 49m
+
+$ kubectl get configmaps/my-vault-vault-config -n demo -o yaml
+apiVersion: v1
+data:
+ vault.hcl: |2-
+
+ listener "tcp" {
+ address = "0.0.0.0:8200"
+ cluster_address = "0.0.0.0:8201"
+ tls_cert_file = "/etc/vault/tls/server.crt"
+ tls_key_file = "/etc/vault/tls/server.key"
+ }
+
+ storage "gcs" {
+ bucket = "demo-vault"
+ }
+
+ telemetry {
+ statsd_address = "0.0.0.0:9125"
+ }
+kind: ConfigMap
+metadata:
+ name: my-vault-vault-config
+ namespace: demo
+```
+
+In this `my-vault`, KubeVault operator will use self-signed certificates for Vault and also will create `{metadata.name}-vault-tls` secret containing certificates. You can optionally specify certificates in [spec.tls](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver#spectls).
+
+```bash
+$ kubectl get secrets -n demo
+NAME TYPE DATA AGE
+my-vault-vault-tls Opaque 3 1h
+```
+
+We can see unseal keys and root token in `demo-vault` bucket.
+
+
+
+### Using Vault
+
+Download and decrypt the root token:
+
+```bash
+$ export VAULT_TOKEN=$(gsutil cat gs://demo-vault/vault-root-token | \
+ gcloud kms decrypt \
+ --project ackube \
+ --location global \
+ --keyring vault \
+ --key vault-key \
+ --ciphertext-file - \
+ --plaintext-file - )
+
+$ echo $VAULT_TOKEN
+s.5DEELd1OiRmwfnrqfqQeguug
+```
+
+> Note: Make sure you have the permission to do above operation. Also we highly recommend not to use root token for using vault.
+
+For testing purpose, we are going to port forward the active vault pod, since the service we exposed for Vault is ClusterIP type. Make sure Vault cli is installed.
+
+```bash
+$ kubectl port-forward my-vault-75b6f87dbb-kq4tp -n demo 8200:8200
+Forwarding from 127.0.0.1:8200 -> 8200
+
+# run following commands on another terminal
+$ export VAULT_SKIP_VERIFY="true"
+
+$ export VAULT_ADDR='https://127.0.0.1:8200'
+
+$ vault status
+Key Value
+--- -----
+Seal Type shamir
+Sealed false
+Total Shares 4
+Threshold 2
+Version 1.2.0
+Cluster Name vault-cluster-84d6b1b0
+Cluster ID bb6487bb-0deb-9e95-144e-e85c9ebd07eb
+HA Enabled false
+
+```
+
+Set Vault token for further use. In this case, we are going to use root token(not recommended).
+
+```bash
+$ export VAULT_TOKEN='s.5DEELd1OiRmwfnrqfqQeguug'
+
+$ vault secrets list
+Path Type Accessor Description
+---- ---- -------- -----------
+cubbyhole/ cubbyhole cubbyhole_9ce16bb9 per-token private secret storage
+identity/ identity identity_45904875 identity store
+secret/ kv kv_22970276 key/value secret storage
+sys/ system system_51cd4d05 system endpoints used for control, policy and debugging
+
+```
+
+We are going to write,read and delete a secret in Vault
+
+```bash
+$ vault kv put secret/foo A=B
+Success! Data written to: secret/foo
+
+# see written secret data
+$ vault kv get secret/foo
+== Data ==
+Key Value
+--- -----
+A B
+
+# delete the secret
+$ vault kv delete secret/foo
+Success! Data deleted (if it existed) at: secret/foo
+
+# check the secret whether it is exist or not
+$ vault kv get secret/foo
+No value found at secret/foo
+
+```
diff --git a/content/docs/v2025.11.21/guides/platforms/multi-cluster-vault.md b/content/docs/v2025.11.21/guides/platforms/multi-cluster-vault.md
new file mode 100644
index 000000000..21ae06a3c
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/platforms/multi-cluster-vault.md
@@ -0,0 +1,224 @@
+---
+title: Use a Vault Server with Multiple Kubernetes Clusters
+menu:
+ docs_v2025.11.21:
+ identifier: multi-cluster-platform
+ name: Multi-Cluster
+ parent: platform-guides
+ weight: 100
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Use a Vault Server with Multiple Kubernetes Clusters
+
+In this tutorial, we are going to show how to use KubeVault operators in multiple Kubernetes clusters against a shared Vault server.
+
+To being with, we have created two GKE clusters.
+
+
+
+We are going to install KubeVault operator in `demo-cluster-1` using Helm 3. We are going to set `--cluster-name` flag. This flag value will be used by KubeVault operator when creating resources in Vault.
+
+```bash
+$ kubectl config current-context
+gke_ackube_us-central1-a_demo-cluster-1
+
+$ helm install kubevault oci://ghcr.io/appscode-charts/kubevault \
+ --version {{< param "info.version" >}} \
+ --namespace kubevault --create-namespace \
+ --set clusterName=demo-cluster-1
+
+$ kubectl get pods -n kube-system
+NAME READY STATUS RESTARTS AGE
+vault-operator-5fc7666575-8v6ft 1/1 Running 0 1h
+```
+
+We are going to deploy Vault in `demo-cluster-1` using KubeVault operator. Guides to deploy Vault in GKE can be found [here](/docs/v2025.11.21/guides/platforms/gke).
+
+```bash
+$ kubectl get vaultserverversions/1.2.0 -o yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.2.0
+spec:
+ version: 1.2.0
+ deprecated: false
+ vault:
+ image: vault:1.2.0
+ unsealer:
+ image: kubevault/vault-unsealer:v0.3.0
+ exporter:
+ image: kubevault/vault-exporter:0.1.0
+
+$ cat examples/guides/provider/multi-cluster/my-vault.yaml
+cat examples/guides/provider/multi-cluster/my-vault.yaml
+apiVersion: kubevault.com/v1alpha1
+kind: VaultServer
+metadata:
+ name: my-vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: "1.2.0"
+ backend:
+ gcs:
+ bucket: "demo-vault"
+ credentialSecret: "google-cred"
+ serviceTemplate:
+ spec:
+ type: LoadBalancer
+ loadBalancerIP: 104.155.177.205
+ tls:
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9UQXhNRGN3T1RNNE1UaGFGdzB5T1RBeE1EUXdPVE00TVRoYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdXZxWFJrMGZrMHNWMFpoMDQwd0FaVTBhCkhlRW9vUnlVMlpaaGtjS3dPS201N2pUWkJaMEkvMjg2dTNpUVFpc2tMTFNjYUtvaHp0c012RXFCU0JpNU5MNEMKVXVQbm5CZklIVVo1UDhwQWNOUXJ5SURETGxXZTFBTEVKU0N0L3daRG5mMkRPdXZGSVMybFJVZDV2WFp1dlVjWgptdml5T3VUOW9CclNwNkh5YUpRYkUrZk1qQTRvZ0ZoQWZmN1djMm1DVk1jam8wU3htK2lrVWxVZWhXdWd4T3M0Cm5GUG5pWmt3a1h0KzFweU45WjltclhwUTlZM3FvdGlmdk1aUnVhVS9hbjUxOUZqSWdzVUZtRGVoZ3c3blJwYkkKZ0NGeUNPSlc5ZTNDczNRVTViVTJYUk1leDBlTDZReTZJY2dDdGZIRmpBeGhjUHAzeEJjRW5XSEdONDM2dHdJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFUMzFuQUNpMmNySW0rWCtGZUNocjJJcnhZeGFDSlpLNW92Y1Jqem5TZFR0N2JadWoKcTVZQW5jbitESDlxUURkczFVTEdjR1ZISlpiS3RORU9GVVlJbDVXYUZBVnNBMTJoaURCZnJXc24ydUV6K0pUVwovcStLSVE0OW1LUWV1TG80bkVoQnRJYjJzaXBKMmxmUEVyUXhHQllrZ3lOT05zOTN5NEdPVXU4dVdBaUFqZ21oCmM4a1QzTVV0ZVRNUHczQ3JKU2ZtbGUxQkk0bkNPNXEreW54Zk56SXZqZU5PYnNvVTdOOVhoZTdCQjZSSzQ1akgKVW41bzBTZkkrR0dYU0l5eWFxVHlJRUJkK3Nub1pMRWQzMm9DeWJFOC9QajE3T3BDZHhhd0ZnZWJGUnNEQ2pkRQo0bUI2RmVPMi9md3VFUk5lTlZnczBHMjBPc2t4cDJoTWJRYUlJZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
+ tlsSecret: vault-tls
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ googleKmsGcs:
+ bucket: "demo-vault"
+ kmsProject: "ackube"
+ kmsLocation: "global"
+ kmsKeyRing: "vault"
+ kmsCryptoKey: "vault-key"
+ credentialSecret: "google-cred"
+
+$ kubectl apply -f docs/examples/guides/provider/multi-cluster/my-vault.yaml
+vaultserver.kubevault.com/my-vault created
+
+$ kubectl get vaultserver my-vault -n demo
+NAME NODES VERSION STATUS AGE
+my-vault 1 1.2.0 Running 1m
+
+$ kubectl get services -n demo
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+my-vault LoadBalancer 10.3.251.241 104.155.177.205 8200:31542/TCP,8201:31390/TCP,9102:30911/TCP 2m
+```
+
+Now we are going to create `demo-policy-secret-admin` [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) in `demo-cluster-1`. Guides to manage policy in Vault can be found [here](/docs/v2025.11.21/guides/policy-management/overview).
+
+```bash
+$ cat examples/guides/provider/multi-cluster/demo-policy-secret-admin.yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: demo-policy-secret-admin
+ namespace: demo
+spec:
+ ref:
+ name: my-vault
+ namespace: demo
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["create", "read", "update", "delete", "list"]
+ }
+$ kubectl apply -f docs/examples/guides/provider/multi-cluster/demo-policy-secret-admin.yaml
+vaultpolicy.policy.kubevault.com/demo-policy-secret-admin created
+
+$ kubectl get vaultpolicies -n demo
+NAME STATUS AGE
+demo-policy-secret-admin Success 1m
+```
+
+Check the created `demo-policy-secret-admin` [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) in Vault. To resolve the naming conflict, name of policy in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. For this case, it is `k8s.demo-cluster-1.demo.demo-policy-secret-admin`.
+
+```bash
+$ export VAULT_ADDR='https://104.155.177.205:31542'
+
+$ export VAULT_CACERT="cert/ca.crt"
+
+$ export VAULT_TOKEN="s.KLJFDIUJLKDFDLKFJ"
+
+$ vault policy list
+default
+k8s.demo-cluster-1.demo.demo-policy-secret-admin
+my-vault-policy-controller
+root
+
+```
+
+We are going to install KubeVault operator in `demo-cluster-2` using Helm 3. We are going to set `--cluster-name`, this flag value will be used by KubeVault operator when creating resource in Vault.
+
+```bash
+$ kubectl config current-context
+gke_ackube_us-central1-a_demo-cluster-2
+
+$ helm install kubevault oci://ghcr.io/appscode-charts/kubevault \
+ --version {{< param "info.version" >}} \
+ --namespace kubevault --create-namespace \
+ --set clusterName=demo-cluster-2
+
+$ kubectl get pods -n kube-system
+NAME READY STATUS RESTARTS AGE
+vault-operator-5fc7666575-8v6ft 1/1 Running 0 1h
+```
+
+Now we are going to create an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and credential information of the Vault that is deployed in `demo-cluster-1`. In this AppBinding, we are going to use [token auth](https://www.vaultproject.io/docs/auth/token.html#token-auth-method). Guides to Vault authentication using AppBinding can be found [here](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/overview).
+
+```bash
+$ cat examples/guides/provider/multi-cluster/vault-app.yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault-app
+ namespace: demo
+spec:
+ secret:
+ name: vault-token
+ clientConfig:
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9UQXhNRGN3T1RNNE1UaGFGdzB5T1RBeE1EUXdPVE00TVRoYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdXZxWFJrMGZrMHNWMFpoMDQwd0FaVTBhCkhlRW9vUnlVMlpaaGtjS3dPS201N2pUWkJaMEkvMjg2dTNpUVFpc2tMTFNjYUtvaHp0c012RXFCU0JpNU5MNEMKVXVQbm5CZklIVVo1UDhwQWNOUXJ5SURETGxXZTFBTEVKU0N0L3daRG5mMkRPdXZGSVMybFJVZDV2WFp1dlVjWgptdml5T3VUOW9CclNwNkh5YUpRYkUrZk1qQTRvZ0ZoQWZmN1djMm1DVk1jam8wU3htK2lrVWxVZWhXdWd4T3M0Cm5GUG5pWmt3a1h0KzFweU45WjltclhwUTlZM3FvdGlmdk1aUnVhVS9hbjUxOUZqSWdzVUZtRGVoZ3c3blJwYkkKZ0NGeUNPSlc5ZTNDczNRVTViVTJYUk1leDBlTDZReTZJY2dDdGZIRmpBeGhjUHAzeEJjRW5XSEdONDM2dHdJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFUMzFuQUNpMmNySW0rWCtGZUNocjJJcnhZeGFDSlpLNW92Y1Jqem5TZFR0N2JadWoKcTVZQW5jbitESDlxUURkczFVTEdjR1ZISlpiS3RORU9GVVlJbDVXYUZBVnNBMTJoaURCZnJXc24ydUV6K0pUVwovcStLSVE0OW1LUWV1TG80bkVoQnRJYjJzaXBKMmxmUEVyUXhHQllrZ3lOT05zOTN5NEdPVXU4dVdBaUFqZ21oCmM4a1QzTVV0ZVRNUHczQ3JKU2ZtbGUxQkk0bkNPNXEreW54Zk56SXZqZU5PYnNvVTdOOVhoZTdCQjZSSzQ1akgKVW41bzBTZkkrR0dYU0l5eWFxVHlJRUJkK3Nub1pMRWQzMm9DeWJFOC9QajE3T3BDZHhhd0ZnZWJGUnNEQ2pkRQo0bUI2RmVPMi9md3VFUk5lTlZnczBHMjBPc2t4cDJoTWJRYUlJZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
+ url: https://104.155.177.205:8200
+
+$ kubectl apply -f docs/examples/guides/provider/multi-cluster/vault-app.yaml
+appbinding.appcatalog.appscode.com/vault-app created
+```
+
+Now we are going to create `demo-policy-secret-reader` [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) in `demo-cluster-2`.
+
+```bash
+$ cat examples/guides/provider/multi-cluster/demo-policy-secret-reader.yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: demo-policy-secret-reader
+ namespace: demo
+spec:
+ ref:
+ name: vault-app
+ namespace: demo
+ policyDocument: |
+ path "secret/*" {
+ capabilities = ["read", "list"]
+ }
+
+$ kubectl apply -f docs/examples/guides/provider/multi-cluster/demo-policy-secret-reader.yaml
+vaultpolicy.policy.kubevault.com/demo-policy-secret-reader created
+
+$ kubectl get vaultpolicies -n demo
+NAME STATUS AGE
+demo-policy-secret-reader Success 1m
+```
+
+Check the created `demo-policy-secret-reader` [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) in Vault. To resolve the naming conflict, name of policy in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. For this case, it is `k8s.demo-cluster-2.demo.demo-policy-secret-reader`.
+
+```bash
+$ vault policy list
+default
+k8s.demo-cluster-1.demo.demo-policy-secret-admin
+k8s.demo-cluster-2.demo.demo-policy-secret-reader
+my-vault-policy-controller
+root
+
+```
+
+This how we can use KubeVault operator in multiple Kubernetes clusters with a shared Vault Server without naming conflict.
diff --git a/content/docs/v2025.11.21/guides/policy-management/_index.md b/content/docs/v2025.11.21/guides/policy-management/_index.md
new file mode 100755
index 000000000..853a63c84
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/policy-management/_index.md
@@ -0,0 +1,17 @@
+---
+title: Policy Management Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: policy-management-guides
+ name: Policy Management
+ parent: guides
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/policy-management/overview.md b/content/docs/v2025.11.21/guides/policy-management/overview.md
new file mode 100644
index 000000000..fdbad86b0
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/policy-management/overview.md
@@ -0,0 +1,356 @@
+---
+title: Vault Policy Management
+menu:
+ docs_v2025.11.21:
+ identifier: overview-policy-management
+ name: Overview
+ parent: policy-management-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Vault Policy Management
+
+You can easily manage the Vault [policies](https://www.vaultproject.io/docs/concepts/policies.html) in Kubernetes native way using the KubeVault operator. The operator also provides functionality to create auth method roles that bind policies.
+
+You should be familiar with the following CRD:
+
+- [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy)
+- [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding)
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+## Before you begin
+
+- Install KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+- Deploy the Vault server or configure an existing one.
+ - [Setup Vault Server](/docs/v2025.11.21/guides/vault-server/overview#setup-vault-server)
+
+Now, you have the AppBinding that holds the connection information of the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ labels:
+ app: vault
+ vault_cluster: vault
+ name: vault
+ namespace: demo
+spec:
+ clientConfig:
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9URXhNRGN3TXpVNE1qZGFGdzB5T1RFeE1EUXdNelU0TWpkYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdVFaUWZNU1pZek13djUzQjlKcmJlZkc0ClREYmtuaERGamZNMmJrdU90ak83cElFdG5ZSzRrVEdDRkRGd1RlTUNoczhiNFBQcGN5YzBZZ3BSdFFYMW9VTGUKdTFCOE0ralBtMXdhYys4S0JGR3BJdjVpS2dzMjI1MWczTThoY0lqK0ZFQ3hMVTN1bHZDazlUSXlJYzNLSGlDcwpFUmg2VXA2V1hxSVJYb3loNlViWmFrd2tsUTd5SGdUY0ZQMzNzNlBVVXVZaFNtUTJBNmxPU2NPSFRaVytHVDNrCjdPSzUxQ3g5RUptcjdZY1J2N3RiNXI0bGYycy81ZGg0SnYwS2UySkNCUExoK0dBeVh2cHlMd1dmc0w3cWduZ28KZSt0SXVadXFsSENwWDN1eERILzBncGRtK0NHTkN0aUlZUzdGOEFQODlsVVdrc2JOcVdKL1RnTlIrYmp6WHdJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFGb0QvMGtZSHk5OW96MU9xSEVOOC9UVjVXM0dIN1lZSUdqVHZ5Mmc2NFpsajNDbjQKdHdlejd3VGhtMGllazFSR1VXM3luNzg2cEswZVFqYWM3OWZpUG5iTEx0WkRVTzFkSVM5Rnp1MmFiNmpITEpxYQpteUswcHJ1NGNDbmtZTmtOdWhKclQwSkl4Rjc5cXBEanlhSjVuOUxXbDFQZmZwZDZrUW5vdjZrNGtQL2JoTXhECk9oWVBvaVcydkZxSEI4NCtPVHhLbHRkWnNwTkR3bEh1NjZ6a1c0Z0xiRVBnTWUzN1p3NUFISWZld2hqWG93VHYKNVZpZnZYUjVreVNZTTdCMHlqcnpzUzNvK1ZGdS9wMzdmWThwaHMwZzdCWjd3TlhCcWJBT010K2s0Vy9CU0xUagpOelB2STB0SGFCTklnRFdHbm1waEIxN1BpQnBPc1Y2RHdiOVRYdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+ service:
+ name: vault
+ port: 8200
+ scheme: HTTPS
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes
+ vaultRole: vault-policy-controller
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+```
+
+## VaultPolicy
+
+
+
+Using VaultPolicy, you can create, update and delete policy in Vault. In this tutorial, we are going to create `read-only-policy` in `demo` namespace with the permissions to read and list Vault policies.
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: read-only-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "sys/policy" {
+ capabilities = ["list"]
+ }
+
+ path "sys/policy/*" {
+ capabilities = ["read"]
+ }
+```
+
+Now, we are going to create VaultPolicy.
+
+```bash
+$ kubectl apply -f docs/examples/guides/policy-management/read-only-policy.yaml
+vaultpolicy.policy.kubevault.com/read-only-policy created
+```
+
+Check whether the VaultPolicy is successful.
+
+```cosole
+$ kubectl get vaultpolicy -n demo
+NAME PHASE AGE
+read-only-policy Success 15s
+```
+
+Check whether the policy is created in the Vault server. To resolve the naming conflict, name of policy in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. In this case, it is `k8s.-.demo.read-only-policy`.
+
+> Don't have Vault CLI? Enable Vault CLI from [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli).
+
+```bash
+$ vault list sys/policy
+Keys
+----
+k8s.-.demo.read-only-policy
+... ...
+
+$ vault read sys/policy/k8s.-.demo.read-only-policy
+Key Value
+--- -----
+name k8s.-.demo.read-only-policy
+rules path "sys/policy" {
+ capabilities = ["list"]
+}
+
+path "sys/policy/*" {
+ capabilities = ["read"]
+}
+```
+
+If we delete VaultPolicy `read-only-policy`, then the respective Vault policy will also be deleted from Vault.
+
+```cosole
+$ kubectl delete vaultpolicies/read-only-policy -n demo
+vaultpolicy.policy.kubevault.com "read-only-policy" deleted
+```
+
+Check whether the policy is deleted in Vault.
+
+```bash
+$ vault read sys/policy/k8s.-.demo.read-only-policy
+No value found at sys/policy/k8s.-.demo.read-only-policy
+
+$ vault list sys/policy
+Keys
+----
+default
+k8s.-.demo.vault-auth-method-controller
+root
+vault-policy-controller
+```
+
+## VaultPolicyBinding
+
+
+
+Using VaultPolicyBinding, you can create an auth method role that binds the Vault policies to users or service accounts.
+
+Currently supported auth methods for creating role:
+
+- [Kubernetes Auth Method](https://www.vaultproject.io/docs/auth/kubernetes.html)
+
+In this tutorial, we are going to create a `policy-reader-role` VaultPolicyBinding in `demo` namespace.
+
+Create a service account in the demo namespace:
+
+```bash
+$ kubectl create serviceaccount -n demo demo-sa
+serviceaccount/demo-sa created
+```
+
+Get JWT token of the `demo-sa` service account:
+
+```bash
+$ kubectl get secret -n demo demo-sa-token-jz7x5 -o jsonpath="{.data.token}" | base64 -d
+eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tc2EtdG9rZW4tano3eDUiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVtby1zYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjQxMGE4M2ViLWJhMDMtNDY1OS1iOTVjLTlmM2Y3ODdmZTM0OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZW1vOmRlbW8tc2EifQ.w2H7cUXxAjeY4ZGJYVuTK8XrhpCXZeqUPQhFAyTndWhcevXOJFnK7jtyceYWaN0zy6TkBxHeAzVQdyLaFrNgecUKTzCZGaWHAoXlJOMY4Q49mHzEf3iGOBM7m1ckTTP9ABcOsVjD7OvlKslse_NnMDxVtuiughtMcrIhK5pbngQbJRpGkHaiOjgzIpHR3ybLmak7a24CXif0ZAqZd_y5l7bKi8eLr2Sidgq1R1sOMtOpnrj7qQCownw_KRrSPqhSCVSmaNDEYeqA9Jbw-JWVb3SW-FodjTPJsKj_qv791dZZE910CMBcsuJMPuAvNlX0cpOqO-7cdJzNG5y7IoYiSA
+```
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: policy-reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: read-only-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "demo-sa"
+ serviceAccountNamespaces:
+ - "demo"
+```
+
+Here, a Kubernetes auth method role will be created that binds the `read-only-policy` policy to the service account `demo-sa` in `demo` namespace.
+
+Let's create `read-only-policy` by using VaultPolicy:
+
+```bash
+$ kubectl apply -f docs/examples/guides/policy-management/demo-policy.yaml
+vaultpolicy.policy.kubevault.com/read-only-policy created
+```
+
+Check status:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME PHASE AGE
+read-only-policy Success 15s
+```
+
+Now, we are going to create VaultPolicyBinding `policy-reader-role`.
+
+```cosole
+$ kubectl apply -f docs/examples/guides/policy-management/policy-reader-role.yaml
+vaultpolicybinding.policy.kubevault.com/policy-reader-role created
+```
+
+Check whether the `policy-reader-role` is successful.
+
+```bash
+$ kubectl get vaultpolicybinding -n demo
+NAME PHASE AGE
+policy-reader-role Success 11s
+```
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/policy-management/../vault-server/vault-server#enable-vault-cli).
+
+Check whether the Kubernetes auth role is created in Vault. To resolve the naming conflict,name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`. In this case, it is `k8s.-.demo.policy-reader-role`.
+
+```bash
+$ vault list auth/kubernetes/role
+Keys
+----
+k8s.-.demo.policy-reader-role
+k8s.-.demo.vault-auth-method-controller
+vault-policy-controller
+
+
+$ vault read auth/kubernetes/role/k8s.-.demo.policy-reader-role
+Key Value
+--- -----
+bound_service_account_names [demo-sa]
+bound_service_account_namespaces [demo]
+policies [k8s.-.demo.read-only-policy]
+token_bound_cidrs []
+token_explicit_max_ttl 0s
+token_max_ttl 0s
+token_no_default_policy false
+token_num_uses 0
+token_period 0s
+token_policies [k8s.-.demo.read-only-policy]
+token_ttl 0s
+token_type default
+```
+
+Now, we are going to perform authentication to the Vault using `demo-sa`'s JWT token. In response to successful authentication, the Vault will provide us a token that will have permissions of the `read-only-policy` policy.
+
+```bash
+$ vault write auth/kubernetes/login \
+ role=k8s.-.demo.policy-reader-role \
+ jwt=eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlbW8tc2EtdG9rZW4tano3eDUiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVtby1zYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjQxMGE4M2ViLWJhMDMtNDY1OS1iOTVjLTlmM2Y3ODdmZTM0OCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZW1vOmRlbW8tc2EifQ.w2H7cUXxAjeY4ZGJYVuTK8XrhpCXZeqUPQhFAyTndWhcevXOJFnK7jtyceYWaN0zy6TkBxHeAzVQdyLaFrNgecUKTzCZGaWHAoXlJOMY4Q49mHzEf3iGOBM7m1ckTTP9ABcOsVjD7OvlKslse_NnMDxVtuiughtMcrIhK5pbngQbJRpGkHaiOjgzIpHR3ybLmak7a24CXif0ZAqZd_y5l7bKi8eLr2Sidgq1R1sOMtOpnrj7qQCownw_KRrSPqhSCVSmaNDEYeqA9Jbw-JWVb3SW-FodjTPJsKj_qv791dZZE910CMBcsuJMPuAvNlX0cpOqO-7cdJzNG5y7IoYiSA
+Key Value
+--- -----
+token s.0of6p1q8SrcN3OscDaBlmWuI
+token_accessor lvddBe41uXe0DK5xGoaPKsN7
+token_duration 768h
+token_renewable true
+token_policies ["default" "k8s.-.demo.read-only-policy"]
+identity_policies []
+policies ["default" "k8s.-.demo.read-only-policy"]
+token_meta_role k8s.-.demo.policy-reader-role
+token_meta_service_account_name demo-sa
+token_meta_service_account_namespace demo
+token_meta_service_account_secret_name demo-sa-token-jz7x5
+token_meta_service_account_uid 410a83eb-ba03-4659-b95c-9f3f787fe348
+```
+
+Grab the token and export it as env to check its behavior:
+
+```bash
+$ export VAULT_TOKEN=s.0of6p1q8SrcN3OscDaBlmWuI
+
+$ vault list sys/policy
+Keys
+----
+default
+k8s.-.demo.read-only-policy
+k8s.-.demo.vault-auth-method-controller
+root
+vault-policy-controller
+
+$ vault read sys/policy/k8s.-.demo.read-only-policy
+Key Value
+--- -----
+name k8s.-.demo.read-only-policy
+rules path "sys/policy" {
+ capabilities = ["list"]
+}
+
+path "sys/policy/*" {
+ capabilities = ["read"]
+}
+
+$ vault delete sys/policy/k8s.-.demo.read-only-policy
+Error deleting sys/policy/k8s.-.demo.read-only-policy: Error making API request.
+
+URL: DELETE https://127.0.0.1:8200/v1/sys/policy/k8s.-.demo.read-only-policy
+Code: 403. Errors:
+
+* 1 error occurred:
+ * permission denied
+
+$ vault list auth/kubernetes/role
+Error listing auth/kubernetes/role/: Error making API request.
+
+URL: GET https://127.0.0.1:8200/v1/auth/kubernetes/role?list=true
+Code: 403. Errors:
+
+* 1 error occurred:
+ * permission denied
+
+```
+
+Here, we can see that we don't have the permission to do anything but list and read the policies. So, the VaultPolicy `read-only-policy` and the VaultPolicyBinding `policy-reader-role` are working perfectly.
+
+If we delete VaultPolicyBinding, then the respective role will be deleted from Vault.
+
+```bash
+$ kubectl delete vaultpolicybinding policy-reader-role -n demo
+vaultpolicybinding.policy.kubevault.com "policy-reader-role" deleted
+```
+
+Check whether the role is deleted from Vault.
+
+```bash
+$ vault read auth/kubernetes/role/k8s.-.demo.policy-reader-role
+No value found at auth/kubernetes/role/k8s.-.demo.policy-reader-role
+
+$ vault list auth/kubernetes/role
+Keys
+----
+k8s.-.demo.vault-auth-method-controller
+vault-policy-controller
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/_index.md b/content/docs/v2025.11.21/guides/secret-engines/_index.md
new file mode 100755
index 000000000..984c1f07b
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/_index.md
@@ -0,0 +1,17 @@
+---
+title: Secret Engine Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: secret-engines-guides
+ name: Secret Engines
+ parent: guides
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/aws/_index.md b/content/docs/v2025.11.21/guides/secret-engines/aws/_index.md
new file mode 100755
index 000000000..341f2c941
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/aws/_index.md
@@ -0,0 +1,17 @@
+---
+title: AWS | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: aws-secret-engines
+ name: AWS
+ parent: secret-engines-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/aws/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/aws/csi-driver.md
new file mode 100644
index 000000000..fa998692b
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/aws/csi-driver.md
@@ -0,0 +1,293 @@
+---
+title: Mount AWS IAM Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-aws
+ name: CSI Driver
+ parent: aws-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount AWS IAM Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/aws) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure AWS SecretEngine
+
+### Enable AWS SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secretengine.yaml
+secretengine.engine.kubevault.com/aws-engine created
+```
+
+### Create AWSRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secretenginerole.yaml
+gcprole.engine.kubevault.com/aws-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.aws-reader-role"
+ objects: |
+ - objectName: "access_key"
+ secretPath: "your-aws-path/creds/k8s.-.demo.aws-role"
+ secretKey: "access_key"
+ - objectName: "secret_key"
+ secretPath: "your-aws-path/creds/k8s.-.demo.aws-role"
+ secretKey: "secret_key"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `AWS` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/aws-keys"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/aws-keys
+access_key secret_key
+
+/ # cat /secrets-store/aws-keys/access_key
+AKIAWSY....
+
+/ # cat /secrets-store/aws-keys/secret_key
+sGOEbfiDwOL5Wke......
+/ # exit
+```
+
+So, we can see that the secret `access_key` & `secret_key` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/aws/overview.md b/content/docs/v2025.11.21/guides/secret-engines/aws/overview.md
new file mode 100644
index 000000000..61715f75c
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/aws/overview.md
@@ -0,0 +1,363 @@
+---
+title: Manage AWS IAM Secrets using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-aws
+ name: Overview
+ parent: aws-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage AWS IAM Secrets using the KubeVault operator
+
+The AWS secrets engine generates AWS access credentials dynamically based on IAM policies. The AWS IAM credentials are time-based and are automatically revoked when the Vault lease expires. You can easily manage the [AWS secret engine](https://www.vaultproject.io/docs/secrets/aws/index.html) using KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [AWSRole](/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/api/secret/aws/index.html#create-update-role) using AWSRole and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure AWS Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for AWS secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: aws-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ aws:
+ credentialSecret: aws-cred
+ region: us-east-1
+ leaseConfig:
+ lease: 1h
+ leaseMax: 1h
+```
+
+To configure the AWS secret engine, you need to provide `aws_access_key_id` and `aws_secret_access_key` through a Kubernetes secret.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: aws-cred
+ namespace: demo
+data:
+ access_key: eyJtc2ciOiJleGFtcGxlIn0= # base64 encoded aws access key id
+ secret_key: eyJtc2ciOiJleGFtcGxlIn0= # base64 encoded aws secret access key
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secret.yaml
+secret/aws-cred created
+
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secretengine.yaml
+secretengine.engine.kubevault.com/aws-secret-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS
+aws-secret-engine Success
+```
+
+Since the status is `Success`, the AWS secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events if any.
+
+## Create AWS Role
+
+By using [AWSRole](/docs/v2025.11.21/concepts/secret-engine-crds/aws-secret-engine/awsrole), you can create a [role](https://www.vaultproject.io/api/secret/aws/index.html#create-update-role) on the Vault server in Kubernetes native way.
+
+A sample AWSRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AWSRole
+metadata:
+ name: aws-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: aws-secret-engine
+ credentialType: iam_user
+ policyDocument: |
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "ec2:*",
+ "Resource": "*"
+ }
+ ]
+ }
+```
+
+Let's deploy AWSRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secretenginerole.yaml
+awsrole.engine.kubevault.com/aws-role created
+
+$ kubectl get awsrole -n demo
+NAME STATUS
+aws-role Success
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-aws-path/roles
+Keys
+----
+k8s.-.demo.aws-role
+
+$ vault read your-aws-path/roles/k8s.-.demo.aws-role
+Key Value
+--- -----
+credential_type iam_user
+default_sts_ttl 0s
+iam_groups
+iam_tags
+max_sts_ttl 0s
+permissions_boundary_arn n/a
+policy_arns
+policy_document {"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"ec2:*","Resource":"*"}]}
+role_arns
+user_path n/a
+```
+
+If we delete the AWSRole, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete awsrole -n demo aws-role
+awsrole.engine.kubevault.com "aws-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read your-aws-path/roles/k8s.-.demo.aws-role
+No value found at your-aws-path/roles/k8s.-.demo.aws-role
+
+$ vault list aws/roles
+No value found at aws/roles/
+```
+
+## Generate AWS credentials
+
+Here, we are going to make a request to Vault for AWS credential by creating `aws-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: aws-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: AWSRole
+ name: aws-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of AWSRole against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to and it will have read access of the credential secret.
+
+Now, we are going to create an SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/aws/secretaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/aws-cred-rqst created
+
+$ kubectl get secretaccessrequest -n demo
+NAME AGE
+aws-cred-rqst 35s
+```
+
+AWS credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest aws-cred-rqst -n demo
+ approved
+
+$ kubectl get secretaccessrequest -n demo aws-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: aws-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ name: aws-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2019-11-13T12:18:07Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: your-aws-path/creds/k8s.-.demo.aws-role/X9dCjtiQCykbuJ7UmzM64xfh
+ renewable: true
+ secret:
+ name: aws-cred-rqst-ryym7w
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest aws-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-13T12:18:07Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "your-aws-path/creds/k8s.-.demo.aws-role/X9dCjtiQCykbuJ7UmzM64xfh",
+ "renewable": true
+ },
+ "secret": {
+ "name": "aws-cred-rqst-ryym7w"
+ }
+}
+
+$ kubectl get secret -n demo aws-cred-rqst-ryym7w -o yaml
+apiVersion: v1
+data:
+ access_key: QUtJQVdTWV....=
+ secret_key: RVA1dXdXWnVlTX....==
+ security_token: ""
+kind: Secret
+metadata:
+ name: aws-cred-rqst-ryym7w
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: aws-cred-rqst
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo aws-cred-rqst
+secretaccessrequest.engine.kubevault.com "aws-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest aws-cred-rqst -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you can not change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/azure/_index.md b/content/docs/v2025.11.21/guides/secret-engines/azure/_index.md
new file mode 100755
index 000000000..4fa0e6ae6
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/azure/_index.md
@@ -0,0 +1,17 @@
+---
+title: Azure | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: azure-secret-engines
+ name: Azure
+ parent: secret-engines-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/azure/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/azure/csi-driver.md
new file mode 100644
index 000000000..793745e4a
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/azure/csi-driver.md
@@ -0,0 +1,293 @@
+---
+title: Mount Azure Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-azure
+ name: CSI Driver
+ parent: azure-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount Azure Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/azure) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure Azure SecretEngine
+
+### Enable Azure SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secretengine.yaml
+secretengine.engine.kubevault.com/azure-engine created
+```
+
+### Create AzureRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secretenginerole.yaml
+azurerole.engine.kubevault.com/azure-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: AzureRole
+ name: azure-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.azure-reader-role"
+ objects: |
+ - objectName: "client_id"
+ secretPath: "your-azure-path/creds/k8s.-.demo.azure-role"
+ secretKey: "client_id"
+ - objectName: "client_secret"
+ secretPath: "your-azure-path/creds/k8s.-.demo.azure-role"
+ secretKey: "client_secret"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `Azure` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/azure-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/azure-creds
+client_id client_secret
+
+/ # cat /secrets-store/azure-creds/client_id
+ya29.c.Kl20BwwWtb6DoTjY4-eSVgQQq.......
+
+/ # cat /secrets-store/azure-creds/client_secret
+ya29.c.Kl20BwwWtb6DoTjY4-eSVgQQq.......
+/ # exit
+```
+
+So, we can see that the secret `client_id` and `client_secret` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/azure/overview.md b/content/docs/v2025.11.21/guides/secret-engines/azure/overview.md
new file mode 100644
index 000000000..ae409dcf8
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/azure/overview.md
@@ -0,0 +1,361 @@
+---
+title: Manage Azure service principals using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-azure
+ name: Overview
+ parent: azure-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage Azure service principals using the KubeVault operator
+
+The Azure secrets engine dynamically generates Azure service principals and role assignments. Vault roles can be mapped to one or more Azure roles, providing a simple, flexible way to manage the permissions granted to generated service principals. You can easily manage the [Azure secret engine](https://www.vaultproject.io/docs/secrets/azure/index.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [AzureRole](/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/azurerole)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/api/secret/azure/index.html#create-update-role) using AzureRole and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure Azure Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for Azure secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: azure-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ azure:
+ credentialSecret: azure-cred
+```
+
+To configure the Azure secret engine, you need to provide azure credentials through a Kubernetes secret.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: azure-cred
+ namespace: demo
+data:
+ client-secret: eyJtc2ciOiJleGFtcGxlIn0=
+ subscription-id: eyJtc2ciOiJleGFtcGxlIn0=
+ client-id: eyJtc2ciOiJleGFtcGxlIn0=
+ tenant-id: eyJtc2ciOiJleGFtcGxlIn0=
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secret.yaml
+secret/azure-cred created
+
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secretengine.yaml
+secretengine.engine.kubevault.com/azure-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS
+azure-engine Success
+```
+
+Since the status is `Success`, the Azure secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create Azure Role
+
+By using [AzureRole](/docs/v2025.11.21/concepts/secret-engine-crds/azure-secret-engine/azurerole), you can create a [role](https://www.vaultproject.io/api/secret/azure/index.html#create-update-role) on the Vault server in Kubernetes native way.
+
+A sample AzureRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: AzureRole
+metadata:
+ name: azure-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: vault
+ applicationObjectID: e211afbc-cc4a-462f-ad6f-59e26eb5406f
+ ttl: 1h
+```
+
+Let's deploy AzureRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/secretenginerole.yaml
+azurerole.engine.kubevault.com/azure-role created
+
+$ kubectl get azureroles -n demo
+NAME STATUS
+azure-role Success
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list azure/roles
+Keys
+----
+k8s.-.demo.azure-role
+
+$ vault read azure/roles/k8s.-.demo.azure-role
+Key Value
+--- -----
+application_object_id c1cb042d-96d7-423a-8dba-243c2e5010d3
+azure_roles
+max_ttl 0s
+ttl 1h
+```
+
+If we delete the AzureRole, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete -f docs/examples/guides/secret-engines/azure/secretenginerole.yaml
+ azurerole.engine.kubevault.com "azure-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read azure/roles/k8s.-.demo.azure-role
+ No value found at azure/roles/k8s.-.demo.azure-role
+
+$ vault list azure/roles
+ No value found at azure/roles/
+```
+
+## Generate Azure credentials
+
+
+Here, we are going to make a request to Vault for Azure credentials by creating `azure-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: azure-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: AzureRole
+ name: azure-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of AzureRole against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to and it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/azure/azureaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/azure-cred-rqst created
+
+$ kubectl get secretaccessrequests -n demo
+NAME AGE
+azure-cred-rqst 3s
+```
+
+Azure credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest azure-cred-rqst -n demo
+ approved
+
+$ kubectl get secretaccessrequests -n demo azure-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: azure-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ name: azure-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2019-11-14T09:21:49Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: azure/creds/k8s.-.demo.azure-role/FJVEWUW9NpGlFOdIIMd900Zr
+ renewable: true
+ secret:
+ name: azure-cred-rqst-luc5p4
+
+
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest azure-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-14T09:21:49Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "azure/creds/k8s.-.demo.azure-role/FJVEWUW9NpGlFOdIIMd900Zr",
+ "renewable": true
+ },
+ "secret": {
+ "name": "azure-cred-rqst-luc5p4"
+ }
+}
+
+$ kubectl get secret -n demo azure-cred-rqst-luc5p4 -o yaml
+apiVersion: v1
+data:
+ client_id: MmI4NzFkNGEtN...
+ client_secret: ZjJlMjA3N...
+kind: Secret
+metadata:
+ name: azure-cred-rqst-luc5p4
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: azure-cred-rqst
+ uid: d944491b-a22c-4777-bc8f-2e2c94b47b7b
+type: Opaque
+
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo azure-cred-rqst
+secretaccessrequest.engine.kubevault.com "azure-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credentials.
+
+```bash
+$ kubectl vault deny secretaccessrequest azure-cred-rqst -n demo
+ Denied
+
+$ kubectl get secretaccessrequest azure-cred-rqst -n demo -o json | jq '.status'
+ {
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-14T09:21:49Z",
+ "message": "This was denied by kubectl vault deny secretaccessrequest",
+ "reason": "KubectlDeny",
+ "type": "Denied"
+ }
+ ]
+ }
+```
+
+> Note: Once SecretAccessRequest is `Approved` or `Denied`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/csi_architecture.svg b/content/docs/v2025.11.21/guides/secret-engines/csi_architecture.svg
new file mode 100644
index 000000000..775afdf10
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/csi_architecture.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/_index.md b/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/_index.md
new file mode 100755
index 000000000..036a39733
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/_index.md
@@ -0,0 +1,17 @@
+---
+title: Elasticsearch | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: elasticsearch-secret-engines
+ name: Elasticsearch
+ parent: secret-engines-guides
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/csi-driver.md
new file mode 100644
index 000000000..e571e4876
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/csi-driver.md
@@ -0,0 +1,292 @@
+---
+title: Mount Elasticsearch Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-elasticsearch
+ name: CSI Driver
+ parent: elasticsearch-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount Elasticsearch Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/elasticsearch) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure Elasticsearch SecretEngine
+
+### Enable Elasticsearch SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/secretengine.yaml
+secretengine.engine.kubevault.com/es-engine created
+```
+
+### Create ElasticsearchRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/secretenginerole.yaml
+elasticsearchrole.engine.kubevault.com/es-superuser-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: ElasticsearchRole
+ name: es-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.es-reader-role"
+ objects: |
+ - objectName: "es-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.es-superuser-role"
+ secretKey: "username"
+ - objectName: "es-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.es-superuser-role"
+ secretKey: "password"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `Elasticsearch` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/es-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/es-creds
+es-creds-password es-creds-username
+
+/ # cat /secrets-store/es-creds/es-creds-password
+TAu2Zvg1WYE07W8Uf-nW
+
+/ # cat /secrets-store/es-creds/es-creds-username
+v-kubernetes-test-k8s.-.demo.es-s-iPkxiH80Ollq2QgF82Ab-1629178048
+
+/ # exit
+```
+
+So, we can see that the secret `db-username` and `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/overview.md b/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/overview.md
new file mode 100644
index 000000000..088269879
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/elasticsearch/overview.md
@@ -0,0 +1,337 @@
+---
+title: Manage Elasticsearch credentials using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-elasticsearch
+ name: Overview
+ parent: elasticsearch-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage Elasticsearch credentials using the KubeVault operator
+
+Elasticsearch is one of the supported plugins for the database secrets engine. This plugin generates database credentials dynamically based on configured roles for the Elasticsearch database. You can easily manage [Elasticsearch secret engine](https://www.vaultproject.io/docs/secrets/databases/elasticdb.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [ElasticsearchRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/elasticsearch)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/docs/secrets/databases/elasticdb#setup) using Elasticsearch and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure Elasticsearch Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for the Elasticsearch secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: es-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ elasticsearch:
+ databaseRef:
+ name: elasticsearch
+ namespace: demo
+ pluginName: "elasticsearch-database-plugin"
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/secretengine.yaml
+secretengine.engine.kubevault.com/es-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS AGE
+es-engine Success 10s
+```
+
+Since the status is `Success`, the Elasticsearch secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create Elasticsearch Role
+
+By using [ElasticsearchRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/elasticsearch), you can create a [role](https://www.vaultproject.io/docs/secrets/databases/elasticdb#setup) on the Vault server in Kubernetes native way.
+
+A sample ElasticsearchRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: ElasticsearchRole
+metadata:
+ name: es-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: es-secret-engine
+ creationStatements:
+ - '{"elasticsearch_roles": ["superuser"]}'
+ defaultTTL: 1h
+ maxTTL: 24h
+```
+
+Let's deploy ElasticsearchRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/secretenginerole.yaml
+elasticsearchrole.engine.kubevault.com/es-superuser-role created
+
+$ kubectl get elasticsearchrole -n demo
+NAME STATUS AGE
+es-superuser-role Success 34m
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-database-path/roles
+Keys
+----
+k8s.-.demo.es-superuser-role
+
+$ vault read your-database-path/roles/k8s.-.demo.es-superuser-role
+Key Value
+--- -----
+creation_statements [{"elasticsearch_roles": ["superuser"]}]
+db_name k8s.-.demo.elasticsearch
+default_ttl 1h
+max_ttl 24h
+renew_statements []
+revocation_statements []
+rollback_statements []
+```
+
+If we delete the ElasticsearchRole, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete elasticsearchrole -n demo es-superuser-role
+elasticsearchrole.engine.kubevault.com "es-superuser-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read your-database-path/roles/k8s.-.demo.es-superuser-role
+No value found at your-database-path/roles/k8s.-.demo.es-superuser-role
+
+$ vault list your-database-path/roles
+No value found at your-database-path/roles/
+```
+
+## Generate Elasticsearch credentials
+
+
+Here, we are going to make a request to Vault for Elasticsearch credentials by creating `es-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: es-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: ElasticsearchRole
+ name: es-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of Elasticsearch against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/elasticsearch/elasticaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/es-cred-rqst created
+
+$ kubectl get secretaccessrequest -n demo
+NAME AGE
+es-cred-rqst 72m
+```
+
+Database credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest es-cred-rqst -n demo
+approved
+
+$ kubectl get secretaccessrequest -n demo es-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: es-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: ElasticsearchRole
+ name: es-superuser-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2020-11-18T06:41:57Z"
+ message: This was approved by kubectl vault approve secreteaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: your-database-path/creds/k8s.-.demo.es-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx
+ renewable: true
+ secret:
+ name: es-cred-rqst-gy66wq
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest es-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-18T06:41:57Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "your-database-path/creds/k8s.-.demo.es-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx",
+ "renewable": true
+ },
+ "secret": {
+ "name": "es-cred-rqst-gy66wq"
+ }
+}
+
+$ kubectl get secret -n demo es-cred-rqst-gy66wq -o yaml
+apiVersion: v1
+data:
+ password: QTFhLVBkZGlsZFFxa0o1cnlvR20=
+ username: di1rdWJlcm5ldGVzLWRlbW8TE1NzQwNTkzMTc=
+kind: Secret
+metadata:
+ name: es-cred-rqst-gy66wq
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: es-cred-rqst
+ uid: 54ce63ca-d0e7-4b97-9085-b52eb3cb334f
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo es-cred-rqst
+secretaccessrequest.engine.kubevault.com "es-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest es-cred-rqst -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/gcp/_index.md b/content/docs/v2025.11.21/guides/secret-engines/gcp/_index.md
new file mode 100755
index 000000000..cab6af49b
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/gcp/_index.md
@@ -0,0 +1,17 @@
+---
+title: GCP | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: gcp-secret-engines
+ name: GCP
+ parent: secret-engines-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/gcp/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/gcp/csi-driver.md
new file mode 100644
index 000000000..b1ceadd9a
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/gcp/csi-driver.md
@@ -0,0 +1,288 @@
+---
+title: Mount GCP Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-gcp
+ name: CSI Driver
+ parent: gcp-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount GCP Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/gcp) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure GCP SecretEngine
+
+### Enable GCP SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secretengine.yaml
+secretengine.engine.kubevault.com/gcp-engine created
+```
+
+### Create GCPRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secretenginerole.yaml
+gcprole.engine.kubevault.com/gcp-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: GCPRole
+ name: gcp-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.gcp-reader-role"
+ objects: |
+ - objectName: "gcp-token"
+ secretPath: "your-gcp-path/token/k8s.-.demo.gcp-role"
+ secretKey: "token"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `GCP` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/gcp-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/gcp-creds
+gcp-token
+
+/ # cat /secrets-store/gcp-creds/gcp-token
+ya29.c.Kl20BwwWtb6DoTjY4-eSVgQQq.......
+
+/ # exit
+```
+
+So, we can see that the secret `gcp-token` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/gcp/overview.md b/content/docs/v2025.11.21/guides/secret-engines/gcp/overview.md
new file mode 100644
index 000000000..6d38fe35a
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/gcp/overview.md
@@ -0,0 +1,343 @@
+---
+title: Manage GCP IAM Secrets using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-gcp
+ name: Overview
+ parent: gcp-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage GCP IAM Secrets using the KubeVault operator
+
+The Google Cloud Vault secrets engine dynamically generates Google Cloud service account keys and OAuth tokens based on IAM policies. This enables users to gain access to Google Cloud resources without needing to create or manage a dedicated service account. You can easily manage [GCP secret engine](https://www.vaultproject.io/docs/secrets/gcp/index.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [GCPRole](/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/api/secret/gcp/index.html#create-update-roleset) using GCPRole and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure GCP Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for GCP secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: gcp-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ gcp:
+ credentialSecret: gcp-cred
+```
+
+To configure the GCP secret engine, you need to provide google service account credentials through a Kubernetes secret.
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: gcp-cred
+ namespace: demo
+data:
+ sa.json: eyJtc2ciOiJleGFtcGxlIn0= ## base64 encoded google service account credential
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secret.yaml
+secret/gcp-cred created
+
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secretengine.yaml
+secretengine.engine.kubevault.com/gcp-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS
+gcp-engine Success
+```
+
+Since the status is `Success`, the GCP secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create GCP Roleset
+
+By using [GCPRole](/docs/v2025.11.21/concepts/secret-engine-crds/gcp-secret-engine/gcprole), you can [create gcp roleset](https://www.vaultproject.io/api/secret/gcp/index.html#create-update-roleset) on the Vault server in Kubernetes native way.
+
+A sample GCPRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: GCPRole
+metadata:
+ name: gcp-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: gcp-secret-engine
+ secretType: "access_token"
+ project: appscode-testing
+ bindings: |
+ resource "//cloudresourcemanager.googleapis.com/projects/appscode-testing" {
+ roles = ["roles/viewer"]
+ }
+ tokenScopes:
+ - https://www.googleapis.com/auth/cloud-platform
+```
+
+Let's deploy GCPRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secretenginerole.yaml
+gcprole.engine.kubevault.com/gcp-role created
+
+$ kubectl get gcprole -n demo
+NAME STATUS
+gcp-role Success
+```
+
+You can also check from Vault that the roleset is created.
+To resolve the naming conflict, name of the roleset in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-gcp-path/roleset
+Keys
+----
+k8s.-.demo.gcp-role
+
+$ vault read your-gcp-path/roleset/k8s.-.demo.gcp-role
+Key Value
+--- -----
+bindings map[//cloudresourcemanager.googleapis.com/projects/appscode-testing:[roles/viewer]]
+project appscode-testing
+secret_type access_token
+service_account_email vaultk8s---demo-gcp-1629380381@appscode-testing.iam.gserviceaccount.com
+token_scopes [https://www.googleapis.com/auth/cloud-platform]
+```
+
+If we delete the GCPRole, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete -f docs/examples/guides/secret-engines/gcp/secretenginerole.yaml
+ gcprole.engine.kubevault.com "gcp-role" deleted
+```
+
+Check from Vault whether the roleset exists:
+
+```bash
+$ vault read your-gcp-path/roleset/k8s.-.demo.gcp-role
+ No value found at your-gcp-path/roleset/k8s.-.demo.gcp-role
+
+$ vault list your-gcp-path/roleset
+ No value found at your-gcp-path/roleset/
+```
+
+## Generate GCP credentials
+
+
+Here, we are going to make a request to Vault for GCP credential by creating `gcp-cred-req` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: gcp-cred-req
+ namespace: demo
+spec:
+ roleRef:
+ kind: GCPRole
+ name: gcp-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of GCPRole against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to and it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/gcp/secretaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/gcp-cred-req created
+
+$ kubectl get secretaccessrequests -n demo
+NAME AGE
+gcp-cred-req 3s
+```
+
+GCP credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest gcp-cred-req -n demo
+ approved
+
+$ kubectl get secretaccessrequest -n demo gcp-cred-req -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: gcp-cred-req
+ namespace: demo
+spec:
+ roleRef:
+ name: gcp-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2019-11-12T10:40:30Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 0s
+ secret:
+ name: gcp-cred-req-unyzu6
+
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest gcp-cred-req -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-12T10:40:30Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "0s"
+ },
+ "secret": {
+ "name": "gcp-cred-req-unyzu6"
+ }
+}
+
+$ kubectl get secret -n demo gcp-cred-req-unyzu6 -o yaml
+apiVersion: v1
+data:
+ expires_at_seconds: MTU3MzU1ODgzMA==
+ token: eWEyOS5jLktsMndCLTR5=
+ token_ttl: MzU5OQ==
+kind: Secret
+metadata:
+ name: gcp-cred-req-unyzu6
+ namespace: demo
+type: Opaque
+
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo gcp-cred-req
+ secretaccessrequest.engine.kubevault.com "gcp-cred-req" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest gcp-cred-req -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved` or `Denied`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/kv/_index.md b/content/docs/v2025.11.21/guides/secret-engines/kv/_index.md
new file mode 100755
index 000000000..12f973c60
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/kv/_index.md
@@ -0,0 +1,17 @@
+---
+title: Key/Value | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: kv-secret-engines
+ name: Key/Value
+ parent: secret-engines-guides
+ weight: 20
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/kv/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/kv/csi-driver.md
new file mode 100644
index 000000000..6bfb0250d
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/kv/csi-driver.md
@@ -0,0 +1,326 @@
+---
+title: Mount Key/Value Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-kv
+ name: CSI Driver
+ parent: kv-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount Key/Value Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/kv) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure KV Secret Engine
+
+We will use the [Vault CLI](https://www.vaultproject.io/docs/commands/#vault-commands-cli-) throughout the tutorial to [enable and configure](https://www.vaultproject.io/docs/secrets/kv/kv-v1.html#setup) the KV secret engine.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+### Enable KV Secret Engine
+
+Enable the KV secret engine:
+
+```bash
+$ vault secrets enable -path=secret kv
+Success! Enabled the kv secrets engine at: secret/
+```
+
+### Write KV Secret
+
+Write arbitrary key-value pairs:
+
+```bash
+$ vault kv put secret/db-pass password="db-secret-password"
+Success! Data written to: secret/db-pass
+```
+
+### Read KV Secret
+
+Read a specific key-value pair:
+
+```bash
+$ vault kv get secret/db-pass
+====== Data ======
+Key Value
+--- -----
+password db-secret-password
+```
+
+Let's say pod's service account name is `pod-sa` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `pod-sa` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: pod-sa
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/serviceaccount.yaml
+serviceaccount/pod-sa created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+pod-sa 1 4h10m
+```
+
+### Create VaultPolicy and VaultPolicyBinding for Pod's Service Account
+
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.-.demo.kv-se-role`.
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: kv-se-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "secret/db-pass" {
+ capabilities = ["read"]
+ }
+---
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: kv-se-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: kv-se-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "pod-sa"
+ serviceAccountNamespaces:
+ - "trial"
+```
+
+Let's create VaultPolicy and VaultPolicyBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/policy.yaml
+vaultpolicy.policy.kubevault.com/kv-se-policy created
+
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/policybinding.yaml
+vaultpolicybinding.policy.kubevault.com/kv-se-role created
+```
+
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+kv-se-policy Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+kv-se-role Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-database
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.kv-se-role"
+ objects: |
+ - objectName: "db-password"
+ secretPath: "secret/db-pass"
+ secretKey: "password"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-database created
+```
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `KV` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: mypod
+ namespace: demo
+spec:
+ serviceAccountName: pod-sa
+ containers:
+ - image: jweissig/app:0.0.1
+ name: test-app
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/test"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-database"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/pod.yaml
+pod/mypod created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+mypod 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo mypod sh
+/ # ls /secrets-store/test
+db-password
+
+/ # cat /secrets-store/test/db-password
+db-secret-password
+
+/ # exit
+```
+
+So, we can see that the secret `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/kv/overview.md b/content/docs/v2025.11.21/guides/secret-engines/kv/overview.md
new file mode 100644
index 000000000..ddc280d6b
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/kv/overview.md
@@ -0,0 +1,352 @@
+---
+title: Manage Key/Value Secrets using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-kv
+ name: Overview
+ parent: kv-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage Key/Value Secrets using the KubeVault operator
+
+You can easily manage [KV secret engine](https://www.vaultproject.io/docs/secrets/kv/index.html#kv-secrets-engine) using the KubeVault operator.
+
+You should be familiar with the following CRD:
+
+- [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy)
+- [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding)
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to demonstrate the use of the KV secret engine.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ clientConfig:
+ caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN1RENDQWFDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFOTVFzd0NRWURWUVFERXdKallUQWUKRncweE9URXhNVEl3T1RFMU5EQmFGdzB5T1RFeE1Ea3dPVEUxTkRCYU1BMHhDekFKQmdOVkJBTVRBbU5oTUlJQgpJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdFZFZmtic2c2T085dnM2d1Z6bTlPQ1FYClBtYzBYTjlCWjNMbXZRTG0zdzZGaWF2aUlSS3VDVk1hN1NRSGo2L2YvOHZPeWhqNEpMcHhCM0hCYVFPZ3RrM2QKeEFDbHppU1lEd3dDbGEwSThxdklGVENLWndreXQzdHVQb0xybkppRFdTS2xJait6aFZDTHZ0enB4MDE3SEZadApmZEdhUUtlSXREUVdyNUV1QWlCMjhhSVF4WXREaVN6Y0h3OUdEMnkrblRMUEd4UXlxUlhua0d1UlIvR1B3R3lLClJ5cTQ5NmpFTmFjOE8wVERYRkIydWJQSFNza2xOU1VwSUN3S1IvR3BobnhGak1rWm4yRGJFZW9GWDE5UnhzUmcKSW94TFBhWDkrRVZxZU5jMlczN2MwQlhBSGwyMHVJUWQrVytIWDhnOVBVVXRVZW9uYnlHMDMvampvNERJRHdJRApBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBTkJna3Foa2lHCjl3MEJBUXNGQUFPQ0FRRUFabHRFN0M3a3ZCeTNzeldHY0J0SkpBTHZXY3ZFeUdxYUdCYmFUbGlVbWJHTW9QWXoKbnVqMUVrY1I1Qlg2YnkxZk15M0ZtZkJXL2E0NU9HcDU3U0RMWTVuc2w0S1RlUDdGZkFYZFBNZGxrV0lQZGpnNAptOVlyOUxnTThkOGVrWUJmN0paUkNzcEorYkpDU1A2a2p1V3l6MUtlYzBOdCtIU0psaTF3dXIrMWVyMUprRUdWClBQMzFoeTQ2RTJKeFlvbnRQc0d5akxlQ1NhTlk0UWdWK3ZneWJmSlFEMVYxbDZ4UlVlMzk2YkJ3aS94VGkzN0oKNWxTVklmb1kxcUlBaGJPbjBUWHp2YzBRRXBKUExaRDM2VDBZcEtJSVhjZUVGYXNxZzVWb1pINGx1Uk50SStBUAp0blg4S1JZU0xGOWlCNEJXd0N0aGFhZzZFZVFqYWpQNWlxZnZoUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+ service:
+ name: vault
+ port: 8200
+ scheme: HTTPS
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes
+ vaultRole: vault-policy-controller
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+```
+
+## Use KV Secret Engine as Root User
+
+Here, we are going to use the Vault root token to perform authentication to the Vault server. We will use the [Vault CLI](https://www.vaultproject.io/docs/commands/#vault-commands-cli-) throughout the tutorial.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+Export the root token as environment variable:
+
+```bash
+export VAULT_TOKEN=s.lbSCc2GGit1QmqghBgYgjbOG
+```
+
+### Enable KV Secret Engine
+
+Enable the KV secret engine:
+
+```bash
+$ vault secrets enable -version=1 kv
+Success! Enabled the kv secrets engine at: kv/
+```
+
+### Write KV Secrets
+
+Write arbitrary key-value pairs:
+
+```bash
+$ vault kv put kv/my-secret my-value=s3cr3t
+Success! Data written to: kv/my-secret
+
+$ vault kv put kv/secret-name secret-value=8HI.HFDJK324
+Success! Data written to: kv/secret-name
+
+$ vault kv put kv/key value=sdfkjdslkfjdslj
+Success! Data written to: kv/key
+```
+
+### List KV Secrets
+
+List key-value pairs:
+
+```bash
+$ vault kv list kv/
+Keys
+----
+key
+my-secret
+secret-name
+```
+
+### Read KV Secret
+
+Read a specific key-value pair:
+
+```bash
+$ vault kv get kv/my-secret
+====== Data ======
+Key Value
+--- -----
+my-value s3cr3t
+```
+
+### Delete KV Secrets
+
+Delete a specific key-value pair:
+
+```bash
+$ vault kv delete kv/my-secret
+Success! Data deleted (if it existed) at: kv/my-secret
+```
+
+## Use KV Secret Engine as Non-root User
+
+Here, we are going to create a Kubernetes service account and give it limited access (i.e only KV secret engine) from the Vault using the VaultPolicy and the VaultPolicyBinding.
+
+### Create Kubernetes Service Account
+
+Create a service account `kv-admin` to the `demo` namespace:
+
+```bash
+$ kubectl create serviceaccount -n demo kv-admin
+serviceaccount/kv-admin created
+
+# get service account JWT token which will be required while performing
+# login operation to the Vault
+$ kubectl get secret -n demo kv-admin-token-8cgr2 -o jsonpath="{.data.token}" | base64 -d
+eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imt2LWFkbWluLXRva2VuLThjZ3IyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Imt2LWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMjhiNDdlMWQtMzQyZC00MjYyLWI0NDItMzRjYzViOTFhYThlIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlbW86a3YtYWRtaW4ifQ.NkAbcuOsziZCtDtUYuxzuCKcAVuywnIbdEHylB1un6yc5K_Qfl_AtsnuKjWbJDZtp1kjc6bwy6dftMPSoPwd6U9FO5kbGbLqoA6vsa3Y_gJ74dhYqZnGHZZg9KpCxLHxvl8phcjIrRMvKW_dn95p334GWSI_AqU1zvGTQnFhjlrb-NRKpeTA7N7Y1JP2x1wB8KdtHha-qqGmLsUMJbc8VebgKnG8zjhc1KfgtO0lMLt4uLthBS4ca10r4fOsz259n66FOkVPfbPnXlUYzeObz-Ng4cFwdZ6xLgdF2wz9e8pTKXhe8NifzTFMk_44TPpE5pBqsog80lfMuq7Tk4O3TQ
+```
+
+### Create VaultPolicy and VaultPolicyBinding
+
+A sample VaultPolicy object with necessary path permission for KV secret engine:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: kv-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "sys/mounts" {
+ capabilities = ["read", "list"]
+ }
+
+ path "sys/mounts/*" {
+ capabilities = ["create", "read", "update", "delete"]
+ }
+
+ path "kv/*" {
+ capabilities = ["create","list", "read", "update", "delete"]
+ }
+
+ path "sys/leases/revoke/*" {
+ capabilities = ["update"]
+ }
+```
+
+Create VaultPolicy and check status:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/policy.yaml
+vaultpolicy.policy.kubevault.com/kv-policy created
+
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+kv-policy Success 8m51s
+```
+
+A sample VaultPolicyBinding object that binds the `kv-policy` to the `kv-admin` service account:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: kv-admin-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: kv-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "kv-admin"
+ serviceAccountNamespaces:
+ - "demo"
+ ttl: "1000"
+ maxTTL: "2000"
+ period: "1000"
+```
+
+Create VaultPolicyBinding and check status:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/kv/policyBinding.yaml
+vaultpolicybinding.policy.kubevault.com/kv-admin-role created
+
+$ kubectl get vaultpolicybindings -n demo
+NAME STATUS AGE
+kv-admin-role Success 4m56s
+```
+
+### Login Vault and Use KV Secret Engine
+
+To resolve the naming conflict, name of the policy and role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+List Vault policies and Kubernetes auth roles:
+
+```bash
+$ vault list sys/policy
+Keys
+----
+k8s.-.demo.kv-policy
+k8s.-.demo.vault-auth-method-controller
+vault-policy-controller
+
+$ vault list auth/kubernetes/role
+Keys
+----
+k8s.-.demo.kv-admin-role
+k8s.-.demo.vault-auth-method-controller
+vault-policy-controller
+
+$ vault read auth/kubernetes/role/k8s.-.demo.kv-admin-role
+Key Value
+--- -----
+bound_service_account_names [kv-admin]
+bound_service_account_namespaces [demo]
+max_ttl 33m20s
+period 16m40s
+policies [k8s.-.demo.kv-policy]
+token_bound_cidrs []
+token_explicit_max_ttl 0s
+token_max_ttl 33m20s
+token_no_default_policy false
+token_num_uses 0
+token_period 16m40s
+token_policies [k8s.-.demo.kv-policy]
+token_ttl 16m40s
+token_type default
+ttl 16m40s
+```
+
+So, we can see that the `kv-policy` is added to the `kv-admin-role`.
+
+Now, login to the Vault using `kv-admin`'s JWT token under `kv-admin-role` role.
+
+```bash
+$ vault write auth/kubernetes/login \
+ role=k8s.-.demo.kv-admin-role \
+ jwt=eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6Imt2LWFkbWluLXRva2VuLThjZ3IyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6Imt2LWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMjhiNDdlMWQtMzQyZC00MjYyLWI0NDItMzRjYzViOTFhYThlIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlbW86a3YtYWRtaW4ifQ.NkAbcuOsziZCtDtUYuxzuCKcAVuywnIbdEHylB1un6yc5K_Qfl_AtsnuKjWbJDZtp1kjc6bwy6dftMPSoPwd6U9FO5kbGbLqoA6vsa3Y_gJ74dhYqZnGHZZg9KpCxLHxvl8phcjIrRMvKW_dn95p334GWSI_AqU1zvGTQnFhjlrb-NRKpeTA7N7Y1JP2x1wB8KdtHha-qqGmLsUMJbc8VebgKnG8zjhc1KfgtO0lMLt4uLthBS4ca10r4fOsz259n66FOkVPfbPnXlUYzeObz-Ng4cFwdZ6xLgdF2wz9e8pTKXhe8NifzTFMk_44TPpE5pBqsog80lfMuq7Tk4O3TQ
+Key Value
+--- -----
+token s.HJ8owGJLrqzlnA8tKuYdrElh
+token_accessor FHN3pCvTAoyZuq7FZoOe1fSc
+token_duration 16m40s
+token_renewable true
+token_policies ["default" "k8s.-.demo.kv-policy"]
+identity_policies []
+policies ["default" "k8s.-.demo.kv-policy"]
+token_meta_role k8s.-.demo.kv-admin-role
+token_meta_service_account_name kv-admin
+token_meta_service_account_namespace demo
+token_meta_service_account_secret_name kv-admin-token-8cgr2
+token_meta_service_account_uid 28b47e1d-342d-4262-b442-34cc5b91aa8e
+```
+
+Export the new Vault token as an environment variable:
+
+```bash
+export VAULT_TOKEN=s.HJ8owGJLrqzlnA8tKuYdrElh
+```
+
+Now perform read, write, list and delete operation on KV secret engine:
+
+```bash
+# Enable KV secret engine
+$ vault secrets enable -version=1 kv
+Success! Enabled the kv secrets engine at: kv/
+
+# Write KV secret
+$ vault kv put kv/my-secret my-value=s3cr3t
+Success! Data written to: kv/my-secret
+
+# List KV secrets
+$ vault kv list kv/
+Keys
+----
+my-secret
+
+# Read KV secret
+$ vault kv get kv/my-secret
+====== Data ======
+Key Value
+--- -----
+my-value s3cr3t
+
+# Delete KV secret
+$ vault kv delete kv/my-secret
+Success! Data deleted (if it existed) at: kv/my-secret
+```
+
+To learn more usages of Vault `Key/Vaule` secret engine click [this](https://www.vaultproject.io/docs/secrets/kv/kv-v1.html#usage).
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mariadb/_index.md b/content/docs/v2025.11.21/guides/secret-engines/mariadb/_index.md
new file mode 100644
index 000000000..18775d0f5
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mariadb/_index.md
@@ -0,0 +1,17 @@
+---
+title: MariaDB | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: mariadb-secret-engines
+ name: MariaDB
+ parent: secret-engines-guides
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mariadb/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/mariadb/csi-driver.md
new file mode 100644
index 000000000..a4e11a402
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mariadb/csi-driver.md
@@ -0,0 +1,297 @@
+---
+title: Mount MariaDB Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-mariadb
+ name: CSI Driver
+ parent: mariadb-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount MariaDB Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/mariadb) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure MariaDB SecretEngine
+
+### Enable MariaDB SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/secretengine.yaml
+secretengine.engine.kubevault.com/mariadb-engine created
+```
+
+### Create MariaDBRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/secretenginerole.yaml
+mariadbrole.engine.kubevault.com/mariadb-superuser-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: MariaDBRole
+ name: mariadb-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.mariadb-reader-role"
+ objects: |
+ - objectName: "mariadb-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.mariadb-superuser-role"
+ secretKey: "username"
+ - objectName: "mariadb-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.mariadb-superuser-role"
+ secretKey: "password"
+
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `MariaDB` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/mariadb-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/mariadb-creds
+mariadb-creds-password mariadb-creds-username
+
+/ # cat /secrets-store/mariadb-creds/mariadb-creds-password
+TAu2Zvg1WYE07W8Uf-nW
+
+/ # cat /secrets-store/mariadb-creds/mariadb-creds-username
+v-kubernetes-test-k8s.-.demo.mariadb-s-iPkxiH80Ollq2QgF82Ab-1629178048
+
+/ # exit
+```
+
+So, we can see that the secret `db-username` and `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mariadb/overview.md b/content/docs/v2025.11.21/guides/secret-engines/mariadb/overview.md
new file mode 100644
index 000000000..434c9a09c
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mariadb/overview.md
@@ -0,0 +1,337 @@
+---
+title: Manage MariaDB credentials using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-mariadb
+ name: Overview
+ parent: mariadb-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage MariaDB credentials using the KubeVault operator
+
+MariaDB is one of the supported plugins for the database secrets engine. This plugin generates database credentials dynamically based on configured roles for the MariaDB database. You can easily manage [MariaDB secret engine](https://www.vaultproject.io/docs/secrets/databases/mysql-maria.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [MariaDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mariadb)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/docs/secrets/databases/mysql-maria#setup) using MariaDB and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure MariaDB Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for the MariaDB secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: mariadb-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mariadb:
+ databaseRef:
+ name: mariadb
+ namespace: demo
+ pluginName: "mysql-database-plugin"
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/secretengine.yaml
+secretengine.engine.kubevault.com/mariadb-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS AGE
+mariadb-engine Success 10s
+```
+
+Since the status is `Success`, the MariaDB secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create MariaDB Role
+
+By using [MariaDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mariadb), you can create a [role](https://www.vaultproject.io/docs/secrets/databases/mysql-maria#setup) on the Vault server in Kubernetes native way.
+
+A sample MariaDBRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MariaDBRole
+metadata:
+ name: mariadb-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: sql-secrt-engine
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+ defaultTTL: 1h
+ maxTTL: 24h
+```
+
+Let's deploy MariaDBRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/secretenginerole.yaml
+mariadbrole.engine.kubevault.com/mariadb-superuser-role created
+
+$ kubectl get mariadbrole -n demo
+NAME STATUS AGE
+mariadb-superuser-role Success 34m
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-database-path/roles
+Keys
+----
+k8s.-.demo.mariadb-superuser-role
+
+$ vault read your-database-path/roles/k8s.-.demo.mariadb-superuser-role
+Key Value
+--- -----
+creation_statements [CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON *.* TO '{{name}}'@'%';]
+db_name k8s.-.demo.mariadb
+default_ttl 1h
+max_ttl 24h
+renew_statements []
+revocation_statements []
+rollback_statements []
+```
+
+If we delete the MariaDB, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete mariadbrole -n demo mariadb-superuser-role
+mariadbrole.engine.kubevault.com "mariadb-superuser-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read your-database-path/roles/k8s.-.demo.mariadb-superuser-role
+No value found at your-database-path/roles/k8s.-.demo.mariadb-superuser-role
+
+$ vault list your-database-path/roles
+No value found at your-database-path/roles/
+```
+
+## Generate MariaDB credentials
+
+Here, we are going to make a request to Vault for MariaDB credentials by creating `mariadb-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: mariadb-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: MariaDBRole
+ name: mariadb-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of MariaDB against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mariadb/mariadbaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/mariadb-cred-rqst created
+
+$ kubectl get secretaccessrequest -n demo
+NAME AGE
+mariadb-cred-rqst 72m
+```
+
+Database credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest mariadb-cred-rqst -n demo
+approved
+
+$ kubectl get secretaccessrequest -n demo mariadb-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: mariadb-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: MariaDBRole
+ name: mariadb-superuser-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2020-11-18T06:41:57Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: your-database-path/creds/k8s.-.demo.mariadb-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx
+ renewable: true
+ secret:
+ name: mariadb-cred-rqst-gy66wq
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest mariadb-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-18T06:41:57Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "your-database-path/creds/k8s.-.demo.mariadb-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx",
+ "renewable": true
+ },
+ "secret": {
+ "name": "mariadb-cred-rqst-gy66wq"
+ }
+}
+
+$ kubectl get secret -n demo mariadb-cred-rqst-gy66wq -o yaml
+apiVersion: v1
+data:
+ password: QTFhLVBkZGlsZFFxa0o1cnlvR20=
+ username: di1rdWJlcm5ldGVzLWRlbW8TE1NzQwNTkzMTc=
+kind: Secret
+metadata:
+ name: mariadb-cred-rqst-gy66wq
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: mariadb-cred-rqst
+ uid: 54ce63ca-d0e7-4b97-9085-b52eb3cb334f
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo mariadb-cred-rqst
+secretaccessrequest.engine.kubevault.com "mariadb-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest mariadb-cred-rqst -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mongodb/_index.md b/content/docs/v2025.11.21/guides/secret-engines/mongodb/_index.md
new file mode 100755
index 000000000..d482f96f1
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mongodb/_index.md
@@ -0,0 +1,17 @@
+---
+title: MongoDB | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: mongodb-secret-engines
+ name: MongoDB
+ parent: secret-engines-guides
+ weight: 30
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mongodb/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/mongodb/csi-driver.md
new file mode 100644
index 000000000..f7d0f520f
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mongodb/csi-driver.md
@@ -0,0 +1,295 @@
+---
+title: Mount MongoDB Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-mongodb
+ name: CSI Driver
+ parent: mongodb-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount MongoDB Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/mongodb) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure MongoDB SecretEngine
+
+### Enable MongoDB SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/secretengine.yaml
+secretengine.engine.kubevault.com/mongo-engine created
+```
+
+### Create MongoDBRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/secretenginerole.yaml
+mongodbroles.engine.kubevault.com/mongo-superuser-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: MongoDBRole
+ name: mongo-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/secretrolebinding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.mongo-reader-role"
+ objects: |
+ - objectName: "mongo-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.mongo-superuser-role"
+ secretKey: "username"
+ - objectName: "mongo-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.mongo-superuser-role"
+ secretKey: "password"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `MongoDB` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/mongo-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/mongo-creds
+mongo-creds-password mongo-creds-username
+
+/ # cat /secrets-store/mongo-creds/mongo-creds-password
+TAu2Zvg1WYE07W8Uf-nW
+
+/ # cat /secrets-store/mongo-creds/mongo-creds-username
+v-kubernetes-test-k8s.-.demo.mongo-s-iPkxiH80Ollq2QgF82Ab-1629178048
+
+/ # exit
+```
+
+So, we can see that the secret `db-username` and `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mongodb/overview.md b/content/docs/v2025.11.21/guides/secret-engines/mongodb/overview.md
new file mode 100644
index 000000000..4d3622e32
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mongodb/overview.md
@@ -0,0 +1,336 @@
+---
+title: Manage MongoDB credentials using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-mongodb
+ name: Overview
+ parent: mongodb-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage MongoDB credentials using the KubeVault operator
+
+MongoDB is one of the supported plugins for the database secrets engine. This plugin generates database credentials dynamically based on configured roles for the MongoDB database. You can easily manage [MongoDB secret engine](https://www.vaultproject.io/docs/secrets/databases/mongodb.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [MongoDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/docs/secrets/databases/mongodb#setup) using MongoDB and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure MongoDB Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for the MongoDB secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: mongo-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mongodb:
+ databaseRef:
+ name: mongodb
+ namespace: demo
+ pluginName: "mongodb-database-plugin"
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/secretengine.yaml
+secretengine.engine.kubevault.com/mongo-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS AGE
+mongo-engine Success 10s
+```
+
+Since the status is `Success`, the MongoDB secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create MongoDB Role
+
+By using [MongoDBRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mongodb), you can create a [role](https://www.vaultproject.io/docs/secrets/databases/mongodb#setup) on the Vault server in Kubernetes native way.
+
+A sample MongoDBRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MongoDBRole
+metadata:
+ name: mongo-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: mongo-secret-engine
+ creationStatements:
+ - "{ \"db\": \"admin\", \"roles\": [{ \"role\": \"readWrite\" }, {\"role\": \"read\", \"db\": \"foo\"}] }"
+ defaultTTL: 1h
+ maxTTL: 24h
+```
+
+Let's deploy MongoDBRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/secretenginerole.yaml
+mongodbrole.engine.kubevault.com/mongo-superuser-role created
+
+$ kubectl get mongodbrole -n demo
+NAME STATUS AGE
+mongo-superuser-role Success 34m
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-database-path/roles
+Keys
+----
+k8s.-.demo.mongo-superuser-role
+
+$ vault read your-database-path/roles/k8s.-.demo.mongo-superuser-role
+Key Value
+--- -----
+creation_statements [{ "db": "admin", "roles": [{ "role": "readWrite" }, {"role": "read", "db": "foo"}] }]
+db_name k8s.-.db.mongodb
+default_ttl 1h
+max_ttl 24h
+renew_statements []
+revocation_statements []
+rollback_statements []
+```
+
+If we delete the MongoDBRole, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete mongodbrole -n demo mongo-superuser-role
+mongodbrole.engine.kubevault.com "mongo-superuser-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read your-database-path/roles/k8s.-.demo.mongo-superuser-role
+No value found at your-database-path/roles/k8s.-.demo.mongo-superuser-role
+
+$ vault list your-database-path/roles
+No value found at your-database-path/roles/
+```
+
+## Generate MongoDB credentials
+
+Here, we are going to make a request to Vault for MongoDB credentials by creating `mongo-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: mongo-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: MongoDBRole
+ name: mongo-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of MongoDB against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mongodb/mongodbaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/mongo-cred-rqst created
+
+$ kubectl get secretaccessrequest -n demo
+NAME AGE
+mongo-cred-rqst 72m
+```
+
+Database credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest mongo-cred-rqst -n demo
+approved
+
+$ kubectl get secretaccessrequest -n demo mongo-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: mongo-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: MongoDBRole
+ name: mongo-superuser-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2020-11-18T06:41:57Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: your-database-path/creds/k8s.-.demo.mongo-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx
+ renewable: true
+ secret:
+ name: mongo-cred-rqst-gy66wq
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest mongo-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-18T06:41:57Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "your-database-path/creds/k8s.-.demo.mongo-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx",
+ "renewable": true
+ },
+ "secret": {
+ "name": "mongo-cred-rqst-gy66wq"
+ }
+}
+
+$ kubectl get secret -n demo mongo-cred-rqst-gy66wq -o yaml
+apiVersion: v1
+data:
+ password: QTFhLVBkZGlsZFFxa0o1cnlvR20=
+ username: di1rdWJlcm5ldGVzLWRlbW8TE1NzQwNTkzMTc=
+kind: Secret
+metadata:
+ name: mongo-cred-rqst-gy66wq
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: mongo-cred-rqst
+ uid: 54ce63ca-d0e7-4b97-9085-b52eb3cb334f
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo mongo-cred-rqst
+secretaccessrequest.engine.kubevault.com "mongo-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest mongo-cred-rqst -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mysql/_index.md b/content/docs/v2025.11.21/guides/secret-engines/mysql/_index.md
new file mode 100755
index 000000000..e10552c7e
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mysql/_index.md
@@ -0,0 +1,17 @@
+---
+title: MySQL | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: mysql-secret-engines
+ name: MySQL
+ parent: secret-engines-guides
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mysql/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/mysql/csi-driver.md
new file mode 100644
index 000000000..36fc00790
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mysql/csi-driver.md
@@ -0,0 +1,297 @@
+---
+title: Mount MySQL Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-mysql
+ name: CSI Driver
+ parent: mysql-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount MySQL Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/mysql) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure MySQL SecretEngine
+
+### Enable MySQL SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/secretengine.yaml
+secretengine.engine.kubevault.com/mysql-engine created
+```
+
+### Create MySQLRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/secretenginerole.yaml
+mysqlrole/mysql-superuser-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: MySQLRole
+ name: mysql-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.mysql-reader-role"
+ objects: |
+ - objectName: "mysql-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.mysql-superuser-role"
+ secretKey: "username"
+ - objectName: "mysql-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.mysql-superuser-role"
+ secretKey: "password"
+
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `MySQL` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/mysql-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/mysql-creds
+mysql-creds-password mysql-creds-username
+
+/ # cat /secrets-store/mysql-creds/mysql-creds-password
+TAu2Zvg1WYE07W8Uf-nW
+
+/ # cat /secrets-store/mysql-creds/mysql-creds-username
+v-kubernetes-test-k8s.-.demo.mysql-s-iPkxiH80Ollq2QgF82Ab-1629178048
+
+/ # exit
+```
+
+So, we can see that the secret `db-username` and `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/mysql/overview.md b/content/docs/v2025.11.21/guides/secret-engines/mysql/overview.md
new file mode 100644
index 000000000..4f6f3a1bd
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/mysql/overview.md
@@ -0,0 +1,337 @@
+---
+title: Manage MySQL credentials using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-mysql
+ name: Overview
+ parent: mysql-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage MySQL credentials using the KubeVault operator
+
+MySQL is one of the supported plugins for the database secrets engine. This plugin generates database credentials dynamically based on configured roles for the MySQL database. You can easily manage [MySQL secret engine](https://www.vaultproject.io/docs/secrets/databases/mysql-maria.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [MySQLRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mysql)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/docs/secrets/databases/mysql-maria#setup) using MySQL and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure MySQL Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for the MySQL secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: mysql-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ mysql:
+ databaseRef:
+ name: mysql
+ namespace: demo
+ pluginName: "mysql-database-plugin"
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/secretengine.yaml
+secretengine.engine.kubevault.com/mysql-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS AGE
+mysql-engine Success 10s
+```
+
+Since the status is `Success`, the MySQL secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create MySQL Role
+
+By using [MySQLRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/mysql), you can create a [role](https://www.vaultproject.io/docs/secrets/databases/mysql-maria#setup) on the Vault server in Kubernetes native way.
+
+A sample MySQLRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: MySQLRole
+metadata:
+ name: mysql-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: sql-secrt-engine
+ creationStatements:
+ - "CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';"
+ - "GRANT SELECT ON *.* TO '{{name}}'@'%';"
+ defaultTTL: 1h
+ maxTTL: 24h
+```
+
+Let's deploy MySQLRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/secretenginerole.yaml
+mongodbrole.engine.kubevault.com/mysql-superuser-role created
+
+$ kubectl get mysqlrole -n demo
+NAME STATUS AGE
+mysql-superuser-role Success 34m
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-database-path/roles
+Keys
+----
+k8s.-.demo.mysql-superuser-role
+
+$ vault read your-database-path/roles/k8s.-.demo.mysql-superuser-role
+Key Value
+--- -----
+creation_statements [CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON *.* TO '{{name}}'@'%';]
+db_name k8s.-.demo.mysql
+default_ttl 1h
+max_ttl 24h
+renew_statements []
+revocation_statements []
+rollback_statements []
+```
+
+If we delete the MySQL, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete mysqlrole -n demo mysql-superuser-role
+mysqlrole.engine.kubevault.com "mysql-superuser-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read your-database-path/roles/k8s.-.demo.mysql-superuser-role
+No value found at your-database-path/roles/k8s.-.demo.mysql-superuser-role
+
+$ vault list your-database-path/roles
+No value found at your-database-path/roles/
+```
+
+## Generate MySQL credentials
+
+Here, we are going to make a request to Vault for MySQL credentials by creating `mysql-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: mysql-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: MySQLRole
+ name: mysql-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of MySQL against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/mysql/mysqlaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/mysql-cred-rqst created
+
+$ kubectl get secretaccessrequest -n demo
+NAME AGE
+mysql-cred-rqst 72m
+```
+
+Database credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest mysql-cred-rqst -n demo
+approved
+
+$ kubectl get secretaccessrequest -n demo mysql-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: mysql-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: MySQLRole
+ name: mysql-superuser-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2020-11-18T06:41:57Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: your-database-path/creds/k8s.-.demo.mysql-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx
+ renewable: true
+ secret:
+ name: mysql-cred-rqst-gy66wq
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest mysql-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-18T06:41:57Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "your-database-path/creds/k8s.-.demo.mysql-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx",
+ "renewable": true
+ },
+ "secret": {
+ "name": "mysql-cred-rqst-gy66wq"
+ }
+}
+
+$ kubectl get secret -n demo mysql-cred-rqst-gy66wq -o yaml
+apiVersion: v1
+data:
+ password: QTFhLVBkZGlsZFFxa0o1cnlvR20=
+ username: di1rdWJlcm5ldGVzLWRlbW8TE1NzQwNTkzMTc=
+kind: Secret
+metadata:
+ name: mysql-cred-rqst-gy66wq
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: mysql-cred-rqst
+ uid: 54ce63ca-d0e7-4b97-9085-b52eb3cb334f
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo mysql-cred-rqst
+secretaccessrequest.engine.kubevault.com "mysql-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest mysql-cred-rqst -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/pki/_index.md b/content/docs/v2025.11.21/guides/secret-engines/pki/_index.md
new file mode 100755
index 000000000..f372266c9
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/pki/_index.md
@@ -0,0 +1,17 @@
+---
+title: PKI | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: pki-secret-engines
+ name: PKI
+ parent: secret-engines-guides
+ weight: 50
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/pki/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/pki/csi-driver.md
new file mode 100644
index 000000000..8d30e2bc2
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/pki/csi-driver.md
@@ -0,0 +1,406 @@
+---
+title: Mount PKI(certificates) Secrets into Kubernetes pod using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-pki
+ name: CSI Driver
+ parent: pki-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount PKI(certificates) Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/pki) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure PKI Secret Engine
+
+We will use the [Vault CLI](https://www.vaultproject.io/docs/commands/#vault-commands-cli-) throughout the tutorial to [enable and configure](https://www.vaultproject.io/docs/secrets/pki/index.html#setup) the PKI secret engine.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+To use secret from `PKI` secret engine, you have to perform the following steps.
+
+### Enable PKI Secret Engine
+
+To enable `PKI` secret engine run the following command.
+
+```bash
+$ vault secrets enable pki
+Success! Enabled the pki secrets engine at: pki/
+```
+
+Increase the TTL by tuning the secrets engine. The default value of 30 days may be too short, so increase it to 1 year:
+
+```bash
+$ vault secrets tune -max-lease-ttl=8760h pki
+Success! Tuned the secrets engine at: pki/
+```
+
+### Configure CA Certificate and Private Key
+
+Configure a CA certificate and private key. Vault can accept an existing key pair, or it can generate its own self-signed root.
+
+```bash
+$ vault write pki/root/generate/internal \
+ common_name=my-website.com \
+ ttl=8760h
+Key Value
+--- -----
+certificate -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+expiration 1606200496
+issuing_ca -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+serial_number 10:39:a7:02:60:b4:b2:22:12:96:b7:b3:0f:7f:c2:79:45:d3:49:fb
+```
+
+### Configure a PKI Role
+
+We need to configure a role that maps a name in vault to a procedure for generating certificate. When users of machines generate credentials, they are generated agains this role:
+
+```bash
+$ vault write pki/roles/example-dot-com \
+ allowed_domains=my-website.com \
+ allow_subdomains=true \
+ max_ttl=72h
+Success! Data written to: pki/roles/example-dot-com
+```
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create VaultPolicy and VaultPolicyBinding for Pod's Service Account
+
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.-.demo.pki-se-role`.
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: pki-se-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "pki/issue/*" {
+ capabilities = ["update"]
+ }
+---
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: pki-se-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: pki-se-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "test-user-account"
+ serviceAccountNamespaces:
+ - "demo"
+```
+
+Let's create VaultPolicy and VaultPolicyBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/policy.yaml
+vaultpolicy.policy.kubevault.com/pki-se-policy created
+
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/policybinding.yaml
+vaultpolicybinding.policy.kubevault.com/pki-se-role created
+```
+
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+pki-se-policy Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+pki-se-role Success 10s
+```
+
+## Mount Certificates into a Kubernetes Pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.pki-se-role"
+ objects: |
+ - objectName: "certificate"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "certificate"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+
+ - objectName: "issuing_ca"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "issuing_ca"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+
+ - objectName: "private_key"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "private_key"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+
+ - objectName: "private_key_type"
+ secretPath: "pki/issue/example-dot-com"
+ secretKey: "private_key_type"
+ secretArgs:
+ common_name: "www.my-website.com"
+ ttl: 24h
+ method: "POST"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+
+Here, you can also pass the following parameters optionally to issue the certificate
+
+- `common_name` (string: ) – Specifies the requested CN for the certificate. If the CN is allowed by role policy, it will be issued.
+
+- `alt_names` (string: "") – Specifies requested Subject Alternative Names, in a comma-delimited list. These can be host names or email addresses; they will be parsed into their respective fields. If any requested names do not match role policy, the entire request will be denied.
+
+- `ip_sans` (string: "") – Specifies requested IP Subject Alternative Names, in a comma-delimited list. Only valid if the role allows IP SANs (which is the default).
+
+- `uri_sans` (string: "") – Specifies the requested URI Subject Alternative Names, in a comma-delimited list.
+
+- `other_sans` (string: "") – Specifies custom OID/UTF8-string SANs. These must match values specified on the role in allowed_other_sans (globbing allowed). The format is the same as OpenSSL: ;: where the only current valid type is UTF8. This can be a comma-delimited list or a JSON string slice.
+
+- `ttl` (string: "") – Specifies requested Time To Live. Cannot be greater than the role's max_ttl value. If not provided, the role's ttl value will be used. Note that the role values default to system values if not explicitly set.
+
+- `format` (string: "") – Specifies the format for returned data. Can be pem, der, or pem_bundle; defaults to pem. If der, the output is base64 encoded. If pem_bundle, the certificate field will contain the private key and certificate, concatenated; if the issuing CA is not a Vault-derived self-signed root, this will be included as well.
+
+- `private_key_format` (string: "") – Specifies the format for marshaling the private key. Defaults to der which will return either base64-encoded DER or PEM-encoded DER, depending on the value of format. The other option is pkcs8 which will return the key marshalled as PEM-encoded PKCS8.
+
+- `exclude_cn_from_sans` (bool: false) – If true, the given common_name will not be included in DNS or Email Subject Alternate Names (as appropriate). Useful if the CN is not a hostname or email address, but is instead some human-readable identifier.
+
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `PKI` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/pki-assets"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/pod.yaml
+pod/demo-app created
+```
+
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n test pod/demo-app -- /bin/sh
+
+/ # ls /secrets-store/pki-assets
+certificate issuing_ca private_key private_key_type
+
+/ # cat /secrets-store/pki-assets/certificate
+-----BEGIN CERTIFICATE-----
+MIIDVjCCAj6gAwIBAgIUNjTBC3qR7Zaj0XrzUc3QEbE+EhgwDQYJKoZIhvcNAQEL
+BQAwGTEXMBUGA1UEAxMObXktd2Vic2l0ZS5jb20wHhcNMTkxMjEzMTExNDIwWhcN
+..... .... .... .... .... .... .... .... .... .... .... .... ...
+bo901cITjNyCTbAF2401pYFZ4rSlxhcuAvc7c27uqvKEh2/ctMGRkvPVygbPdvB8
+LfCskfX0sk8PQiEznlmYlChK3KNsEp+xSCyjU+pDEw8AcDXwE6vVFft/fRX0oiHH
+KIzTZ7R/QKUkLisloMUHStINISAehglLZTJjo79jB7GN66wyqP+E8iRLEYFAAsb0
+aZ5wuSTYEpqOuP6G1tOdhiE7iptFu9Wg9dKtmXkZnc0iTBL60xMUUapH
+-----END CERTIFICATE-----
+```
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/pki/overview.md b/content/docs/v2025.11.21/guides/secret-engines/pki/overview.md
new file mode 100644
index 000000000..d5c6f1da8
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/pki/overview.md
@@ -0,0 +1,458 @@
+---
+title: Manage PKI(certificates) secrets using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-pki
+ name: Overview
+ parent: pki-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage PKI(certificates) secrets using the KubeVault operator
+
+The [PKI secrets engine](https://www.vaultproject.io/docs/secrets/pki/index.html) generates dynamic X.509 certificates. With this secrets engine, services can get certificates without going through the usual manual process of generating a private key and CSR, submitting to a CA, and waiting for a verification and signing process to complete. Vault's built-in authentication and authorization mechanisms provide the verification functionality.
+
+You can easily manage [PKI secret engine](https://www.vaultproject.io/docs/secrets/pki/index.html) using the KubeVault operator.
+
+You should be familiar with the following CRD:
+
+- [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy)
+- [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding)
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to demonstrate the use of the PKI secret engine.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Use PKI Secret Engine as Root User
+
+Here, we are going to use the Vault root token to perform authentication to the Vault server. We will use the [Vault CLI](https://www.vaultproject.io/docs/commands/#vault-commands-cli-) throughout the tutorial.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+Export the root token as environment variable:
+
+```bash
+$ export VAULT_TOKEN=s.diWLjSzmfSmF0qUNYV3qOIeX
+```
+
+Enable the PKI secrets engine:
+
+```bash
+$ vault secrets enable pki
+Success! Enabled the pki secrets engine at: pki/
+```
+
+Increase the TTL by tuning the secrets engine. The default value of 30 days may be too short, so increase it to 1 year:
+
+```bash
+$ vault secrets tune -max-lease-ttl=8760h pki
+Success! Tuned the secrets engine at: pki/
+```
+
+Configure a CA certificate and private key:
+
+```bash
+$ vault write pki/root/generate/internal \
+ common_name=my-website.com \
+ ttl=8760h
+Key Value
+--- -----
+certificate -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+expiration 1606200496
+issuing_ca -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+serial_number 10:39:a7:02:60:b4:b2:22:12:96:b7:b3:0f:7f:c2:79:45:d3:49:fb
+```
+
+Configure a role that maps a name in Vault to a procedure for generating a certificate. When users or machines generate credentials, they are generated against this role:
+
+```bash
+$ vault write pki/roles/example-dot-com \
+ allowed_domains=my-website.com \
+ allow_subdomains=true \
+ max_ttl=72h
+Success! Data written to: pki/roles/example-dot-com
+```
+
+Generate a new credential by writing to the /issue endpoint with the name of the role:
+
+```bash
+$ vault write pki/issue/example-dot-com \
+ common_name=www.my-website.com
+Key Value
+--- -----
+certificate -----BEGIN CERTIFICATE-----
+MIIDVjCCAj6gAwIBAgIUWQhPLW6R/nk/3x3XReHC1Ze4BWUwDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+TSuguIiSBt5NN0ou4aY01FbeJJOHZhtpj31XdXOCAKR40lPCmWtEUAbcuEhLlkm+
+vmhNYxBqkx33jEIMxk95P4eKIYPyr45/8o7bV1jq7G26aBzj1Mjd0JmU
+-----END CERTIFICATE-----
+expiration 1574924103
+issuing_ca -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+private_key -----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuK7V4GuoHSF8pnlr4hApeU7V3zpuQ2rWt3pXgi9TPBCmIuye
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
++o8HetGW5xWvuQ/ObkiSzdQ8nxMyiQj/whe4riYriOw1fYwPrjZfxTm1jsyEmbbm
+gYewhfHP3hOgTCVu3SjhvOXS3pnW7hUP4wtvpLLdRumEUM/fK7pwNg==
+-----END RSA PRIVATE KEY-----
+private_key_type rsa
+serial_number 59:008:4f:2d:6e:91:fe:79:3f:df:1d:d7:45:e1:c2:d5:97:b8:05:65
+```
+
+For more details visit the [official Vault documentation](https://www.vaultproject.io/docs/secrets/pki/index.html#setup).
+
+## Use PKI Secret Engine as Non-root User
+
+Here, we are going to create a Kubernetes service account and give it limited access (i.e only PKI secret engine) from the Vault using the VaultPolicy and the VaultPolicyBinding.
+
+### Create Kubernetes Service Account
+
+Create a service account `pki-admin` to the `demo` namespace:
+
+```bash
+$ kubectl create serviceaccount -n demo pki-admin
+serviceaccount/pki-admin created
+
+# get service account JWT token which will be required while performing
+# login operation to the Vault
+$ kubectl get secrets -n demo pki-admin-token-26kwb -o jsonpath="{.data.token}" | base64 --decode;
+eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InBraS1hZG1pbi10b2tlbi0yNmt3YiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJwa2ktYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkYmVkZDQ2Ni0yYzc0LTQ0OGItOTBlZS01MDlkNGI4MTJjOTEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVtbzpwa2ktYWRtaW4ifQ.ce7OqA05nsfBMRsEOiG1Lje_mOBdUZRKALB9Sc9LVqjKIJZHdxvZ7NT4ZKrIyPEe02aItzxlXLAP4Fa8dUMshZuNyuxBYN7p2qHRCwVKHqOuz8LdRQWypKiLozL9v0DHk-vbFWFcm0eye57vJBFtriYyYRUA84WZhxRb9wz-f8z7PSmO2mpjkrICt7wi48j-4FObdhFWk6HAKXFD7bCzL4j3CWUcx2wTIsnOEz9SifjYZuGaog6tpWhnj-guEKpXJzBLAoMBU0Vr3U7Zv_z1qvKFF4ZherUBxSOMo27lL2xbhkpbW2wf_DCAjLx8pScoh9mxv7AK2WJCHeA0JRzrug
+```
+
+### Create VaultPolicy and VaultPolicyBinding
+
+A sample VaultPolicy object with necessary path permission for the PKI secret engine:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: pki-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "sys/mounts" {
+ capabilities = ["read", "list"]
+ }
+
+ path "sys/mounts/*" {
+ capabilities = ["create", "read", "update", "delete"]
+ }
+
+ path "pki/*" {
+ capabilities = ["read","create", "list", "update", "delete"]
+ }
+
+ path "sys/leases/revoke/*" {
+ capabilities = ["update"]
+ }
+```
+
+Create VaultPolicy and check status:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/policy.yaml
+vaultpolicy.policy.kubevault.com/pki-policy created
+
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+pki-policy Success 3m15s
+```
+
+A sample VaultPolicyBinding object that binds the `pki-policy` to the `pki-admin` service account:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: pki-admin-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: pki-policy
+ subjectRef:
+ kubernetes:
+ serviceAccountNames:
+ - "pki-admin"
+ serviceAccountNamespaces:
+ - "demo"
+ ttl: "1000"
+ maxTTL: "2000"
+ period: "1000"
+```
+
+Create VaultPolicyBinding and check status:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/pki/policyBinding.yaml
+vaultpolicybinding.policy.kubevault.com/pki-admin-role created
+
+$ kubectl get vaultpolicybindings -n demo
+NAME STATUS AGE
+pki-admin-role Success 43m
+```
+
+### Login Vault and Use PKI Secret Engine
+
+To resolve the naming conflict, name of the policy and role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+List Vault policies and Kubernetes auth roles:
+
+```bash
+$ vault list sys/policy
+Keys
+----
+k8s.-.demo.pki-policy
+
+$ vault read sys/policy/k8s.-.demo.pki-policy
+Key Value
+--- -----
+name k8s.-.demo.pki-policy
+rules path "sys/mounts" {
+ capabilities = ["read", "list"]
+}
+
+path "sys/mounts/*" {
+ capabilities = ["create", "read", "update", "delete"]
+}
+
+path "pki/*" {
+ capabilities = ["read","create", "list", "update", "delete"]
+}
+
+path "sys/leases/revoke/*" {
+ capabilities = ["update"]
+}
+
+$ vault list auth/kubernetes/role
+Keys
+----
+k8s.-.demo.pki-admin-role
+
+$ vault read auth/kubernetes/role/k8s.-.demo.pki-admin-role
+Key Value
+--- -----
+bound_service_account_names [pki-admin]
+bound_service_account_namespaces [demo]
+max_ttl 33m20s
+period 16m40s
+policies [k8s.-.demo.pki-policy]
+token_bound_cidrs []
+token_explicit_max_ttl 0s
+token_max_ttl 33m20s
+token_no_default_policy false
+token_num_uses 0
+token_period 16m40s
+token_policies [k8s.-.demo.pki-policy]
+token_ttl 16m40s
+token_type default
+ttl 16m40s
+```
+
+So, we can see that the `pki-policy` is added to the `pki-admin-role`.
+
+Now, login to the Vault using `pki-admin`'s JWT token under `pki-admin-role` role.
+
+```bash
+$ vault write auth/kubernetes/login \
+ role=k8s.-.demo.pki-admin-role \
+ jwt=eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZW1vIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InBraS1hZG1pbi10b2tlbi0yNmt3YiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJwa2ktYWRtaW4iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkYmVkZDQ2Ni0yYzc0LTQ0OGItOTBlZS01MDlkNGI4MTJjOTEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVtbzpwa2ktYWRtaW4ifQ.ce7OqA05nsfBMRsEOiG1Lje_mOBdUZRKALB9Sc9LVqjKIJZHdxvZ7NT4ZKrIyPEe02aItzxlXLAP4Fa8dUMshZuNyuxBYN7p2qHRCwVKHqOuz8LdRQWypKiLozL9v0DHk-vbFWFcm0eye57vJBFtriYyYRUA84WZhxRb9wz-f8z7PSmO2mpjkrICt7wi48j-4FObdhFWk6HAKXFD7bCzL4j3CWUcx2wTIsnOEz9SifjYZuGaog6tpWhnj-guEKpXJzBLAoMBU0Vr3U7Zv_z1qvKFF4ZherUBxSOMo27lL2xbhkpbW2wf_DCAjLx8pScoh9mxv7AK2WJCHeA0JRzrug
+
+Key Value
+--- -----
+token s.ZPu4zcyaajjpxtS1t8fnh2LV
+token_accessor 5OknOf72h8WnP1v0I1C01626
+token_duration 16m40s
+token_renewable true
+token_policies ["default" "k8s.-.demo.pki-policy"]
+identity_policies []
+policies ["default" "k8s.-.demo.pki-policy"]
+token_meta_role k8s.-.demo.pki-admin-role
+token_meta_service_account_name pki-admin
+token_meta_service_account_namespace demo
+token_meta_service_account_secret_name pki-admin-token-26kwb
+token_meta_service_account_uid dbedd466-2c74-448b-90ee-509d4b812c91
+```
+
+Export the new Vault token as an environment variable:
+
+```bash
+export VAULT_TOKEN=(kubectl vault root-token get vaultserver vault -n demo --value-only)
+```
+
+Now generate a new certificate using the PKI secret engine.
+
+Enable the PKI secrets engine:
+
+```bash
+$ vault secrets enable pki
+Success! Enabled the pki secrets engine at: pki/
+```
+
+Increase the TTL by tuning the secrets engine. The default value of 30 days may be too short, so increase it to 1 year:
+
+```bash
+$ vault secrets tune -max-lease-ttl=8760h pki
+Success! Tuned the secrets engine at: pki/
+```
+
+Configure a CA certificate and private key:
+
+```bash
+$ vault write pki/root/generate/internal \
+ common_name=my-website.com \
+ ttl=8760h
+Key Value
+--- -----
+certificate -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+expiration 1606200496
+issuing_ca -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+serial_number 10:39:a7:02:60:b4:b2:22:12:96:b7:b3:0f:7f:c2:79:45:d3:49:fb
+```
+
+Configure a role that maps a name in Vault to a procedure for generating a certificate. When users or machines generate credentials, they are generated against this role:
+
+```bash
+$ vault write pki/roles/example-dot-com \
+ allowed_domains=my-website.com \
+ allow_subdomains=true \
+ max_ttl=72h
+Success! Data written to: pki/roles/example-dot-com
+```
+
+Generate a new credential by writing to the /issue endpoint with the name of the role:
+
+```bash
+$ vault write pki/issue/example-dot-com \
+ common_name=www.my-website.com
+Key Value
+--- -----
+certificate -----BEGIN CERTIFICATE-----
+MIIDVjCCAj6gAwIBAgIUWQhPLW6R/nk/3x3XReHC1Ze4BWUwDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+TSuguIiSBt5NN0ou4aY01FbeJJOHZhtpj31XdXOCAKR40lPCmWtEUAbcuEhLlkm+
+vmhNYxBqkx33jEIMxk95P4eKIYPyr45/8o7bV1jq7G26aBzj1Mjd0JmU
+-----END CERTIFICATE-----
+expiration 1574924103
+issuing_ca -----BEGIN CERTIFICATE-----
+MIIDPjCCAiagAwIBAgIUEDmnAmC0siISlrezD3/CeUXTSfswDQYJKoZIhvcNAQEL
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
+CsFVu+vfMM9XEMYeKHRWAq9onJFyGuwKGhF0/7RbZ3EunTj6Zph+UMucGoL4xfXj
+ITltdU1N4JPvihQq+8Omryay
+-----END CERTIFICATE-----
+private_key -----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuK7V4GuoHSF8pnlr4hApeU7V3zpuQ2rWt3pXgi9TPBCmIuye
+... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
++o8HetGW5xWvuQ/ObkiSzdQ8nxMyiQj/whe4riYriOw1fYwPrjZfxTm1jsyEmbbm
+gYewhfHP3hOgTCVu3SjhvOXS3pnW7hUP4wtvpLLdRumEUM/fK7pwNg==
+-----END RSA PRIVATE KEY-----
+private_key_type rsa
+serial_number 59:008:4f:2d:6e:91:fe:79:3f:df:1d:d7:45:e1:c2:d5:97:b8:05:65
+```
+
+For more details visit the [official Vault documentation](https://www.vaultproject.io/docs/secrets/pki/index.html#setup).
diff --git a/content/docs/v2025.11.21/guides/secret-engines/postgres/_index.md b/content/docs/v2025.11.21/guides/secret-engines/postgres/_index.md
new file mode 100755
index 000000000..55db79922
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/postgres/_index.md
@@ -0,0 +1,17 @@
+---
+title: PostgreSQL | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: postgres-secret-engines
+ name: PostgreSQL
+ parent: secret-engines-guides
+ weight: 60
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/postgres/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/postgres/csi-driver.md
new file mode 100644
index 000000000..3019a73fd
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/postgres/csi-driver.md
@@ -0,0 +1,297 @@
+---
+title: Mount PostgreSQL Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-postgresql
+ name: CSI Driver
+ parent: postgres-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount PostgreSQL Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.21.2
+Server Version: v1.21.1
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/postgres) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure PostgreSQL SecretEngine
+
+### Enable PostgreSQL SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/secretengine.yaml
+secretengine.engine.kubevault.com/postgres-engine created
+```
+
+### Create PostgreSQLRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/secretenginerole.yaml
+postgresrole.engine.kubevault.com/postgres-superuser-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.postgres-superuser-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: PostgresRole
+ name: postgres-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/secretrolebinding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: "k8s.-.demo.postgres-reader-role"
+ objects: |
+ - objectName: "postgres-creds-username"
+ secretPath: "your-database-path/creds/k8s.-.demo.postgres-superuser-role"
+ secretKey: "username"
+ - objectName: "postgres-creds-password"
+ secretPath: "your-database-path/creds/k8s.-.demo.postgres-superuser-role"
+ secretKey: "password"
+
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `Postgres` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/postgres-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/postgres-creds
+postgres-creds-password postgres-creds-username
+
+/ # cat /secrets-store/postgres-creds/postgres-creds-password
+TAu2Zvg1WYE07W8Uf-nW
+
+/ # cat /secrets-store/postgres-creds/postgres-creds-username
+v-kubernetes-test-k8s.-.demo.postgres-s-iPkxiH80Ollq2QgF82Ab-1629178048
+
+/ # exit
+```
+
+So, we can see that the secret `db-username` and `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/postgres/overview.md b/content/docs/v2025.11.21/guides/secret-engines/postgres/overview.md
new file mode 100644
index 000000000..bd94c058f
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/postgres/overview.md
@@ -0,0 +1,338 @@
+---
+title: Manage PostgreSQL credentials using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-postgresql
+ name: Overview
+ parent: postgres-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage PostgreSQL credentials using the KubeVault operator
+
+PostgreSQL is one of the supported plugins for the database secrets engine. This plugin generates database credentials dynamically based on configured roles for the PostgreSQL database. You can easily manage [PostgreSQL secret engine](https://www.vaultproject.io/docs/secrets/databases/postgresql.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [PostgresRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://www.vaultproject.io/docs/secrets/databases/postgresql#setup) using PostgreSQL and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure PostgreSQL Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for the PostgreSQL secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: postgres-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ postgres:
+ databaseRef:
+ name: postgres
+ namespace: demo
+ pluginName: "postgresql-database-plugin"
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/secretengine.yaml
+secretengine.engine.kubevault.com/postgres-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS AGE
+postgres-engine Success 10s
+```
+
+Since the status is `Success`, the PostgreSQL secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create PostgreSQL Role
+
+By using [PostgresRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/postgresrole), you can create a [role](https://www.vaultproject.io/docs/secrets/databases/postgresql#setup) on the Vault server in Kubernetes native way.
+
+A sample PostgresRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: PostgresRole
+metadata:
+ name: postgres-superuser-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: vault
+ creationStatements:
+ - "CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';"
+ - "GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"
+ defaultTTL: 1h
+ maxTTL: 24h
+
+```
+
+Let's deploy PostgresRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/secretenginerole.yaml
+postgresrole.engine.kubevault.com/postgres-superuser-role created
+
+$ kubectl get postgresrole -n demo
+NAME STATUS AGE
+postgres-superuser-role Success 34m
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list your-database-path/roles
+Keys
+----
+k8s.-.demo.postgres-superuser-role
+
+$ vault read your-database-path/roles/k8s.-.demo.postgres-superuser-role
+Key Value
+--- -----
+creation_statements [CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO "{{name}}";]
+db_name k8s.-.db.postgres
+default_ttl 1h
+max_ttl 24h
+renew_statements []
+revocation_statements []
+rollback_statements []
+```
+
+If we delete the PostgreSQL, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete postgresrole -n demo postgresrole-superuser-role
+postgresrolerole.engine.kubevault.com "postgres-superuser-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read your-database-path/roles/k8s.-.demo.postgres-superuser-role
+No value found at your-database-path/roles/k8s.-.demo.postgres-superuser-role
+
+$ vault list your-database-path/roles
+No value found at your-database-path/roles/
+```
+
+## Generate PostgreSQL credentials
+
+Here, we are going to make a request to Vault for PostgreSQL credentials by creating `postgres-cred-rqst` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: postgres-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: PostgresRole
+ name: postgres-superuser-role
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+```
+
+Here, `spec.roleRef` is the reference of Postgres against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/postgres/mysqlaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/postgres-cred-rqst created
+
+$ kubectl get secretaccessrequest -n demo
+NAME AGE
+postgres-cred-rqst 72m
+```
+
+Database credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest postgres-cred-rqst -n demo
+approved
+
+$ kubectl get secretaccessrequest -n demo postgres-cred-rqst -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: postgres-cred-rqst
+ namespace: demo
+spec:
+ roleRef:
+ kind: PostgresRole
+ name: postgres-superuser-role
+ namespace: demo
+ subjects:
+ - kind: ServiceAccount
+ name: demo-sa
+ namespace: demo
+status:
+ conditions:
+ - lastUpdateTime: "2020-11-18T06:41:57Z"
+ message: This was approved by kubectl vault approve secretaccessrequest
+ reason: KubectlApprove
+ type: Approved
+ lease:
+ duration: 1h0m0s
+ id: your-database-path/creds/k8s.-.demo.postgres-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx
+ renewable: true
+ secret:
+ name: postgres-cred-rqst-gy66wq
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest postgres-cred-rqst -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastUpdateTime": "2019-11-18T06:41:57Z",
+ "message": "This was approved by kubectl vault approve secretaccessrequest",
+ "reason": "KubectlApprove",
+ "type": "Approved"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "your-database-path/creds/k8s.-.demo.postgres-superuser-role/ni3TCo2HkSwCUb8kmQuvIDdx",
+ "renewable": true
+ },
+ "secret": {
+ "name": "postgres-cred-rqst-gy66wq"
+ }
+}
+
+$ kubectl get secret -n demo postgres-cred-rqst-gy66wq -o yaml
+apiVersion: v1
+data:
+ password: QTFhLVBkZGlsZFFxa0o1cnlvR20=
+ username: di1rdWJlcm5ldGVzLWRlbW8TE1NzQwNTkzMTc=
+kind: Secret
+metadata:
+ name: postgres-cred-rqst-gy66wq
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ controller: true
+ kind: SecretAccessRequest
+ name: postgres-cred-rqst
+ uid: 54ce63ca-d0e7-4b97-9085-b52eb3cb334f
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo postgres-cred-rqst
+secretaccessrequest.engine.kubevault.com "postgres-cred-rqst" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest mysql-cred-rqst -n demo
+ Denied
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/secret-engines/redis/_index.md b/content/docs/v2025.11.21/guides/secret-engines/redis/_index.md
new file mode 100644
index 000000000..25caa1878
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/redis/_index.md
@@ -0,0 +1,17 @@
+---
+title: Redis | Vault Secret Engine
+menu:
+ docs_v2025.11.21:
+ identifier: redis-secret-engines
+ name: Redis
+ parent: secret-engines-guides
+ weight: 40
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/secret-engines/redis/csi-driver.md b/content/docs/v2025.11.21/guides/secret-engines/redis/csi-driver.md
new file mode 100644
index 000000000..0bcf0c723
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/redis/csi-driver.md
@@ -0,0 +1,340 @@
+---
+title: Mount Redis Secrets using CSI Driver
+menu:
+ docs_v2025.11.21:
+ identifier: csi-driver-redis
+ name: CSI Driver
+ parent: redis-secret-engines
+ weight: 15
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+# Mount Redis Secrets using CSI Driver
+
+## Kubernetes Secrets Store CSI Driver
+
+Secrets Store CSI driver for Kubernetes secrets - Integrates secrets stores with Kubernetes via a [Container Storage Interface (CSI)](https://kubernetes-csi.github.io/docs/) volume.
+
+The Secrets Store CSI driver `secrets-store.csi.k8s.io` allows Kubernetes to mount multiple secrets, keys, and certs stored in enterprise-grade external secrets stores into their pods as a volume. Once the Volume is attached, the data in it is mounted into the container’s file system.
+
+
+
+When the `Pod` is created through the K8s API, it’s scheduled on to a node. The `kubelet` process on the node looks at the pod spec & see if there's any `volumeMount` request. The `kubelet` issues an `RPC` to the `CSI driver` to mount the volume. The `CSI driver` creates & mounts `tmpfs` into the pod. Then the `CSI driver` issues a request to the `Provider`. The provider talks to the external secrets store to fetch the secrets & write them to the pod volume as files. At this point, volume is successfully mounted & the pod starts running.
+
+You can read more about the Kubernetes Secrets Store CSI Driver [here](https://secrets-store-csi-driver.sigs.k8s.io/).
+
+## Consuming Secrets
+
+At first, you need to have a Kubernetes 1.16 or later cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). To check the version of your cluster, run:
+
+```bash
+$ kubectl version --short
+Client Version: v1.24.0
+Kustomize Version: v4.5.4
+Server Version: v1.23.13
+```
+
+Before you begin:
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+- Install Secrets Store CSI driver for Kubernetes secrets in your cluster from [here](https://secrets-store-csi-driver.sigs.k8s.io/getting-started/installation.html).
+- Install Vault Specific CSI provider from [here](https://github.com/hashicorp/vault-csi-provider)
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial stored in [examples](/docs/v2025.11.21/examples/guides/secret-engines/redis) folder in GitHub repository [KubeVault/docs](https://github.com/kubevault/kubevault)
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator. To create a Redis Secret Engine, VaultServer version needs to be 1.12.1+.
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server. And we also have the service account that the Vault server can authenticate.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2022-12-27T09:37:31Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha2
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: e32d10cd-aec9-4060-bc9a-098d69bb5d6b
+ resourceVersion: "294415"
+ uid: 09011421-5a2f-44cf-a8ac-7069565b0f78
+spec:
+ appRef:
+ apiGroup: kubevault.com
+ kind: VaultServer
+ name: vault
+ namespace: demo
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ backend: raft
+ backupTokenSecretRef:
+ name: vault-backup-token
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ stash:
+ addon:
+ backupTask:
+ name: vault-backup-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ restoreTask:
+ name: vault-restore-1.10.3
+ params:
+ - name: keyPrefix
+ value: k8s.kubevault.com.demo.vault
+ unsealer:
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ secretShares: 5
+ secretThreshold: 3
+ vaultRole: vault-policy-controller
+```
+
+## Enable & Configure REdis SecretEngine
+
+### Enable Redis SecretEngine
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/secretengine.yaml
+secretengine.engine.kubevault.com/redis-secret-engine created
+```
+
+### Create RedisRole
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/secretenginerole.yaml
+redisrole.engine.kubevault.com/write-read-role created
+```
+
+Let's say pod's service account name is `test-user-account` located in `demo` namespace. We need to create a [VaultPolicy](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) and a [VaultPolicyBinding](/docs/v2025.11.21/concepts/policy-crds/vaultpolicybinding) so that the pod has access to read secrets from the Vault server.
+
+### Create Service Account for Pod
+
+Let's create the service account `test-user-account` which will be used in VaultPolicyBinding.
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: test-user-account
+ namespace: demo
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/serviceaccount.yaml
+serviceaccount/test-user-account created
+
+$ kubectl get serviceaccount -n demo
+NAME SECRETS AGE
+test-user-account 1 4h10m
+```
+
+### Create SecretRoleBinding for Pod's Service Account
+
+SecretRoleBinding will create VaultPolicy and VaultPolicyBinding inside vault.
+When a VaultPolicyBinding object is created, the KubeVault operator create an auth role in the Vault server. The role name is generated by the following naming format: `k8s.(clusterName or -).namespace.name`. Here, it is `k8s.kubevault.com.demo.write-read-role`.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretRoleBinding
+metadata:
+ name: secret-role-binding
+ namespace: demo
+spec:
+ roles:
+ - kind: RedisRole
+ name: write-read-role
+ subjects:
+ - kind: ServiceAccount
+ name: test-user-account
+ namespace: demo
+```
+
+Let's create SecretRoleBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/secret-role-binding.yaml
+secretrolebinding.engine.kubevault.com/secret-role-binding created
+```
+Check if the VaultPolicy and the VaultPolicyBinding are successfully registered to the Vault server:
+
+```bash
+$ kubectl get vaultpolicy -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 8s
+
+$ kubectl get vaultpolicybinding -n demo
+NAME STATUS AGE
+srb-demo-secret-role-binding Success 10s
+```
+
+## Mount secrets into a Kubernetes pod
+
+So, we can create `SecretProviderClass` now. You can read more about `SecretProviderClass` [here](https://secrets-store-csi-driver.sigs.k8s.io/concepts.html#secretproviderclass).
+
+### Create SecretProviderClass
+
+Get `roleName` from VaultPolicyBinding
+```bash
+$ kubectl get vaultpolicybinding -n demo srb-demo-secret-role-binding -o=jsonpath="{['spec.vaultRoleName']}"
+k8s.kubevault.com.demo.srb-demo-secret-role-binding
+```
+
+The `secretPath` can be constructed as `your-data-base-path/creds/your-role-name`.
+Or get secretPath from VaultPolicy
+```bash
+$ kubectl get vaultpolicy -n demo srb-demo-secret-role-binding -o=jsonpath="{['spec.policyDocument']}"
+path "/k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role" {
+ capabilities = ["read"]
+}
+```
+
+The secretPath here is `/k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role`
+
+Create `SecretProviderClass` object with the following content:
+
+```yaml
+apiVersion: secrets-store.csi.x-k8s.io/v1
+kind: SecretProviderClass
+metadata:
+ name: vault-db-provider
+ namespace: demo
+spec:
+ provider: vault
+ parameters:
+ vaultAddress: "http://vault.demo:8200"
+ roleName: k8s.kubevault.com.demo.srb-demo-secret-role-binding
+ objects: |
+ - objectName: "redis-creds-username"
+ secretPath: "/k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role"
+ secretKey: "username"
+ - objectName: "redis-creds-password"
+ secretPath: "/k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role"
+ secretKey: "password"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/secretproviderclass.yaml
+secretproviderclass.secrets-store.csi.x-k8s.io/vault-db-provider created
+```
+
+NOTE: The `SecretProviderClass` needs to be created in the same namespace as the pod.
+
+### Create Pod
+
+Now we can create a `Pod` to consume the `Redis` secrets. When the `Pod` is created, the `Provider` fetches the secret and writes them to Pod's volume as files. At this point, the volume is successfully mounted and the `Pod` starts running.
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: demo-app
+ namespace: demo
+spec:
+ serviceAccountName: test-user-account
+ containers:
+ - image: jweissig/app:0.0.1
+ name: demo-app
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: secrets-store-inline
+ mountPath: "/secrets-store/redis-creds"
+ readOnly: true
+ volumes:
+ - name: secrets-store-inline
+ csi:
+ driver: secrets-store.csi.k8s.io
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: "vault-db-provider"
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/pod.yaml
+pod/demo-app created
+```
+## Test & Verify
+
+Check if the Pod is running successfully, by running:
+
+```bash
+$ kubectl get pods -n demo
+NAME READY STATUS RESTARTS AGE
+demo-app 1/1 Running 0 11s
+```
+
+### Verify Secret
+
+If the Pod is running successfully, then check inside the app container by running
+
+```bash
+$ kubectl exec -it -n demo pod/demo-app -- /bin/sh
+/ # ls /secrets-store/redis-creds
+redis-creds-password redis-creds-username
+
+/ # cat /secrets-store/redis-creds/redis-creds-password
+eEip9Orr-yFONjlRGntY
+
+/ # cat /secrets-store/redis-creds/redis-creds-username
+V_KUBERNETES-DEMO-TEST-USER-ACCOUNT_K8S.KUBEVAULT.COM.DEMO.WRITE-READ-ROLE_764DXABBDPMUGZP9C6AB_1672/app
+
+/ # exit
+```
+
+So, we can see that the secret `db-username` and `db-password` is mounted into the pod, where the secret key is mounted as file and value is the content of that file.
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+$ kubectl delete ns demo
+namespace "demo" deleted
+
+```
diff --git a/content/docs/v2025.11.21/guides/secret-engines/redis/overview.md b/content/docs/v2025.11.21/guides/secret-engines/redis/overview.md
new file mode 100644
index 000000000..1d04db4ea
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/secret-engines/redis/overview.md
@@ -0,0 +1,382 @@
+---
+title: Manage Redis credentials using the KubeVault operator
+menu:
+ docs_v2025.11.21:
+ identifier: overview-redis
+ name: Overview
+ parent: redis-secret-engines
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Manage Redis credentials using the KubeVault operator
+
+Redis is one of the supported plugins for the database secrets engine. This plugin generates database credentials dynamically based on configured roles for the Redis database. You can easily manage [Redis secret engine](https://www.vaultproject.io/docs/secrets/databases/redis.html) using the KubeVault operator.
+
+
+
+You need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine)
+- [RedisRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/redis)
+
+## Before you begin
+
+- Install KubeVault operator in your cluster from [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+In this tutorial, we are going to create a [role](https://developer.hashicorp.com/vault/docs/secrets/databases/redis#setup) using Redis and issue credential using SecretAccessRequest.
+
+## Vault Server
+
+If you don't have a Vault Server, you can deploy it by using the KubeVault operator. To create a Redis Secret Engine, VaultServer version needs to be 1.12.1+
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+
+The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. You need to configure both the Vault server and the cluster so that the KubeVault operator can communicate with your Vault server.
+
+- [Configure cluster and Vault server](/docs/v2025.11.21/guides/vault-server/external-vault-sever#configuration)
+
+Now, we have the [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) that contains connection and authentication information about the Vault server.
+
+```bash
+$ kubectl get appbinding -n demo
+NAME AGE
+vault 50m
+
+$ kubectl get appbinding -n demo vault -o yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ creationTimestamp: "2021-08-16T08:23:38Z"
+ generation: 1
+ labels:
+ app.kubernetes.io/instance: vault
+ app.kubernetes.io/managed-by: kubevault.com
+ app.kubernetes.io/name: vaultservers.kubevault.com
+ name: vault
+ namespace: demo
+ ownerReferences:
+ - apiVersion: kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: VaultServer
+ name: vault
+ uid: 6b405147-93da-41ff-aad3-29ae9f415d0a
+ resourceVersion: "602898"
+ uid: b54873fd-0f34-42f7-bdf3-4e667edb4659
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: http
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ kubernetes:
+ serviceAccountName: vault
+ tokenReviewerServiceAccountName: vault-k8s-token-reviewer
+ usePodServiceAccountForCSIDriver: true
+ path: kubernetes
+ vaultRole: vault-policy-controller
+```
+
+## Enable and Configure Redis Secret Engine
+
+When a [SecretEngine](/docs/v2025.11.21/concepts/secret-engine-crds/secretengine) crd object is created, the KubeVault operator will enable a secret engine on specified path and configure the secret engine with given configurations.
+
+A sample SecretEngine object for the Redis secret engine:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretEngine
+metadata:
+ name: redis-secret-engine
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ namespace: demo
+ redis:
+ databaseRef:
+ name: redis-standalone
+ namespace: demo
+ pluginName: "redis-database-plugin"
+
+```
+
+Let's deploy SecretEngine:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/secretengine.yaml
+secretengine.engine.kubevault.com/redis-secret-engine created
+```
+
+Wait till the status become `Success`:
+
+```bash
+$ kubectl get secretengines -n demo
+NAME STATUS AGE
+redis-secret-engine Success 10s
+```
+
+Since the status is `Success`, the Redis secret engine is enabled and successfully configured. You can use `kubectl describe secretengine -n ` to check for error events, if any.
+
+## Create Redis Role
+
+By using [RedisRole](/docs/v2025.11.21/concepts/secret-engine-crds/database-secret-engine/redis), you can create a [role](https://developer.hashicorp.com/vault/docs/secrets/databases/redis#setup) on the Vault server in Kubernetes native way.
+
+A sample RedisRole object is given below:
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: RedisRole
+metadata:
+ name: write-read-role
+ namespace: demo
+spec:
+ secretEngineRef:
+ name: redis-secret-engine
+ creationStatements:
+ - '["~*", "+@read","+@write"]'
+ defaultTTL: 1h
+ maxTTL: 24h
+```
+
+Let's deploy RedisRole:
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/secretenginerole.yaml
+redisrole.engine.kubevault.com/write-read-role created
+
+$ kubectl get redisrole -n demo
+NAME STATUS AGE
+write-read-role Success 34m
+```
+
+You can also check from Vault that the role is created.
+To resolve the naming conflict, name of the role in Vault will follow this format: `k8s.{clusterName}.{metadata.namespace}.{metadata.name}`.
+
+> Don't have Vault CLI? Download and configure it as described [here](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+```bash
+$ vault list k8s.kubevault.com.redis.demo.redis-secret-engine/roles
+Keys
+----
+k8s.kubevault.com.demo.write-read-role
+
+$ vault read k8s.kubevault.com.redis.demo.redis-secret-engine/roles/k8s.kubevault.com.demo.write-read-role
+Key Value
+--- -----
+creation_statements [["~*", "+@read","+@write"]]
+credential_type password
+db_name k8s.kubevault.com.demo.redis-standalone
+default_ttl 1h
+max_ttl 24h
+renew_statements []
+revocation_statements []
+rollback_statements []
+```
+
+If we delete the Redis, then the respective role will be deleted from the Vault.
+
+```bash
+$ kubectl delete -n demo redisrole write-read-role
+redisrole.engine.kubevault.com "write-read-role" deleted
+```
+
+Check from Vault whether the role exists:
+
+```bash
+$ vault read k8s.kubevault.com.redis.demo.redis-secret-engine/roles/k8s.kubevault.com.demo.write-read-role
+No value found at k8s.kubevault.com.redis.demo.redis-secret-engine/roles/k8s.kubevault.com.demo.write-read-role
+
+$ vault list k8s.kubevault.com.redis.demo.redis-secret-engine/roles
+No value found at k8s.kubevault.com.redis.demo.redis-secret-engine/roles
+```
+
+## Generate Redis credentials
+
+Here, we are going to make a request to Vault for Redis credentials by creating `write-read-access-req` SecretAccessRequest in `demo` namespace.
+
+```yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ name: write-read-access-req
+ namespace: demo
+spec:
+ roleRef:
+ kind: RedisRole
+ name: write-read-role
+ subjects:
+ - kind: ServiceAccount
+ name: write-read-user
+ namespace: demo
+
+```
+
+Here, `spec.roleRef` is the reference of Redis against which credentials will be issued. `spec.subjects` is the reference to the object or user identities a role binding applies to it will have read access of the credential secret.
+
+Now, we are going to create SecretAccessRequest.
+
+```bash
+$ kubectl apply -f docs/examples/guides/secret-engines/redis/redisaccessrequest.yaml
+secretaccessrequest.engine.kubevault.com/write-read-access-req created
+
+$ kubectl get secretaccessrequest -n demo
+NAME STATUS AGE
+write-read-access-req WaitingForApproval 14s
+```
+
+Database credentials will not be issued until it is approved. The KubeVault operator will watch for the approval in the `status.conditions[].type` field of the request object. You can use [KubeVault CLI](https://github.com/kubevault/cli), a [kubectl plugin](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/), to approve or deny SecretAccessRequest.
+
+```bash
+# using KubeVault CLI as kubectl plugin to approve request
+$ kubectl vault approve secretaccessrequest write-read-access-req -n demo
+secretaccessrequests write-read-access-req approved
+
+$ kubectl get secretaccessrequest -n demo write-read-access-req -o yaml
+apiVersion: engine.kubevault.com/v1alpha1
+kind: SecretAccessRequest
+metadata:
+ annotations:
+ kubectl.kubernetes.io/last-applied-configuration: |
+ {"apiVersion":"engine.kubevault.com/v1alpha1","kind":"SecretAccessRequest","metadata":{"annotations":{},"name":"write-read-access-req","namespace":"demo"},"spec":{"roleRef":{"kind":"RedisRole","name":"write-read-role"},"subjects":[{"kind":"ServiceAccount","name":"write-read-user","namespace":"demo"}]}}
+ vaultservers.kubevault.com/name: vault
+ vaultservers.kubevault.com/namespace: demo
+ creationTimestamp: "2022-12-28T09:14:25Z"
+ finalizers:
+ - kubevault.com
+ generation: 1
+ name: write-read-access-req
+ namespace: demo
+ resourceVersion: "341401"
+ uid: 0bf92c6a-fbbb-4600-8bc8-8bddbf2c34dd
+spec:
+ roleRef:
+ kind: RedisRole
+ name: write-read-role
+ subjects:
+ - kind: ServiceAccount
+ name: write-read-user
+ namespace: demo
+status:
+ conditions:
+ - lastTransitionTime: "2022-12-28T09:15:22Z"
+ message: 'This was approved by: kubectl vault approve secretaccessrequest'
+ observedGeneration: 1
+ reason: KubectlApprove
+ status: "True"
+ type: Approved
+ - lastTransitionTime: "2022-12-28T09:15:22Z"
+ message: The requested credentials successfully issued.
+ observedGeneration: 1
+ reason: SuccessfullyIssuedCredential
+ status: "True"
+ type: Available
+ lease:
+ duration: 1h0m0s
+ id: k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role/mNeREfw0SJQBekA8ZkzJn2Tf
+ renewable: true
+ observedGeneration: 1
+ phase: Approved
+ secret:
+ name: write-read-access-req-c9ttdf
+ namespace: demo
+```
+
+Once SecretAccessRequest is approved, the KubeVault operator will issue credentials from Vault and create a secret containing the credential. It will also create a role and rolebinding so that `spec.subjects` can access secret. You can view the information in the `status` field.
+
+```bash
+$ kubectl get secretaccessrequest write-read-access-req -n demo -o json | jq '.status'
+{
+ "conditions": [
+ {
+ "lastTransitionTime": "2022-12-28T09:15:22Z",
+ "message": "This was approved by: kubectl vault approve secretaccessrequest",
+ "observedGeneration": 1,
+ "reason": "KubectlApprove",
+ "status": "True",
+ "type": "Approved"
+ },
+ {
+ "lastTransitionTime": "2022-12-28T09:15:22Z",
+ "message": "The requested credentials successfully issued.",
+ "observedGeneration": 1,
+ "reason": "SuccessfullyIssuedCredential",
+ "status": "True",
+ "type": "Available"
+ }
+ ],
+ "lease": {
+ "duration": "1h0m0s",
+ "id": "k8s.kubevault.com.redis.demo.redis-secret-engine/creds/k8s.kubevault.com.demo.write-read-role/mNeREfw0SJQBekA8ZkzJn2Tf",
+ "renewable": true
+ },
+ "observedGeneration": 1,
+ "phase": "Approved",
+ "secret": {
+ "name": "write-read-access-req-c9ttdf",
+ "namespace": "demo"
+ }
+}
+
+$ kubectl get secret -n demo
+NAME TYPE DATA AGE
+write-read-access-req-c9ttdf Opaque 2 2m3s
+
+$ kubectl get secret -n demo write-read-access-req-c9ttdf -o yaml
+apiVersion: v1
+data:
+ password: MUtwT2YtV0lyZG1qSTJQUktwSFg=
+ username: Vl9LVUJFUk5FVEVTLURFTU8tVkFVTFRfSzhTLktVQkVWQVVMVC5DT00uREVNTy5XUklURS1SRUFELVJPTEVfQVlCVFBLTVhGUEdPM0tHR05NUjJfMTY3MjIxODkyMg==
+kind: Secret
+metadata:
+ creationTimestamp: "2022-12-28T09:15:22Z"
+ name: write-read-access-req-c9ttdf
+ namespace: demo
+ ownerReferences:
+ - apiVersion: engine.kubevault.com/v1alpha1
+ blockOwnerDeletion: true
+ controller: true
+ kind: SecretAccessRequest
+ name: write-read-access-req
+ uid: 0bf92c6a-fbbb-4600-8bc8-8bddbf2c34dd
+ resourceVersion: "341397"
+ uid: b038419d-59ff-4946-8ff3-1a04984d6f0f
+type: Opaque
+```
+
+If SecretAccessRequest is deleted, then credential lease (if any) will be revoked.
+
+```bash
+$ kubectl delete secretaccessrequest -n demo write-read-access-req
+secretaccessrequest.engine.kubevault.com "write-read-access-req" deleted
+```
+
+If SecretAccessRequest is `Denied`, then the KubeVault operator will not issue any credential.
+
+```bash
+$ kubectl vault deny secretaccessrequest write-read-access-req -n demo
+secretaccessrequest.engine.kubevault.com "write-read-access-req" deleted
+```
+
+> Note: Once SecretAccessRequest is `Approved`, you cannot change `spec.roleRef` and `spec.subjects` field.
diff --git a/content/docs/v2025.11.21/guides/vault-ops-request/_index.md b/content/docs/v2025.11.21/guides/vault-ops-request/_index.md
new file mode 100644
index 000000000..6be31265f
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-ops-request/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Ops Request Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: ops-request-guides
+ name: Vault Ops Request
+ parent: guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/vault-ops-request/overview.md b/content/docs/v2025.11.21/guides/vault-ops-request/overview.md
new file mode 100644
index 000000000..2ed3553a9
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-ops-request/overview.md
@@ -0,0 +1,53 @@
+---
+title: Vault Ops Request Overview
+menu:
+ docs_v2025.11.21:
+ identifier: overview-ops-request-guides
+ name: Overview
+ parent: ops-request-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/README).
+
+# Reconfiguring TLS of VaultServer
+
+This guide will give an overview on how KubeVault Enterprise operator reconfigures TLS configuration i.e. add TLS, remove TLS, update issuer/cluster issuer or Certificates and rotate the certificates of a `VaultServer`.
+
+## Before You Begin
+
+- You should be familiar with the following `KubeVault` concepts:
+ - [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+ - [VaultOpsRequest](/docs/v2025.11.21/concepts/vault-ops-request/overview)
+
+## How Reconfiguring VaultServer TLS Configuration Process Works
+
+The Reconfiguring VaultServer TLS process consists of the following steps:
+
+1. At first, a user creates a `VaultServer` Custom Resource Object (CRO).
+
+2. `KubeVault` operator watches the `VaultServer` CRO.
+
+3. When the operator finds a `VaultServer` CR, it creates required number of `StatefulSets` and related necessary stuff like secrets, services, etc.
+
+4. Then, in order to reconfigure the TLS configuration of the `VaultServer` the user creates a `VaultOpsRequest` CR with desired information.
+
+5. `KubeVault` operator watches the `VaultOpsRequest` CR.
+
+6. When it finds a `VaultOpsRequest` CR, it pauses the `VaultServer` object which is referred from the `VaultOpsRequest`. So, the `KubeVault` operator doesn't perform any operations on the `VaultServer` object during the reconfiguring TLS process.
+
+7. Then the `KubeVault` operator will add, remove, update or rotate TLS configuration based on the Ops Request yaml.
+
+8. Then the `KubeVault` operator will restart all the Pods of the database so that they restart with the new TLS configuration defined in the `VaultOpsRequest` CR.
+
+9. After the successful reconfiguring of the `VaultServer` TLS, the `KubeVault` operator resumes the `VaultServer` object so that the `KubeVault` Community operator resumes its usual operations.
+
+In the next docs, we are going to show a step by step guide on reconfiguring TLS configuration of a VaultServer using `VaultOpsRequest` CRD.
\ No newline at end of file
diff --git a/content/docs/v2025.11.21/guides/vault-ops-request/reconfigure_tls.md b/content/docs/v2025.11.21/guides/vault-ops-request/reconfigure_tls.md
new file mode 100644
index 000000000..8170e850b
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-ops-request/reconfigure_tls.md
@@ -0,0 +1,416 @@
+---
+title: Vault Ops Request Reconfigure TLS
+menu:
+ docs_v2025.11.21:
+ identifier: reconfigure-tls-ops-request-guides
+ name: Reconfigure TLS
+ parent: ops-request-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/README).
+
+# Reconfigure VaultServer TLS/SSL
+
+`KubeVault` supports reconfigure i.e. add, remove, update and rotation of TLS/SSL certificates for existing `VaultServer` via a `VaultOpsRequest`. This tutorial will show you how to use `KubeVault` to reconfigure TLS/SSL encryption.
+
+## Before You Begin
+
+- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/).
+
+- Install [`cert-manger`](https://cert-manager.io/docs/installation/) v1.0.0 or later to your cluster to manage your SSL/TLS certificates.
+
+- Now, install KubeVault cli on your workstation and KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+> Note: YAML files used in this tutorial are stored in [docs/examples/guides/vault-ops-request](https://github.com/kubevault/kubevault/tree/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request) folder in GitHub repository [kubevault/kubevault](https://github.com/kubevault/kubevault).
+
+## Add TLS to a VaultServer
+
+Here, We are going to create a `VaultServer` without TLS and then reconfigure the `VaultServer` to use TLS.
+
+### Deploy VaultServer without TLS
+
+In this section, we are going to deploy a VaultServer without TLS. In the next few sections we will reconfigure TLS using `VaultOpsRequest` CRD. Below is the YAML of the `VaultServer` CR that we are going to create,
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.10.3
+ replicas: 3
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ secretEngines:
+ - gcp
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 5
+ secretThreshold: 3
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: WipeOut
+
+```
+
+Let's create the `VaultServer` CR we have shown above,
+
+```bash
+$ kubectl create -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/vaultserver.yaml
+vaultserver.kubevault.com/vault created
+```
+
+
+Now, wait until `VaultServer` has status `Ready`. i.e,
+
+```bash
+$ kubectl get vs -n demo
+NAME REPLICAS VERSION STATUS AGE
+vault 3 1.12.1 Ready 128m
+```
+
+### Create Issuer/ ClusterIssuer
+
+Now, We are going to create an example `Issuer` that will be used to enable SSL/TLS in VaultServer. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`.
+
+- Start off by generating a ca certificates using openssl.
+
+```bash
+$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=vault/O=kubevault"
+Generating a RSA private key
+................+++++
+........................+++++
+writing new private key to './ca.key'
+-----
+```
+
+- Now we are going to create a ca-secret using the certificate files that we have just generated.
+
+```bash
+$ kubectl create secret tls vault-ca --cert=ca.crt --key=ca.key --namespace=demo
+
+secret/vault-ca created
+```
+
+Now, Let's create an `Issuer` using the `vault-ca` secret that we have just created. The `YAML` file looks like this:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: issuer
+ namespace: demo
+spec:
+ ca:
+ secretName: vault-ca
+```
+
+Let's apply the `YAML` file:
+
+```bash
+$ kubectl create -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/issuer.yaml
+issuer.cert-manager.io/issuer created
+```
+
+### Create VaultOpsRequest
+
+In order to add TLS to the VaultServer, we have to create a `VaultOpsRequest` CRO with our created issuer. Below is the YAML of the `VaultOpsRequest` CRO that we are going to create,
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-add-tls
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ issuerRef:
+ name: issuer
+ kind: Issuer
+ apiGroup: "cert-manager.io"
+ certificates:
+ - alias: client
+ subject:
+ organizations:
+ - appscode
+ organizationalUnits:
+ - client
+```
+
+Here,
+
+- `spec.vaultRef.name` specifies that we are performing reconfigure TLS operation on `vault` VaultServer.
+- `spec.type` specifies that we are performing `ReconfigureTLS` on our VaultServer.
+- `spec.tls.issuerRef` specifies the issuer name, kind and api group.
+- `spec.tls.certificates` specifies the certificates.
+
+Let's create the `VaultOpsRequest` CR we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/vault-ops-add-tls.yaml
+vaultopsrequest.ops.kubevault.com/vault-ops-add-tls created
+```
+
+#### Verify TLS Enabled Successfully
+
+Let's wait for `VaultOpsRequest` to be `Successful`. Run the following command to watch `VaultOpsRequest` CRO,
+
+```bash
+$ kubectl get vaultopsrequest -n demo
+Every 2.0s: kubectl get vaultopsrequest -n demo
+NAME TYPE STATUS AGE
+vault-ops-add-tls ReconfigureTLS Successful 91s
+```
+
+## Rotate Certificate
+
+Now we are going to rotate the certificate of this VaultServer. First let's check the current expiration date of the certificate.
+
+```bash
+$ kubectl exec -it -n demo vault-0 -- bin/sh
+/ # cd etc/vault/tls/server
+/etc/vault/tls/server # cat tls.crt
+-----BEGIN CERTIFICATE-----
+MIID2DCCAsCgAwIBAgIQL1rqn4OHpvchiFRI3DPXIjANBgkqhkiG9w0BAQsFADAk
+...
+XJRRwl5psqcyp5ZJI1ar5JP1JCGQa3QTArwstw==
+-----END CERTIFICATE-----
+```
+
+Copy & paste the certificate in any certificates decoding tool like [certlogic](https://certlogik.com/decoder/) & check it's expiry date.
+
+### Create VaultOpsRequest
+
+Now we are going to increase it using a VaultOpsRequest. Below is the yaml of the ops request that we are going to create,
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-rotate
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ rotateCertificates: true
+```
+
+Here,
+
+- `spec.vaultRef.name` specifies that we are performing reconfigure TLS operation on `vault` VaultServer.
+- `spec.type` specifies that we are performing `ReconfigureTLS` on our VaultServer.
+- `spec.tls.rotateCertificates` specifies that we want to rotate the certificate of this VaultServer.
+
+Let's create the `VaultOpsRequest` CR we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/vault-ops-rotate.yaml
+vaultopsrequest.ops.kubevault.com/vault-ops-rotate created
+```
+
+#### Verify Certificate Rotated Successfully
+
+Let's wait for `VaultOpsRequest` to be `Successful`. Run the following command to watch `VaultOpsRequest` CRO,
+
+```bash
+$ kubectl get vaultopsrequest -n demo
+Every 2.0s: kubectl get vaultopsrequest -n demo
+NAME TYPE STATUS AGE
+vault-ops-rotate ReconfigureTLS Successful 112
+```
+
+Now, let's check the expiration date of the certificate again, it should be updated.
+
+```bash
+$ kubectl exec -it -n demo vault-0 -- bin/sh
+/ # cd etc/vault/tls/server
+/etc/vault/tls/server # cat tls.crt
+-----BEGIN CERTIFICATE-----
+MIID2DCCAsCgAwIBAgIQL1rqn4OHpvchiFRI3DPXIjANBgkqhkiG9w0BAQsFADAk
+...
+XJRRwl5psqcyp5ZJI1ar5JP1JCGQa3QTArwstw==
+-----END CERTIFICATE-----
+```
+
+## Change Issuer/ClusterIssuer
+
+Now, we are going to change the issuer of this VaultServer.
+
+- Let's create a new ca certificate and key using a different subject `CN=ca-updated,O=kubevault-updated`.
+
+```bash
+$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=ca-updated/O=kubevault-updated"
+Generating a RSA private key
+..............................................................+++++
+......................................................................................+++++
+writing new private key to './ca.key'
+-----
+```
+
+- Now we are going to create a new ca-secret using the certificate files that we have just generated.
+
+```bash
+$ kubectl create secret tls vault-new-ca \
+ --cert=ca.crt \
+ --key=ca.key \
+ --namespace=demo
+secret/vault-new-ca created
+```
+
+Now, Let's create a new `Issuer` using the `vault-new-ca` secret that we have just created. The `YAML` file looks like this:
+
+```yaml
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+ name: new-issuer
+ namespace: demo
+spec:
+ ca:
+ secretName: vault-new-ca
+```
+
+Let's apply the `YAML` file:
+
+```bash
+$ kubectl create -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/new-issuer.yaml
+issuer.cert-manager.io/new-issuer created
+```
+
+
+### Create VaultOpsRequest
+
+In order to use the new issuer to issue new certificates, we have to create a `VaultOpsRequest` CRO with the newly created issuer. Below is the YAML of the `VaultOpsRequest` CRO that we are going to create,
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-change-issuer
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ issuerRef:
+ name: new-issuer
+ kind: Issuer
+ apiGroup: "cert-manager.io"
+```
+
+Here,
+
+- `spec.vaultRef.name` specifies that we are performing reconfigure TLS operation on `vault` VaultServer.
+- `spec.type` specifies that we are performing `ReconfigureTLS` on our VaultServer.
+- `spec.tls.issuerRef` specifies the issuer name, kind and api group.
+
+Let's create the `VaultOpsRequest` CR we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/vault-ops-change-issuer.yaml
+vaultopsrequest.ops.kubevault.com/vault-ops-change-issuer created
+```
+
+#### Verify Issuer is changed successfully
+
+Let's wait for `VaultOpsRequest` to be `Successful`. Run the following command to watch `VaultOpsRequest` CRO,
+
+```bash
+$ kubectl get vaultopsrequest -n demo
+Every 2.0s: kubectl get vaultopsrequest -n demo
+NAME TYPE STATUS AGE
+vault-ops-change-issuer ReconfigureTLS Successful 105s
+```
+
+## Remove TLS from the VaultServer
+
+Now, we are going to remove TLS from this VaultServer using a VaultOpsRequest.
+
+### Create VaultOpsRequest
+
+Below is the YAML of the `VaultOpsRequest` CRO that we are going to create,
+
+```yaml
+apiVersion: ops.kubevault.com/v1alpha1
+kind: VaultOpsRequest
+metadata:
+ name: vault-ops-remove
+ namespace: demo
+spec:
+ type: ReconfigureTLS
+ vaultRef:
+ name: vault
+ tls:
+ remove: true
+```
+
+Here,
+
+- `spec.vaultRef.name` specifies that we are performing reconfigure TLS operation on `vault` VaultServer.
+- `spec.type` specifies that we are performing `ReconfigureTLS` on our VaultServer.
+- `spec.tls.remove` specifies that we want to remove tls from this VaultServer.
+
+Let's create the `VaultOpsRequest` CR we have shown above,
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-ops-request/vault-ops-remove.yaml
+vaultopsrequest.ops.kubeavult.com/vault-ops-remove created
+```
+
+#### Verify TLS Removed Successfully
+
+Let's wait for `VaultOpsRequest` to be `Successful`. Run the following command to watch `VaultOpsRequest` CRO,
+
+```bash
+$ kubectl get vaultopsrequest -n demo
+Every 2.0s: kubectl get vaultopsrequest -n demo
+NAME TYPE STATUS AGE
+vault-ops-remove ReconfigureTLS Successful 105s
+```
+
+## Cleaning up
+
+To clean up the Kubernetes resources created by this tutorial, run:
+
+```bash
+kubectl delete vaultserver -n demo vault
+kubectl delete issuer -n demo issuer new-issuer
+kubectl delete vaultopsrequest vault-ops-add-tls vault-ops-remove vault-ops-rotate vault-ops-change-issuer
+kubectl delete ns demo
+```
diff --git a/content/docs/v2025.11.21/guides/vault-server/_index.md b/content/docs/v2025.11.21/guides/vault-server/_index.md
new file mode 100755
index 000000000..b3028af15
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-server/_index.md
@@ -0,0 +1,17 @@
+---
+title: Vault Server Guides | KubeVault
+menu:
+ docs_v2025.11.21:
+ identifier: vault-server-guides
+ name: Vault Server
+ parent: guides
+ weight: 10
+menu_name: docs_v2025.11.21
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
diff --git a/content/docs/v2025.11.21/guides/vault-server/auth-method.md b/content/docs/v2025.11.21/guides/vault-server/auth-method.md
new file mode 100644
index 000000000..a8ec251ac
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-server/auth-method.md
@@ -0,0 +1,225 @@
+---
+title: Auth Method
+menu:
+ docs_v2025.11.21:
+ identifier: auth-method
+ name: Auth Method
+ parent: vault-server-guides
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+In this tutorial, we'll see how we can enable, configure `JWT/OIDC` auth method & use it to authenticate to `VaultServer` using `KubeVault`.
+
+> Before jumping in, an `OIDC Provider` must be configured. An `Auth0` application has already been configured for this tutorial purpose. Application `Domain`, `Client ID`, `Client Secret`, `Allowed Callback URLs`, etc. must be properly set from the provider side.
+
+## Deploy VaultServer, Enable & Configure Auth Methods
+
+Let's start by deploying the `VaultServer`. We're going to enable & configure `JWT` auth method in this tutorial.
+
+Here's the complete `VaultServer` yaml:
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ version: 1.10.3
+ replicas: 2
+ allowedSecretEngines:
+ namespaces:
+ from: All
+ secretEngines:
+ - gcp
+ authMethods:
+ - type: jwt
+ path: jwt
+ jwtConfig:
+ defaultLeaseTTL: 1h
+ defaultRole: k8s.kubevault.com.demo.reader-writer-role
+ oidcClientID: aFSrk3w06WsQqyjA30HvhbbJIR1VBidU
+ oidcDiscoveryURL: https://dev-tob49v6v.us.auth0.com/
+ credentialSecretRef:
+ name: jwt-cred
+ backend:
+ raft:
+ storage:
+ storageClassName: "standard"
+ resources:
+ requests:
+ storage: 1Gi
+ unsealer:
+ secretShares: 3
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+ monitor:
+ agent: prometheus.io
+ prometheus:
+ exporter:
+ resources: {}
+ terminationPolicy: WipeOut
+
+```
+
+Let's focus on the `.spec.authMethods` section here:
+
+```yaml
+authMethods:
+ - type: jwt
+ path: jwt
+ jwtConfig:
+ defaultLeaseTTL: 1h
+ defaultRole: k8s.kubevault.com.demo.reader-writer-role
+ oidcClientID: aFSrk3w06WsQqyjA30HvhbbJIR1VBidU
+ oidcDiscoveryURL: https://dev-tob49v6v.us.auth0.com/
+ credentialSecretRef:
+ name: jwt-cred
+
+```
+
+* `.spec.authMethods.type` is a required field, the type of authentication method we want to enable.
+* `.spec.authMethods.path` is a required field, the path where we want to enable this authentication method.
+* `.spec.authMethods.jwtConfig` contains various configuration for this authentication method. Details about configuration `parameters` can be found here: [JWT/OIDC Configuration](https://www.vaultproject.io/api-docs/auth/jwt#configure).
+
+In the `.spec.authMethods.jwtConfig` section, we've provided the necessary configuration details. A `K8s Secret` `jwt-cred` containing the provider `Client Secret` needs to be created before deploying the `VaultServer`, which is referred in the `.credentialSecretRef` section.
+
+Here's the `Secret` yaml:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: jwt-cred
+ namespace: demo
+stringData:
+ oidc_client_secret:
+
+```
+
+### Deploy the VaultServer
+
+Let's create the `Secret` first:
+```bash
+$ kubectl apply -f jwt-cred.yaml
+secret/jwt-cred created
+```
+
+Let's deploy the `VaultServer` now:
+```bash
+$ kubectl apply -f vaultserver.yaml
+vaultserver.kubevault.com/vault created
+```
+
+Upon successful deployment of `VaultServer`, the defined `authMethods` will be enabled & configured by the provider configuration. `KubeVault` operator will also create the necessary policies required for the auth methods.
+
+We can verify it using the `Vault CLI`:
+
+```bash
+$ vault auth list
+
+Path Type Accessor Description
+---- ---- -------- -----------
+jwt/ jwt auth_jwt_ba23cc30 n/a
+kubernetes/ kubernetes auth_kubernetes_40fd86fd n/a
+token/ token auth_token_950c8b80 token based credentials
+```
+
+```bash
+$ vault read auth/jwt/config
+
+Key Value
+--- -----
+bound_issuer n/a
+default_role k8s.kubevault.com.demo.reader-writer-role
+jwks_ca_pem n/a
+jwks_url n/a
+jwt_supported_algs []
+jwt_validation_pubkeys []
+namespace_in_state true
+oidc_client_id aFSrk3w06WsQqyjA30HvhbbJIR1VBidU
+oidc_discovery_ca_pem n/a
+oidc_discovery_url https://dev-tob49v6v.us.auth0.com/
+oidc_response_mode n/a
+oidc_response_types []
+provider_config map[]
+
+```
+### Create VaultPolicy & VaultPolicyBinding
+
+So, we're now ready to create `VaultPolicy` & `VaultPolicyBinding`. We'll create a simple `KV` policy to enable user with `read` & `list` privileges only.
+
+Here's the `VaultPolicy` yaml that we're going to create:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: reader-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "/kv/*" {
+ capabilities = ["read", "list"]
+ }
+
+```
+
+Let's create the `VaultPolicy`:
+
+```bash
+$ kubectl apply -f policy.yaml
+vaultpolicy.policy.kubevault.com/reader-policy created
+```
+
+Here's the `VaultPolicyBinding` yaml that we're going to create. Notice that, in the `.spec.subjectRef` section we're using the jwt method which is already enabled.
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicyBinding
+metadata:
+ name: reader-role
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policies:
+ - ref: reader-policy
+ subjectRef:
+ jwt:
+ path: jwt
+ boundAudiences:
+ - "aFSrk3w06WsQqyjA30HvhbbJIR1VBidU"
+ allowedRedirectUris:
+ - "http://localhost:8200/ui/vault/auth/jwt/oidc/callback"
+ - "http://localhost:8250/oidc/callback"
+ userClaim: "sub"
+
+```
+
+Let's create the `VaultPolicyBinding`:
+
+```bash
+$ kubectl apply -f policybinding.yaml
+vaultpolicybinding.policy.kubevault.com/reader-role created
+```
+
+When a `VaultPolicyBinding` is created, `KubeVault` will create a role which can be used to Login to the `Vault`. A Vault role `vaultRoleName: k8s.kubevault.com.demo.reader-role` will be created in our case.
+
+Now, we can port-forward from `Vault` & Login using the `Vault UI` with this role & the authentication method.
+
+
diff --git a/content/docs/v2025.11.21/guides/vault-server/external-vault-sever.md b/content/docs/v2025.11.21/guides/vault-server/external-vault-sever.md
new file mode 100644
index 000000000..d9572f4cc
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-server/external-vault-sever.md
@@ -0,0 +1,326 @@
+---
+title: External Vault Server
+menu:
+ docs_v2025.11.21:
+ identifier: external-vault-server
+ name: External Vault Server
+ parent: vault-server-guides
+ weight: 30
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# External Vault Server
+
+In this tutorial, we are going to demonstrate how the KubeVault operator works with external Vault servers (i.e. not provisioned by the KubeVault operator). To do so, we need to configure both the cluster and the Vault server.
+Later we will create a [Vault policy](https://www.vaultproject.io/docs/concepts/policies.html)
+using [VaultPolicy CRD](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) in Vault to check whether it is working or not.
+
+## Before you begin
+
+- Install KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+## Configuration
+
+To communicate with Vault, the KubeVault operator needs to perform authentication to Vault sever.
+The Vault server will issue a `token` in the response of successful authentication.
+Then the KubeVault operator will perform the rest of the tasks using that `token`.
+Hence, the `token` must have the path-permissions that we want to access from KubeVault operator over API call.
+
+We will use [Kubernetes auth method](https://www.vaultproject.io/docs/auth/kubernetes.html) throughout the tutorial,
+you can use any from the below list:
+
+- [AWS IAM Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/aws-iam)
+- [Kubernetes Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/kubernetes)
+- [TLS Certificates Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/tls)
+- [Token Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/token)
+- [Userpass Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/userpass)
+- [GCP IAM Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/gcp-iam)
+- [Azure Auth Method](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/azure)
+
+The whole configuration process can be divided into two parts:
+
+- `Cluster configuration`: Create an [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) which holds
+ connection and authentication information of Vault. Also create necessary Kubernetes resources (i.e. `secret`, `service account`, `ClusterRole`, `ClusterRoleBinding`, etc.) based on the requirements of the AppBinding.
+
+- `Vault configuration`: Enable and Configure the auth method in Vault. Create [Vault policy](https://www.vaultproject.io/docs/concepts/policies.html) with necessary path-permissions which will be required by the KubeVault operator. Create a `user` or a `role` under the auth method mentioning the vault policies. This role name will be referenced by the AppBinding while performing authentication to Vault and the Vault will issue `token` in the response of successful authentication with assigned policies.
+
+### Cluster Configuration
+
+Since we are using the Kubernetes auth method, we need to create two Kubernetes `service accounts`.
+One of them will be used by the Vault to verify Kubernetes authentication. The other one will be used by the AppBinding
+to perform authentication to Vault.
+
+#### Create Token Reviewer Service Account
+
+The [Kubernetes auth method](https://www.vaultproject.io/docs/auth/kubernetes.html) can be used to authenticate with Vault using a Kubernetes Service Account Token. This auth method accesses the Kubernetes `TokenReview API` to validate the provided JWT is still valid. The service account used in this auth method will need to have access to the `TokenReview API`. If Kubernetes is configured to use RBAC roles, the Service Account should be granted permission to access this API.
+
+Let's name token reviewer service account as `token-reviewer` and create it:
+
+```bash
+$ kubectl create serviceaccount -n demo token-reviewer
+serviceaccount/token-reviewer created
+```
+
+`ClusterRoleBinding` for the token reviewer service account:
+
+```yaml
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: role-tokenreview-binding
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: system:auth-delegator
+subjects:
+- kind: ServiceAccount
+ name: token-reviewer
+ namespace: demo
+```
+
+Create `ClusterRoleBinding`:
+
+```bash
+$ kubectl apply -f docs/examples/guides/vault-server/clusterRoleBinding.yaml
+clusterrolebinding.rbac.authorization.k8s.io/role-tokenreview-binding created
+```
+
+Get the service account JWT token which will be used while configuring Vault:
+
+```bash
+$ kubectl get secrets -n demo token-reviewer-token-s9hrs -o=jsonpath='{.data.token}' | base64 -d
+eyJhbGciOiJSUzI1NiIsImtp...
+```
+
+#### Create AppBinding Service Account
+
+The KubeVault operator will use the AppBinding that holds a reference to this service account to
+perform authentication.
+
+Let's name the service account `vault` and create it:
+
+```bash
+$ kubectl create serviceaccount -n demo vault
+serviceaccount/vault created
+```
+
+#### Create AppBinding
+
+The [AppBinding CRD](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding) provides a way to specify connection information, credential and
+parameters that are necessary for communicating with Vault.
+
+Access vault server using `url`:
+
+```yaml
+apiVersion: appcatalog.appscode.com/v1alpha1
+kind: AppBinding
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ clientConfig:
+ url: https://demo-vault-server.com ## remote vault server url
+ caBundle: eyJtc2ciOiJleGFtcGxlIn0= ## base64 encoded vault server ca.crt
+ parameters:
+ apiVersion: config.kubevault.com/v1alpha1
+ kind: VaultServerConfiguration
+ path: kubernetes ## Kubernetes auth is enabled in this path
+ vaultRole: vault-role ## auth-role name against which login will be done
+ kubernetes:
+ serviceAccountName: vault ## service account name
+ usePodServiceAccountForCSIDriver: true ## required while using CSI driver
+```
+
+Access vault server using Kubernetes service by replacing `spec.clientConfig`:
+
+```yaml
+spec:
+ clientConfig:
+ service:
+ name: vault
+ port: 8200
+ scheme: HTTPS
+ caBundle: eyJtc2ciOiJleGFtcGxlIn0= ## base64 encoded vault server ca.crt
+```
+
+Create AppBinding:
+
+```bash
+$ kubectl apply -f docs/examples/guides/vault-server/appBinding.yaml
+appbinding.appcatalog.appscode.com/vault created
+```
+
+### Vault Configuration
+
+We will use Vault CLI to configure Vault.
+
+1. Create [Vault policy](https://www.vaultproject.io/docs/concepts/policies.html) which contains a list of `path` along with
+ `capacities`. For more details visit Vault [official doc](https://www.vaultproject.io/docs/concepts/policies.html#creating-policies).
+
+ Create `vault.hcl` file:
+
+```hcl
+ path "sys/mounts" {
+ capabilities = ["read", "list"]
+ }
+ path "sys/mounts/*" {
+ capabilities = ["create", "read", "update", "delete"]
+ }
+ path "sys/leases/revoke/*" {
+ capabilities = ["update"]
+ }
+ path "sys/policy/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+ }
+ path "sys/policy" {
+ capabilities = ["read", "list"]
+ }
+ path "sys/policies" {
+ capabilities = ["read", "list"]
+ }
+ path "sys/policies/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+ }
+ path "auth/kubernetes/role" {
+ capabilities = ["read", "list"]
+ }
+ path "auth/kubernetes/role/*" {
+ capabilities = ["create", "update", "read", "delete", "list"]
+ }
+```
+
+ Create vault policy:
+
+```bash
+$ vault policy write vault-policy examples/guides/vault-server/vault.hcl
+Success! Uploaded policy: vault-policy
+```
+
+ List policies to check:
+
+```bash
+$ vault list sys/policy
+Keys
+----
+default
+root
+vault-policy
+```
+
+2. Enable and configure the Kubernetes auth method (if not already enabled). For more details visit Vault
+ [official doc](https://www.vaultproject.io/docs/auth/kubernetes.html#configuration).
+
+ Enable Kubernetes auth:
+
+```bash
+$ vault auth enable kubernetes
+Success! Enabled kubernetes auth method at: kubernetes/
+```
+
+ Configure Kubernetes auth with `token-reviewer` service account JWT token:
+
+```bash
+$ vault write auth/kubernetes/config \
+ token_reviewer_jwt="eyJhbGciOiJSUzI1N..." \
+ kubernetes_host=https://127.0.0.1:40969\
+ kubernetes_ca_cert=@examples/guides/vault-server/ca.crt
+Success! Data written to: auth/kubernetes/config
+```
+
+ You can find `kubernetes_host` and `kubernetes_ca_cert` in your cluster's `kubeconfig` file.
+
+3. Create an auth method role which includes Vault policies.
+ The KubeVault operator will perform authentication under this role and will have permission
+ mentioned by the policies.
+
+ Create Kubernetes auth method role:
+
+```bash
+$ vault write auth/kubernetes/role/vault-role \
+ bound_service_account_names=vault \
+ bound_service_account_namespaces=demo \
+ policies=vault-policy \
+ ttl=1h
+Success! Data written to: auth/kubernetes/role/vault-role
+```
+
+## Testing
+
+We will create a Vault policy using [VaultPolicy CRD](/docs/v2025.11.21/concepts/policy-crds/vaultpolicy) to check whether our configuration worked or not.
+
+Deploy `secret-policy.yaml`:
+
+```yaml
+apiVersion: policy.kubevault.com/v1alpha1
+kind: VaultPolicy
+metadata:
+ name: custom-policy
+ namespace: demo
+spec:
+ vaultRef:
+ name: vault
+ policyDocument: |
+ path "sys/policy" {
+ capabilities = ["read", "list", "create", "update"]
+ }
+
+ path "sys/policy/*" {
+ capabilities = ["read"]
+ }
+
+```
+
+```bash
+$ kubectl apply -f docs/examples/guides/vault-server/secret-policy.yaml
+vaultpolicy.policy.kubevault.com/secret-admin created
+```
+
+Now you can check from Vault:
+
+```bash
+$ vault list sys/policy
+Keys
+----
+default
+root
+secret-admin
+vault-policy
+```
+
+So, we can see, `secret-admin` policy is already on the list.
+
+Now delete the VaultPolicy crd:
+
+```bash
+$ kubectl delete vaultpolicy secret-admin -n demo
+vaultpolicy.policy.kubevault.com "secret-admin" deleted
+````
+
+Deleting VaultPolicy crd will also delete the policy from Vault.
+
+Updated list:
+
+```bash
+$ vault list sys/policy
+Keys
+----
+default
+root
+vault-policy
+```
diff --git a/content/docs/v2025.11.21/guides/vault-server/overview.md b/content/docs/v2025.11.21/guides/vault-server/overview.md
new file mode 100644
index 000000000..71426d584
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-server/overview.md
@@ -0,0 +1,51 @@
+---
+title: Vault Server Overview
+menu:
+ docs_v2025.11.21:
+ identifier: overview-vault-server
+ name: Overview
+ parent: vault-server-guides
+ weight: 10
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Overview
+
+The KubeVault operator makes it easy to deploy, maintain and manage Vault servers in Kubernetes clusters. It covers automatic initialization and unsealing and also stores unseal keys and root token in a secure way. The KubeVault operator can manage policies and secret engines of Vault servers which are not provisioned by the KubeVault operator. It has the following features:
+
+- **Vault Policy Management**: Provides a Kubernetes native way to manage Vault policies and bind those policies to the users or the auth method roles.
+
+ - [Vault Policy](/docs/v2025.11.21/guides/policy-management/overview#vaultpolicy)
+ - [Vault Policy Binding](/docs/v2025.11.21/guides/policy-management/overview#vaultpolicybinding)
+
+- **Vault Secret Engine Management**: Provides a Kubernetes native way to manage Vault secret engines.
+
+ - [GCP Secret Engine](/docs/v2025.11.21/guides/secret-engines/gcp/overview)
+ - [AWS Secret Engine](/docs/v2025.11.21/guides/secret-engines/aws/overview)
+ - [Azure Secret Engine](/docs/v2025.11.21/guides/secret-engines/azure/overview)
+ - Database Secret Engine
+ - [MongoDB Secret Engine](/docs/v2025.11.21/guides/secret-engines/mongodb/overview)
+ - [MySQL Secret Engine](/docs/v2025.11.21/guides/secret-engines/mysql/overview)
+ - [PostgreSQL Secret Engine](/docs/v2025.11.21/guides/secret-engines/postgres/overview)
+
+## Setup Vault Server
+
+
+
+Deploy Vault server using the KubeVault operator:
+
+- [Deploy Vault Server](/docs/v2025.11.21/guides/vault-server/vault-server)
+- [Enable Vault CLI](/docs/v2025.11.21/guides/vault-server/vault-server#enable-vault-cli)
+
+ Configure external Vault server so that the KubeVault operator can communicate with it:
+
+- [Configure Cluster and External Vault Server](/docs/v2025.11.21/guides/vault-server/external-vault-sever)
diff --git a/content/docs/v2025.11.21/guides/vault-server/vault-server.md b/content/docs/v2025.11.21/guides/vault-server/vault-server.md
new file mode 100644
index 000000000..b64188197
--- /dev/null
+++ b/content/docs/v2025.11.21/guides/vault-server/vault-server.md
@@ -0,0 +1,298 @@
+---
+title: Vault Server
+menu:
+ docs_v2025.11.21:
+ identifier: vault-server
+ name: Vault Server
+ parent: vault-server-guides
+ weight: 20
+menu_name: docs_v2025.11.21
+section_menu_id: guides
+info:
+ cli: v0.23.0
+ installer: v2025.11.21
+ operator: v0.23.0
+ unsealer: v0.23.0
+ version: v2025.11.21
+---
+
+> New to KubeVault? Please start [here](/docs/v2025.11.21/concepts/README).
+
+# Vault Server
+
+You can easily deploy and manage [HashiCorp Vault](https://www.vaultproject.io/) in the Kubernetes cluster using KubeVault operator. In this tutorial, we are going to deploy Vault on the Kubernetes cluster using KubeVault operator.
+
+
+
+## Before you begin
+
+- Install KubeVault operator in your cluster following the steps [here](/docs/v2025.11.21/setup/README).
+
+To keep things isolated, we are going to use a separate namespace called `demo` throughout this tutorial.
+
+```bash
+$ kubectl create ns demo
+namespace/demo created
+```
+
+## Deploy Vault Server
+
+To start with this tutorial, you need to be familiar with the following CRDs:
+
+- [AppBinding](/docs/v2025.11.21/concepts/vault-server-crds/auth-methods/appbinding)
+- [VaultServerVersion](/docs/v2025.11.21/concepts/vault-server-crds/vaultserverversion)
+- [VaultServer](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+
+### Deploy VaultServerVersion
+
+By installing KubeVault operator, you have already deployed some VaultServerVersion crds named after
+the Vault image tag its using. You can list them by using the following command:
+
+```bash
+$ kubectl get vaultserverversions
+NAME VERSION VAULT_IMAGE DEPRECATED AGE
+0.11.5 0.11.5 vault:0.11.5 20h
+1.10.3 1.10.3 vault:1.10.3 20h
+1.11.5 1.11.5 vault:1.11.5 20h
+1.12.1 1.12.1 vault:1.12.1 20h
+1.2.0 1.2.0 vault:1.2.0 20h
+1.2.2 1.2.2 vault:1.2.2 20h
+1.2.3 1.2.3 vault:1.2.3 20h
+1.5.9 1.5.9 vault:1.5.9 20h
+1.6.5 1.6.5 vault:1.6.5 20h
+1.7.2 1.7.2 vault:1.7.2 20h
+1.7.3 1.7.3 vault:1.7.3 20h
+1.8.2 1.8.2 vault:1.8.2 20h
+1.9.2 1.9.2 vault:1.9.2 20h
+```
+
+Now you can use them or deploy your own version by yourself:
+
+```yaml
+apiVersion: catalog.kubevault.com/v1alpha1
+kind: VaultServerVersion
+metadata:
+ name: 1.10.3
+spec:
+ exporter:
+ image: kubevault/vault-exporter:v0.1.1
+ unsealer:
+ image: kubevault/vault-unsealer:v0.8.0
+ vault:
+ image: vault:1.10.3
+ version: 1.10.3
+```
+
+Deploy VaultServerVersion `1.10.3`:
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-server/vaultserverversion.yaml
+vaultserverversion.catalog.kubevault.com/1.10.3 created
+```
+
+### Deploy VaultServer
+
+Once you have deployed VaultServerVersion, you are ready to deploy VaultServer.
+
+```yaml
+apiVersion: kubevault.com/v1alpha2
+kind: VaultServer
+metadata:
+ name: vault
+ namespace: demo
+spec:
+ replicas: 1
+ version: 1.10.3
+ serviceTemplates:
+ - alias: vault
+ metadata:
+ annotations:
+ name: vault
+ spec:
+ type: NodePort
+ backend:
+ inmem: {}
+ unsealer:
+ secretShares: 4
+ secretThreshold: 2
+ mode:
+ kubernetesSecret:
+ secretName: vault-keys
+```
+
+Here we are using `inmem` backend which will lose data when Vault server pods are restarted. For production setup, use an appropriate backend. For more information about supported **backends** and **unsealer options** visit `VaultServer` CRD [documentation](/docs/v2025.11.21/concepts/vault-server-crds/vaultserver)
+
+Deploy `VaultServer`:
+
+```bash
+$ kubectl apply -f https://github.com/kubevault/kubevault/raw/{{< param "info.version" >}}/docs/examples/guides/vault-server/vaultserver.yaml
+vaultserver.kubevault.com/vault created
+```
+
+Check VaultServer status:
+
+```bash
+$ kubectl get vaultserver -n demo
+NAME NODES VERSION STATUS AGE
+vault 1 1.10.3 Processing 47s
+$ kubectl get vaultserver -n demo
+NAME NODES VERSION STATUS AGE
+vault 1 1.10.3 Sealed 54s
+$ kubectl get vaultserver -n demo
+NAME NODES VERSION STATUS AGE
+vault 1 1.10.3 Running 68s
+```
+
+Since the status is `Running` that means you have deployed the Vault server successfully. Now, you are ready to use with this Vault server.
+
+On creation of `VaultServer` object, the KubeVault operator performs the following tasks:
+
+- Creates a `deployment` for Vault named after VaultServer crd
+
+ ```bash
+ $ kubectl get deployment -n demo
+ NAME READY UP-TO-DATE AVAILABLE AGE
+ vault 1/1 1 1 25m
+ ```
+
+- Creates a `service` to communicate with vault pod/pods
+
+ ```bash
+ $ kubectl get services -n demo
+ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+ vault NodePort 10.110.35.39 8200:32580/TCP,8201:30062/TCP 20m
+ ```
+
+- Creates an `AppBinding` that holds connection information for this Vault server.
+
+ ```bash
+ $ kubectl get appbindings -n demo
+ NAME AGE
+ vault 30m
+ ```
+
+- Creates a `ServiceAccount` which will be used by the AppBinding for performing authentication.
+
+ ```bash
+ $ kubectl get sa -n demo
+ NAME SECRETS AGE
+ vault 1 36m
+ ```
+
+- Unseals Vault and stores the Vault root token. For `kubernetesSecret` mode, the operator creates a k8s secret containing root token.
+
+ ```bash
+ $ kubectl get secrets -n demo
+ NAME TYPE DATA AGE
+ vault-keys Opaque 5 42m
+ ```
+
+- Enables `Kubernetes auth method` and creates k8s auth role with Vault policies for the `service account`(here 'vault') on Vault.
+
+## Enable Vault CLI
+
+> Don't have the Vault binary? Download from [here](https://www.vaultproject.io/downloads.html).
+
+If you want to communicate with the Vault servers using [Vault (CLI)](https://www.vaultproject.io/docs/commands/), perform the following commands:
+
+Get your desire Vault server pod name:
+
+```bash
+$ kubectl get pods -n demo -l=app.kubernetes.io/name=vault-operator
+NAME READY STATUS RESTARTS AGE
+vault-8679f4cbf-v78cs 3/3 Running 0 93m
+```
+
+Perform port-forwarding:
+
+```bash
+$ kubectl port-forward -n demo pod/vault-8679f4cbf-v78cs 8200
+Forwarding from 127.0.0.1:8200 -> 8200
+Forwarding from [::1]:8200 -> 8200
+...
+```
+
+Now, you can access the Vault server at `https://localhost:8200`.
+
+Retrieve the Vault server CA certificate from the pod `spec` and save the value from `--vault.ca-cert` to a file named `ca.crt`.
+
+```bash
+$ kubectl get pods vault-8679f4cbf-v78cs -n demo -o jsonpath='{.spec.containers[?(@.name=="vault-unsealer")].args}'
+[run --v=3 --secret-shares=4 --secret-threshold=2 --vault.ca-cert=-----BEGIN CERTIFICATE-----
+MIICuDCCAaCgAwIBAgIBADANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYTAe
+Fw0xOTExMDYwOTM2NDhaFw0yOTExMDMwOTM2NDhaMA0xCzAJBgNVBAMTAmNhMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3OfhIHN4VIidwXkf5RTMRl3J
+I3+szklt6xw2ICX83OLFKk5N2DmVM1zCLcBBwE3b2PBnP3eDGEVadIHj14T+9xdc
+zLjj8WbCjVR824Xn2oDLOIuwso4SFFLD1kgyfmrDw9fs0tzL8bAQqYF/75q2+Pu5
+ERVscb0wXwVTE6sEqNToWqG190aUEuLbLE0n2BwqGdX1xHDhe34YgjXwvssdUJS5
+tTG83iWsAJilyjFBl1Y5gP6hkgi1IB+R6HTyXY1rzKiNn3WVofp1kEeEMAJElC1Z
+q4W087gYrl702MpCDh5OfVq+C4f2lc2BLh0HQ5FU1ksecFyvTo5ohdBaNzs20QID
+AQABoyMwITAOBgNVHQ8BAf8EBAMCAqQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
+9w0BAQsFAAOCAQEAn6YSx7ndvmSU+SH0bFJjnLSGMSOwWtfRAiAnJ8z+0Oea87Rr
+nM+fIR4QTW8bo55Q9+fQztoWvpsb9scwfF6dg92/CsMSiOhVFvJLHHASv0Oh6vC0
+dbC2N6ZGvMQb99ZPjpt5By5w7Gy5eZG2lBwitYW5M9imtxuAlkZyobrnXzNDCrYI
+GDVcajcirb4qI36jjLBE9iYDiUfo3uPcgWO9XnDwRvM09lse2+VRttl7/2fqE7Vh
+3mstGC4e50rgshrxvVBx6NFnTo41OpMnG7GUYCtn4/9/W5M0QDEs6rWENj6g064o
+JfizhesI4ULH4XBLLJ0VN6Wp6QVJ5tEyxSA5MA==
+-----END CERTIFICATE-----
+ --auth.k8s-host= ... ... ...
+```
+
+Get `vault-tls` from the Kubernetes secret and write it on `tls.crt` and `tls.key` respectively:
+
+```bash
+$ kubectl get secrets -n demo vault-vault-tls -o jsonpath="{.data.tls\.crt}" | base64 -d>tls.crt
+
+$ kubectl get secrets -n demo vault-vault-tls -o jsonpath="{.data.tls\.key}" | base64 -d>tls.key
+```
+
+List files to check:
+
+```bash
+$ ls
+ca.crt tls.crt tls.key
+```
+
+Export Vault environment variables:
+
+```bash
+$ export VAULT_ADDR=https://127.0.0.1:8200
+
+$ export VAULT_TOKEN=$(kubectl get secrets -n demo vault-keys -o jsonpath="{.data.vault-root-token}" | base64 --decode; echo)
+
+$ export VAULT_CACERT=ca.crt # put ca.crt file directory
+
+$ export VAULT_CLIENT_CERT=tls.crt # put tls.crt file directory
+
+$ export VAULT_CLIENT_KEY=tls.key # put tls.key file directory
+
+```
+
+Now check whether Vault server can be accessed:
+
+```bash
+$ vault status
+Key Value
+--- -----
+Seal Type shamir
+Initialized true
+Sealed false
+Total Shares 4
+Threshold 2
+Version 1.2.3
+Cluster Name vault-cluster-bb64ffd2
+Cluster ID 94fcaedb-0e10-8600-21f5-97339509c60b
+HA Enabled false
+```
+
+```bash
+$ vault list sys/policy
+Keys
+----
+default
+k8s.-.demo.vault-auth-method-controller
+root
+vault-policy-controller
+```
+
+Vault CLI is ready to use. To learn more about the Vault CLI and its functionality, visit the [official documentation](https://www.vaultproject.io/docs/commands/).
diff --git a/content/docs/v2025.11.21/images/concepts/architecture.svg b/content/docs/v2025.11.21/images/concepts/architecture.svg
new file mode 100644
index 000000000..74622cbea
--- /dev/null
+++ b/content/docs/v2025.11.21/images/concepts/architecture.svg
@@ -0,0 +1,632 @@
+
+