Getting to know the secrets engine, enabling KV v2, comparing KV v1 and KV v2 from versioning, metadata, soft delete to permanent destroy, as well as the CLI operations bao kv put, get, list, rollback, and destroy.

In episode 2 you understood initialization and unsealing — your OpenBao server is now ready to serve requests. Episode 3 brings you to the feature you will use most often every day: the KV Secrets Engine, the place to store and read static secrets such as application credentials, API keys, and sensitive configuration.
Two KV versions are compared here: KV v1, which is simple with no history, and KV v2, which brings versioning, metadata, soft delete, undelete, and permanent destroy. Most production teams use KV v2 — and after this episode you will understand why.
Before storing a secret, OpenBao needs to know which type of secrets engine to use at a given mount path. A secrets engine is essentially a module that determines how secrets are stored and accessed — KV for static key-value pairs, database for dynamic credentials, transit for encryption, PKI for certificates.
Enabling KV v2 at the secret path takes just one command:
bao secrets enable -path=secret kv-v2
bao secrets listbao secrets enable -path=secret kv-v2 mounts the KV version 2 engine at the secret path. The bao secrets list command then shows the list of enabled engines. Note that the mount path can be anything — secret, myapp, or any other name — as long as you consistently use it when storing and reading data.
The fundamental differences between the two versions:
| Aspect | KV v1 | KV v2 |
|---|---|---|
| Version history | None — old values are lost when overwritten | Every write creates a new version |
| Metadata | None | Timestamps, versions, deletion times are stored |
| Soft delete | None | Values are marked deleted, can be restored |
| Undelete | None | bao kv undelete restores a version |
| Permanent destroy | Overwrites the value | bao kv destroy permanently deletes a version |
| Access path | secret/app | secret/data/app |
| Rollback | None | bao kv rollback restores an old version |
KV v2 is essentially the complete version: versioning gives you an audit trail, soft delete gives you a safety net for mistakes, and destroy gives you full control when data truly must be removed. This is where you see OpenBao's advantage over a plain .env file.
Both KV v1 and v2 use the bao kv put command to write and bao kv get to read:
bao kv put secret/app username="budi" password="super-secret"
bao kv get secret/appThe bao kv get output will show the key-value pairs along with their metadata. One important note: for KV v2, the CLI automatically handles the data path — you just write secret/app, and OpenBao forwards it to secret/data/app.
To see which keys are stored at a path and to delete them:
bao kv list secret/
bao kv delete secret/appbao kv list secret/ shows the list of keys at that path level. bao kv delete on KV v2 performs a soft delete — the latest version is marked deleted, but its history is still stored.
KV v2's main advantage lies in versioning. Every time bao kv put is called on the same path, OpenBao records it as a new version:
bao kv put secret/app username="budi" password="v1-pass"
bao kv put secret/app username="budi" password="v2-pass"
bao kv get -version=1 secret/appVersion 1 stores v1-pass, version 2 stores v2-pass. To see the old value, add -version=1. This is very useful for auditing: you always know when a value changed and what it looked like before.
Each version carries metadata you can inspect:
bao kv metadata get secret/appMetadata shows the available versions, creation time, deletion time, and per-version locks. When a version is soft-deleted, the metadata records it as deleted with a deletion timestamp — but the data for that version can still be restored.
A mistaken deletion is not the end of the story in KV v2. As long as a version has not been destroyed, a soft-deleted version can be restored:
bao kv undelete -versions=2 secret/app
bao kv get secret/appbao kv undelete -versions=2 marks version 2 as active again. Data that seemed gone comes back intact — just like restoring a file from the recycle bin.
Tip
A good habit for teams: before using bao kv destroy, check the metadata first with bao kv metadata get. Soft delete can be restored, permanent destroy cannot. Make sure you are truly certain before permanently deleting.
If the latest version turns out to be wrong — for example, a password overwritten by human error — rollback restores the value from an old version:
bao kv rollback -version=1 secret/app
bao kv get secret/appbao kv rollback -version=1 creates a new version whose contents are identical to version 1, without destroying the history. The audit trail stays complete: you can clearly see that a rollback happened, when, and to which version.
When a secret truly must be eliminated — for example, old values that are no longer used and would be a risk if left behind — use bao kv destroy:
bao kv destroy -versions=1 secret/app
bao kv metadata get secret/appAfter being destroyed, version 1 is permanently removed from storage and cannot be recovered by any means. The metadata will show that the version is no longer available. To delete all data including metadata, use bao kv metadata delete secret/app or delete the entire path with a deeper bao kv delete.
Warning
Clearly distinguish these two commands: bao kv delete is reversible (soft delete, can be undeleted), while bao kv destroy is permanent. Choosing the wrong command in production could mean losing data forever.
In this episode 3, you understood the secrets engine concept and how to enable KV v2, compared the fundamental differences between KV v1 and KV v2, and mastered all the CLI operations from bao kv put, bao kv get, bao kv list, metadata, soft delete and undelete, rollback, to permanent destroy.
Key takeaways:
-version, metadata get, and rollback, secret history is always tracked.data path is only an internal concern — the bao kv CLI handles path mapping automatically.In the next episode, episode 4, we level up from static secrets to the Dynamic Database Secrets Engine — OpenBao creates database users and passwords on-demand, with short lifetimes, automatically revoked when they expire. You will see how the credential paradigm changes completely: from leak-prone static passwords to temporary credentials that never linger on the server. Get your PostgreSQL or MySQL instance ready!