For development and debugging integrations, you can run Stronghold locally in Docker. Use such an instance for development only: do not store real secrets in it.
Building the image
The image is built from the Stronghold binary with stronghold bootstrap docker:
stronghold bootstrap docker
docker load -i stronghold-v1.19.0.tarBy default, the image is tagged stronghold:<VERSION>, where <VERSION> is the Stronghold version, for example stronghold:1.19.0.
Development mode
The default container command is stronghold server -dev. In development mode, Stronghold:
- keeps data in memory — everything is lost when the container stops;
- initializes and unseals automatically;
- prints the root token to the log;
- runs without TLS.
Start the container. By default, development mode listens only on 127.0.0.1 inside the container, so the published port would not be reachable. Set the listen address explicitly:
docker run --rm --name stronghold-dev -p 8200:8200 stronghold:1.19.0 stronghold server -dev -dev-listen-address=0.0.0.0:8200Find the root token in the container log (the Root Token line) and configure the client:
export STRONGHOLD_ADDR=http://127.0.0.1:8200
export STRONGHOLD_TOKEN=<ROOT_TOKEN>
d8 stronghold statusReplace <ROOT_TOKEN> with the root token from the container log.
For Vault client libraries, set the same values in VAULT_ADDR and VAULT_TOKEN. For details, see Application clients.
To set a predictable root token, add the -dev-root-token-id parameter:
docker run --rm --name stronghold-dev -p 8200:8200 stronghold:1.19.0 stronghold server -dev -dev-root-token-id=root -dev-listen-address=0.0.0.0:8200Single-node Raft configuration in Docker Compose
If data must persist across restarts, run Stronghold with a configuration file and Raft storage.
Create
config/stronghold.hcl(the format is described in Configuration):ui = true disable_mlock = true api_addr = "http://127.0.0.1:8200" cluster_addr = "http://127.0.0.1:8201" storage "raft" { path = "/stronghold/data" node_id = "dev-node-1" } listener "tcp" { address = "0.0.0.0:8200" tls_disable = true }tls_disable = trueis acceptable only on a local developer machine.Create
compose.yaml:services: stronghold: image: stronghold:1.19.0 command: ["stronghold", "server", "-config=/stronghold/config/stronghold.hcl"] ports: - "8200:8200" volumes: - ./config:/stronghold/config:ro - stronghold-data:/stronghold/data restart: unless-stopped volumes: stronghold-data:The image runs as root (no user is set in the image), so no additional permissions on the
/stronghold/datavolume are needed. The image has no ENTRYPOINT: the full command is passed, as in the example.Start the container:
docker compose up -dInitialize and unseal Stronghold. For local development, a single key is enough:
export STRONGHOLD_ADDR=http://127.0.0.1:8200 d8 stronghold operator init -key-shares=1 -key-threshold=1 d8 stronghold operator unsealSave the unseal key and root token from the
operator initoutput. After each container restart, rund8 stronghold operator unseal.Log in with the root token and enable the engines you need, for example KV version 2:
export STRONGHOLD_TOKEN=<ROOT_TOKEN> d8 stronghold secrets enable -path=secret -version=2 kv d8 stronghold kv put -mount=secret myapp/db username=app password=S3cr3tReplace
<ROOT_TOKEN>with the root token from theoperator initoutput.
The web UI is available at http://127.0.0.1:8200/ui.
Running an application next to Stronghold
An application in the same compose.yaml reaches Stronghold by service name. Add the app service to the services section of the compose.yaml file from the previous section:
services:
app:
image: registry.example.com/myapp:1.0.0
environment:
VAULT_ADDR: http://stronghold:8200
VAULT_TOKEN: <ROOT_TOKEN>
depends_on:
- strongholdReplace <ROOT_TOKEN> with the root token from the operator init output. Stronghold with Raft storage does not create a root token with a predefined value, as -dev-root-token-id does in development mode.
A token in an environment variable is acceptable only for local development. In real environments, use the auth methods described in Delivering secrets to Kubernetes pods and Application clients.