This lab reproduces on video the guide how to install OpenBao with Docker and Raft storage: the same openbao/openbao:2.6.2 image, the same configuration and the same commands, really executed in a throwaway container. If you want to run OpenBao in Docker to hold your services’ credentials, here you see every real output, from the first sealed bao status to the Raft snapshot.
What OpenBao is and why Raft
OpenBao is the fork of HashiCorp Vault that keeps the MPL 2.0 licence and Vault’s API, so the concepts in the article on HashiCorp Vault for secrets management apply the same way. Raft storage is built into the binary: it writes the encrypted data to a directory and needs no external database. The Raft backend documentation requires cluster_addr even on a single node.
Who owns the data volume
The image runs as the unprivileged openbao user, and Docker only copies that owner into a new volume when the path already exists in the image. That is why the volume goes at /openbao/file: at /openbao/data the directory stays owned by root and the lab shows the Permission denied. How a volume gets initialised is covered in the Docker volumes documentation and in the lab on how data persists in Docker.
Initialising and unsealing without showing the keys
bao operator init generates 5 unseal keys and the root token, and the lab writes them with jq to files with mode 600 so they are never printed. It then unseals with 3 of them. In the lab the keys go in as arguments because there is no keyboard; on your server run bao operator unseal with no argument, which prompts for the hidden key and keeps it out of the history. The full reference is in the bao operator init documentation.
What differs from the guide
The lab’s compose.yaml leaves out mem_limit and memswap_limit: the nested container it is recorded in does not delegate the cgroup v2 memory controller, and Docker rejects any memory limit. On your server keep both lines with the same value, as the guide explains, so the container’s swap stays at 0 and secrets never land on disk. The root token is not revoked here either, because the container is destroyed at the end.
For the other ways to handle secrets in containers there is the lab on managing secrets in Docker, and to ship snapshots off the server, the guide to restic for encrypted backups. The image and its tags are at openbao/openbao on Docker Hub, and the code in the OpenBao repository.
FAQ
Why does OpenBao start sealed after every restart?
Because with Shamir unsealing the key that decrypts the data is never stored on disk: it is rebuilt in memory from 3 of the 5 unseal keys. Until then bao status shows Sealed true and Unseal Progress 0/3, as in the lab, and the secrets stay encrypted.
Where do I mount OpenBao's Raft volume in Docker?
At /openbao/file. The image runs as the openbao user and Docker only copies that owner into a new volume when the path already exists in the image. On a path such as /openbao/data the directory stays owned by root and writing fails with Permission denied, as the lab shows.
Does a Raft snapshot store the secrets in clear text?
No. The file is a tar.gz with meta.json, state.bin, SHA256SUMS and SHA256SUMS.sealed, and state.bin keeps the data encrypted with OpenBao's key. That is why it only restores with the original unseal keys, which must be kept somewhere other than the snapshot.
Why does the first kv put fail right after enabling KV v2?
When you enable kv-v2, OpenBao prepares the versioned storage and for a moment answers Upgrading from non-versioned to versioned data. The guide hit it on one of its installs: wait a second and run the command again. The lab handles it with a loop of up to 10 attempts.