Application hosting is complex and manifold: starting with dedicated programs running on bare metal or virtual severs, to containers on dedicated servers or as a fleet managed by an orchestration software like Kubernetes. Most applications require secrets, access credentials for databases or services, or keys to process encrypted data. From an operations point of view, managing secrets coherently and effectively across on-premise and cloud provider hosted applications is a crucial task.
Hashicorp Vault is a secrets management application. It can be installed in any environment, and then provides configurable API paths for issuing tokens that provide fine-grained access to required secrets.
This article starts a new series about Hashicorp Vault. It provides the essential information’s to start Vault server, configure system access, and store secrets with an internal secrets’ engine. It also covers the essential system components.
The technical context of this article is hashicorp_vault_v.1.20, published 2025-06-25. All provided information and command examples should be valid with newer versions too, baring update to the syntax of CLI commands.
This article originally appeared on my blog admantium.com.
Installing the Hashicorp Vault Binary
Hashicorp Vault is provided as a single binary for several Linux distributions and other platforms. On a Linux computer, you can simply download the appropriate binary file:
curl --output /tmp/vault.zip https://releases.hashicorp.com/vault/1.20.0/vault_1.20.0_linux_amd64.zip unzip /tmp/vault.zip -d /tmp chmod +x /tmp/vault mv /tmp/vault /usr/local/bin Test that the binary is available by running the following command:
> vault --version # Log messages Vault v1.20.0 (6fdd6b59e97d97a9e19b0fb5304bf879c190295e), built 2025-06-23T10:21:30Z Vault Binary: Functional Overview
The vault binary provides CLI access to most functions of a Hashicorp Vault server or cluster, as well as commands specific to secret management. For the scope of this article, only a small part of the commands are required. Here is the overview:
-
server: Starts a server process -
operator: Configure a vault cluster (or single instance) -
secrets: Configure secrets engine -
kv: Direct access to the key-value secrets engine
Starting a Vault Server
Note: For simplifying operating a vault cluster, a development mode can be used. However, this article intents an introduction based on production-grade processes, and therefore explains commands targeting the complete Vault operation lifecycle.
Every vault server instance needs a configuration file with three essential parts: local and cluster instance information, network configuration for its API, and a storage backend. A basic, runnable configuration file as provided in the official Hashicorp Vault tutorial about Set up a Vault dev server is this:
# Source: https://developer.hashicorp.com/vault/tutorials/get-started/setup api_addr = "http://127.0.0.1:8200" cluster_addr = "http://127.0.0.1:8201" cluster_name = "vault" disable_mlock = true ui = true listener "tcp" { address = "127.0.0.1:8200" tls_disable = true } backend "raft" { path = "/etc/hashicorp_vault/raft_storage/" node_id = "node01" } To start a single instance Vault server, run the following command on the target machine:
> vault server -config=./vault_config.hcl # Log messages ==> Vault server configuration: Administrative Namespace: Api Address: http://127.0.0.1:8200 Cgo: disabled Cluster Address: http://127.0.0.1:8201 Environment Variables: ... Go Version: go1.24.4 Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", disable_request_limiter: "false", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled") Log Level: Mlock: supported: false, enabled: false Recovery Mode: false Storage: raft (HA available) Version: Vault v1.20.0, built 2025-06-23T10:21:30Z Version Sha: 6fdd6b59e97d97a9e19b0fb5304bf879c190295e ==> Vault server started! Log data will stream in below: 2025-06-29T11:20:49.816+0200 [INFO] proxy environment: http_proxy="" https_proxy="" no_proxy="" 2025-06-29T11:20:49.965+0200 [INFO] incrementing seal generation: generation=1 2025-06-29T11:20:49.965+0200 [INFO] core: Initializing version history cache for core 2025-06-29T11:20:49.965+0200 [INFO] events: Starting event system 2025-06-29T11:21:00.750+0200 [INFO] core: security barrier not initialized 2025-06-29T11:21:00.750+0200 [INFO] core: security barrier not initialized 2025-06-29T11:21:00.750+0200 [INFO] core: seal configuration missing, not initialized When a Vault server starts, most of its functionality is disabled. In Vault parlance, it is sealed, its secrets can not be accessed. And when a new, single instance is started, it needs to generate the unseal keys.
Unsealing requires to enter a minimum number of all available key shares. To generate 5 keys and require 2 of them for unsealing, run the following command in a new terminal:
export VAULT_ADDR="http://127.0.0.1:8200" vault operator init -key-shares=5 -key-threshold=2 The concrete unseal keys are printed to the terminal - copy and store them.
Unseal Key 1: mDu2BlVT4XmGEKv7mu2aG4b3aRMTuP27dG67bn6QsKG1 Unseal Key 2: OgMEN5ul8tvcxaN1K38lP12sZgR5/Bb1SzGMFNhwYhMP Unseal Key 3: gcFcm94ivGBdMl+R3vptnBe/STTGI2LpWlxhSB1VRkur Unseal Key 4: 85jC/L8aiBLKESltmKf2ZOlg3Dt+hbOp4LitHFQqhtVD Unseal Key 5: rvwIABjZ/U9NBe+gsFjHMuS5my1bjBzaBQKOrmqhEx9P Initial Root Token: hvs.uzEHZBQpWuWKlmeUYx4KY6UZ Then, enter two keys as exemplified in the following:
> vault operator unseal mDu2BlVT4XmGEKv7mu2aG4b3aRMTuP27dG67bn6QsKG1 > vault operator unseal 85jC/L8aiBLKESltmKf2ZOlg3Dt+hbOp4LitHFQqhtVD # Log messages Key Value --- ----- Seal Type shamir Initialized true Sealed false Total Shares 5 Threshold 2 Version 1.20.0 Build Date 2025-06-23T10:21:30Z Storage Type raft Cluster Name vault Cluster ID 476afccd-f98e-e299-829e-8efbe3c482a7 Removed From Cluster false HA Enabled true HA Cluster n/a HA Mode standby Active Node Address <none> Raft Committed Index 32 Raft Applied Index 32 Once completed, the vault UI is shown.
Key-Value Store Secrets Engine
In Hashicorp Vault, a secrets engine is a plugin for writing, reading, and deleting secret data. Each engine has different capabilities and features to store and encrypt data. Several secret engines are supported - the GUI provides a grouped overview:
A built-in secrets engine, available since very early versions of Hashicorp Vault, is key-value, abbreviated as kv. Just as the name implies, this engine allows to store arbitrary key-values pair. The engine is available as a verion1 and version2, where the latter also allow to store versioned secrets.
The following sections provide a compact introduction to initializing and using the kv-v2 secrets engine.
Activation
Before any secret’s engine can be operated, it needs to get activated with the vault secrets top level command. This command itself accepts different sub commands and flags, but to keep this article concise, only the secrets activation will be covered. Execute the following command to active the kv-v2 engine:
vault login vault secrets enable -max-lease-ttl=1h -path=kv2 kv-v2 This command structure is enable [FLAGS] kv-v2, with following meaning for the flags:
-
max-lease-ttl: The access to a secret is governed via tokens, and each token has a defined TTL. The max lease TTL is the maximum amount of time in which a token can be renewed. -
path: All Hashicorp Vault functions are exposed via an API that supports a REST-like interface. All secrets are provided with the/secretssuffix, and the path variable is its sub path. Therefore, the above command exposes the kv-v2 engine at the path/secrets/kv2
Data Manipulation
The vault binary defines the handy vault kv subcommand to interact with the engine. It provides essential subcommands to store, read, and delete data.
To get familiar with the command structure, let’s assume a use-case in which a secret called api-key is stored and retrieved. Furthermore, additional versions of this secret are stored, then an earlier version deleted, and finally a complex value consisting of multiple keys is stored.
To store the api-key secret, execute the following command:
vault kv put -mount=kv2 apps api_key=15baab8378896bf The output of each command shows helpful information about the applied operation.
== Secret Path == kv2/data/apps ======= Metadata ======= Key Value --- ----- created_time 2025-06-30T16:28:56.799416Z custom_metadata <nil> deletion_time n/a destroyed false version 1 Lets save another version of this key:
vault kv put -mount=kv2 apps api_key=b1952df28e97f550 The version increments automatically.
== Secret Path == kv2/data/apps ======= Metadata ======= Key Value --- ----- created_time 2025-06-30T16:29:22.393146Z custom_metadata <nil> deletion_time n/a destroyed false version 2 Now lets read version 1 of this secret again.
vault kv get -mount=kv2 -version=1 apps The essential flag is the aptly named version - just add the desired version as a number.
== Secret Path == kv2/data/apps ======= Metadata ======= Key Value --- ----- created_time 2025-06-30T16:28:56.799416Z custom_metadata <nil> deletion_time n/a destroyed false version 1 ===== Data ===== Key Value --- ----- api_key 15baab8378896bf It is crucial to understand that the apps path can only store a single key-value pair.
When the api_user key is stored ...
vault kv put -mount=kv2 apps api_user=example … it results in three different version of the apps secret.
The complete history of a secret can be revealed with the following command:
vault kv metadata get -mount=kv2 apps It shows that three versions were created:
= Metadata Path = kv2/metadata/apps ========== Metadata ========== Key Value --- ----- cas_required false created_time 2025-06-30T16:28:56.799416Z current_version 3 custom_metadata <nil> delete_version_after 0s max_versions 0 oldest_version 0 updated_time 2025-06-30T16:37:49.305843Z ====== Version 1 ====== Key Value --- ----- created_time 2025-06-30T16:28:56.799416Z deletion_time n/a destroyed false ====== Version 2 ====== Key Value --- ----- created_time 2025-06-30T16:29:22.393146Z deletion_time n/a destroyed false ====== Version 3 ====== Key Value --- ----- created_time 2025-06-30T16:37:49.305843Z deletion_time n/a destroyed false Secrets stay in the version history until the maximum number of versions were stored. With a default value of 10, the very first secret would be erased when the 11 version is stored. Alternatively, a specific version can be deleted with the same named command.
Let’s delete the first version of the apps secret.
vault kv delete -mount=kv2 -versions=1 apps However, this only marks the version for deletion. The actual deletion requires another command:
vault kv destroy -mount=kv2 -versions=1 apps # Log messages ====== Version 1 ====== Key Value --- ----- created_time 2025-06-30T16:28:56.799416Z deletion_time 2025-06-30T16:42:23.336321Z destroyed true Now, if the deleted version is accessed, the command only prints the metadata, not the actual value:
vault kv get -mount=kv2 -version=1 apps # Log messages ======= Metadata ======= Key Value --- ----- created_time 2025-06-30T16:28:56.799416Z custom_metadata <nil> deletion_time 2025-06-30T16:42:23.336321Z destroyed true version 1 Finally, lets store a version of the apps secret which it itself a JSON-formatted string with the two attributes api_user and api_key.
First, the JSON encoded secret needs to be stored in a file, for example at the location /tmp/data.json.
{ "api_user": "example", "api_key": "15baab8378896bf" } Then this JSON data can be attached to the command using the @ signifier and the full file path.
vault kv put kv2/apps value=@/tmp/data.json And to show the resulting config, run the following:
> vault kv get kv2/apps # Log messages ==== Secret Path ==== kv2/data/credentials ======= Metadata ======= Key Value --- ----- created_time 2025-06-30T16:58:21.323787Z custom_metadata <nil> deletion_time n/a destroyed false version 1 ==== Data ==== Key Value --- ----- value { "api_user": "example", "api_key": "15baab8378896bf" } Conclusion
Applications hosted as process or containers, on bare-metal servers or orchestrated via Kubernetes, require secrets such as access credentials or keys for processing encrypted data. Hashicorp Vault is a tool that supports effective and secure secrets management. This introductory article showed how to start a single instance Vault server, beginning with the installation of the binary file, and configuration file. It than showed the base processes of generating unseal keys and unsealing the vault. Finally, a key-value secrets engine was added, data stored and delete, and version information accessed.


Top comments (0)