---
layout: docs
page_title: Add a containerized secrets plugin to Vault
description: >-
Add a containerized secrets plugin to your Vault instance.
---
# Add a containerized secrets plugin to Vault
Run your external secrets plugins in containers to increases the isolation
between the plugin and Vault.
## Before you start
- **Your Vault instance must be running on Linux**.
- **Your Vault instance must have local access to the Docker Engine API**.
Vault uses the [Docker SDK](https://pkg.go.dev/github.com/docker/docker) to
manage containerized plugins.
- **You must have [gVisor](https://gvisor.dev/docs/user_guide/install/)
installed**. Vault uses `runsc` as the entrypoint to your container runtime.
- **If you are using a container runtime other than gVisor, you must have a
`runsc`-compatible container runtime installed**.
## Step 1: Install your container engine
Install one of the supported container engines:
- [Docker](https://docs.docker.com/engine/install/)
- [Rootless Docker](https://docs.docker.com/engine/security/rootless/)
## Step 2: Configure your container runtime
Update your container engine to use `runsc` for Unix sockets between the host
and plugin binary.
1. Add `runsc` to your
[Docker daemon configuration](https://docs.docker.com/config/daemon):
```shell-session
$ sudo tee PATH_TO_DOCKER_DAEMON_CONFIG_FILE <
1. Create a configuration directory if it does not exist already:
```shell-session
$ mkdir -p ~/.config/docker
```
1. Add `runsc` to your Docker configuration:
```shell-session
$ tee ~/.config/docker/daemon.json <
## Step 3: Update the HashiCorp `go-plugin` library
You must build your plugin locally with v1.5.0+ of the HashiCorp
[`go-plugin`](https://github.com/hashicorp/go-plugin) library to ensure the
finished binary is compatible with containerization.
Use `go install` to pull the latest version of the plugin library from the
`hashicorp/go-plugin` repo on GitHub:
```shell-session
$ go install github.com/hashicorp/go-plugin@latest
```
If you build with the Vault SDK, you can update `go-plugin` with `go install`
by pulling the latest SDK version from the `hashicorp/vault` repo:
`go install github.com/hashicorp/vault/sdk@latest`
## Step 4: Build the plugin container
Containerized plugins must run as a binary in the finished container and
behave the same whether run in a container or as a standalone application:
1. Build your plugin binary so it runs on Linux.
1. Create a container file for your plugin with the compiled binary as the
entry-point.
1. Build the image with a unique tag.
For example, to build a containerized version of the built-in key-value (KV)
secrets plugin for Docker:
1. Clone the latest version of the KV secrets plugin from
`hashicorp/vault-plugin-secrets-kv`.
```shell-session
$ git clone https://github.com/hashicorp/vault-plugin-secrets-kv.git
```
1. Build the Go binary for Linux.
```shell-session
$ cd vault-plugin-secrets-kv ; CGO_ENABLED=0 GOOS=linux \
go build -o kv cmd/vault-plugin-secrets-kv/main.go
```
1. Create an empty Dockerfile.
```shell-session
$ touch Dockerfile
```
1. Update the empty `Dockerfile` with your infrastructure build details and the
compiled binary as the entry-point.
```Dockerfile
FROM gcr.io/distroless/static-debian12
COPY kv /bin/kv
ENTRYPOINT [ "/bin/kv" ]
```
1. Build the container image and assign an identifiable tag.
```shell-session
$ docker build -t hashicorp/vault-plugin-secrets-kv:mycontainer .
```
## Step 5: Register the plugin
Registering a containerized plugin with Vault is similar to registering any
other external plugin that is available locally to Vault.
1. Store the SHA256 of the plugin image:
```shell-session
$ export SHA256=$(docker images \
--no-trunc \
--format="{{ .ID }}" \
YOUR_PLUGIN_IMAGE_TAG | cut -d: -f2)
```
For example:
```shell-session
$ export SHA256=$(docker images \
--no-trunc \
--format="{{ .ID }}" \
hashicorp/vault-plugin-secrets-kv:mycontainer | cut -d: -f2)
```
1. Register the plugin with `vault plugin register` and specify your plugin
image with the `oci_image` flag:
```shell-session
$ vault plugin register \
-sha256="${SHA256}" \
-oci_image=YOUR_PLUGIN_IMAGE_TAG \
NEW_PLUGIN_TYPE NEW_PLUGIN_ID
```
For example:
```shell-session
$ vault plugin register \
-sha256="${SHA256}" \
-oci_image=hashicorp/vault-plugin-secrets-kv:mycontainer \
secret my-kv-container
```
1. Enable the new plugin for your Vault instance with `vault secrets enable` and
the new plugin ID:
```shell-session
$ vault secrets enable NEW_PLUGIN_ID
```
For example:
```shell-session
$ vault secrets enable my-kv-container
```
You can provide additional information about the image entrypoint, command,
and environment with the `-command`, `-args`, and `-env` flags for
`vault plugin register`.
## Step 6: Test your plugin
Now that the container is registered with Vault, you should be able to interact
with it like any other plugin. Try writing then fetching a new secret with your
new plugin.
1. Use `vault write` to store a secret with your containerized plugin:
```shell-session
$ vault write NEW_PLUGIN_ID/SECRET_PATH SECRET_KEY=SECRET_VALUE
```
For example:
```shell-session
$ vault write my-kv-container/testing subject=containers
Success! Data written to: my-kv-container/testing
```
1. Fetch the secret you just wrote:
```shell-session
$ vault read NEW_PLUGIN_ID/SECRET_PATH
```
For example:
```shell-session
$ vault read my-kv-container/testing
===== Data =====
Key Value
--- -----
subject containers
```
## Use alternative runtimes ((#alt-runtimes))
You can force Vault to use alternative runtimes provided the runtime is
installed locally.
To use an alternative runtime:
1. Register and name the runtime with `vault plugin runtime register`. For
example, to register the default Docker runtime (`runc`) as `docker-rt`:
```shell-session
$ vault plugin runtime register \
-oci_runtime=runc \
-type=container docker-rt
```
1. Use the `--runtime` flag during plugin registration to tell Vault what
runtime to use:
```shell-session
$ vault plugin register \
-runtime=RUNTIME_NAME \
-sha256="${SHA256}" \
-oci_image=YOUR_PLUGIN_IMAGE_TAG \
NEW_PLUGIN_TYPE NEW_PLUGIN_ID
```
For example:
```shell-session
$ vault plugin register \
-runtime=docker-rt \
-sha256="${SHA256}" \
-oci_image=hashicorp/vault-plugin-secrets-kv:mycontainer \
secret my-kv-container
```
## Troubleshooting
### Invalid backend version error
If you run into the following error while registering your plugin:
```plaintext
invalid backend version error: 2 errors occurred:
* error creating container: Error response from daemon: error while looking up the specified runtime path: exec: " /usr/bin/runsc": stat /usr/bin/runsc: no such file or directory
* error creating container: Error response from daemon: error while looking up the specified runtime path: exec: " /usr/bin/runsc": stat /usr/bin/runsc: no such file or directory
```
it means that Vault cannot find the executable for `runsc`. Confirm the
following is true before trying again:
1. You have gVisor installed locally to Vault.
1. The path to `runsc` is correct in you your Docker configuration.
1. Vault has permission to run the `runsc` executable.
If you still get errors when registering a plugin, the recommended workaround is
to use the default Docker runtime (`runc`) as an
[alternative runtime](#alt-runtimes).