Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

By updated

Improve this page

HashiCorp Vault logo

This guide takes you from installing Vault to a first persistent server. You start with dev mode (to learn), then configure a server with Raft storage, initialization and an audit log. Vault is a secrets manager: it stores secrets encrypted and hands them out only to clients that prove who they are.

What you will learn

  • Install Vault from the official package (recommended) or a manual binary
  • Start a dev mode server for tests
  • Configure a first persistent server with Raft
  • Understand Shamir vs auto-unseal
  • Initialize and unseal Vault
  • Enable the audit log for traceability
  • SOCLE anchoring: this guide implements SOCLE-SEC-STO-1 (in French), secrets in a vault encrypted at rest, and SOCLE-SEC-STO-4 (in French), traceability of accesses

Prerequisites

This guide assumes you know the basics of Vault: its architecture, its secrets engines (plugins that store or generate secrets) and its authentication methods (the ways a client proves its identity), covered in the introduction to HashiCorp Vault. On the machine side, you need:

  • Linux (Debian/Ubuntu, RHEL/Fedora, or another distribution)
  • root or sudo access
  • curl and gpg installed, plus wget for the Debian/Ubuntu package route

How do I install Vault on Linux?

Vault can be installed in two ways. Choose only one method: combining the package and a binary dropped into /usr/local/bin leaves two executables on the machine, and the one your shell runs is the one PATH finds first, not necessarily the one systemd starts. The table steers the choice on a single real criterion: who takes charge of the lifecycle (system user, systemd unit, updates), you or the package manager.

MethodAdvantagesDrawbacks
Official packagesystemd service included, simpler updates, user createdDepends on the HashiCorp repository
Manual binaryFull control, no external dependencyManual service configuration

The official HashiCorp package installs:

  • The /usr/bin/vault binary
  • A vault system user
  • A systemd unit (a service definition file) at /usr/lib/systemd/system/vault.service
  • A base configuration at /etc/vault.d/vault.hcl

Debian / Ubuntu

The procedure follows the pattern of a signed APT repository: first fetch the HashiCorp public key, store it in its own keyring (/usr/share/keyrings/), then declare the repository and bind it explicitly to that key with signed-by=. That binding guarantees that another, compromised repository cannot pass itself off as HashiCorp. Never replace this pattern with apt-key add, which is obsolete and removed from recent APT versions.

  1. Add the HashiCorp GPG key

    Terminal window
    sudo apt update && sudo apt install -y gpg
    wget -O- https://apt.releases.hashicorp.com/gpg | \
    sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
  2. Add the repository

    Terminal window
    echo "deb [arch=$(dpkg --print-architecture) \
    signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
    https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
    sudo tee /etc/apt/sources.list.d/hashicorp.list
  3. Install Vault

    Terminal window
    sudo apt update && sudo apt install -y vault
  4. Check the installation

    Terminal window
    vault version
    # Vault v2.0.3 (7193f9a48ff6093ca61b3b627a8671e770428ba6), built 2026-06-17T12:39:45Z
    # Check that the service exists
    systemctl status vault
    # ○ vault.service - "HashiCorp Vault - A tool for managing secrets"
    # Loaded: loaded (/usr/lib/systemd/system/vault.service; disabled)
    # Active: inactive (dead)

    The empty circle and the inactive (dead) are normal: the package installs the service but does not start it, and does not enable it at boot. This is deliberate, because the default configuration is not the one you want. Starting the service comes later in this guide, once /etc/vault.d/vault.hcl is written.

RHEL / Rocky / Fedora

The principle is the same, but HashiCorp publishes two distinct repositories, and picking the wrong one installs packages that do not match your distribution. Distributions of the RHEL family (RHEL, Rocky, AlmaLinux, CentOS Stream) use the /RHEL/ path, Fedora uses /fedora/. If dnf config-manager reports an unknown command, install dnf-plugins-core first.

Terminal window
# RHEL, Rocky, AlmaLinux, CentOS Stream
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# Fedora: dedicated repository
# sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
# Install Vault
sudo dnf install -y vault
# Check
vault version

What is Vault dev mode, and when should I use it?

Dev mode is built for learning and local tests. It starts a complete Vault server in a few seconds, with no configuration.

What dev mode does

Dev mode is not a stripped-down Vault, it is the complete server with configuration shortcuts. Read the right-hand column as the list of disabled protections: in-memory storage, plain HTTP, automatic unsealing and a displayed root token. Each of these lines is exactly what you will spend the rest of the guide setting up properly. Two terms appear here. A root token is the all-powerful credential Vault issues at initialization. A mount is a location, called a path such as secret/, where a secrets engine is attached; clients address secrets by path.

CharacteristicValue
StorageMemory (lost on restart)
ProtocolHTTP (not encrypted)
Initial stateAlready initialized and unsealed
Secrets engineKV v2 enabled on secret/
Root tokenDisplayed at startup

How do I start the dev server?

In a first terminal:

Terminal window
vault server -dev -dev-root-token-id="root"

The -dev-root-token-id option sets a predictable root token to simplify tests. You will see:

==> Vault server configuration:
Api Address: http://127.0.0.1:8200
...
Root Token: root
Development mode should NOT be used in production installations!

How do I configure the client?

The server stays in the foreground in its terminal, so do not close it. Open a second terminal: the vault CLI reads two environment variables there, VAULT_ADDR to know whom to contact and VAULT_TOKEN to authenticate. In dev mode only, this token is the one you imposed at startup.

Terminal window
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='root'
vault status

Expected output:

Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
...
Storage Type inmem

Initialized: true and Sealed: false: you can use Vault.

Initialized says that Vault has already generated its encryption keys; Sealed says whether it is locked: a sealed Vault can neither read nor write a secret. Dev mode performs both operations for you. On a persistent server, you will do them yourself, later in this guide.

How do I run a first quick test?

These two commands write then read back a secret in the KV v2 engine (a key-value store that keeps versions of each secret), mounted automatically on secret/ by dev mode. Look at the output of put: Vault answers with a path secret/data/test, not secret/test. That data/ segment is a particularity of KV v2, which stores values under data/ and their metadata under metadata/. You will meet it again when writing your policies (the rules that say which paths a token may access), where you must use the full path.

Terminal window
vault kv put secret/test message="Hello Vault!"
vault kv get secret/test

If the read returns your message, the installation works. The rest of the guide repeats the same mechanics on a persistent server.

How do I set up a first persistent Vault server?

This section configures a single-node Vault server with Raft storage. It suits:

  • An advanced lab or a mock-up
  • A shared development environment
  • A small infrastructure that tolerates a temporary outage

Target architecture

The diagram shows what you are about to assemble: a single Vault process, its built-in Raft storage sitting on the local disk, and a TLS listener in front. Raft deserves a word, because its name can mislead on a single server: it is a storage engine in its own right, which needs no external database, and which can later welcome other nodes without changing the storage configuration.

A single-node Vault server has a TCP listener over HTTPS on port 8200, Raft storage for persistent data and an audit file that logs accesses.Vault Server (single node)TCP listener(HTTPS port 8200)Raft storage(persistent data)Audit file(access logging)
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

The configuration file

The configuration file is written in HCL (HashiCorp Configuration Language) and its structure is the same whatever the installation method; only its location changes. Four blocks are enough here: storage, listener, advertised addresses and log level. The point most often overlooked is api_addr: it is the address Vault returns to clients and to other nodes, so it must be reachable from the network, not only from the server. The name vault.example.com used below is an example name: replace it with the real name of the machine, or, for a lab without DNS, declare it in /etc/hosts.

Edit /etc/vault.d/vault.hcl:

# Web user interface
ui = true
# Storage with Raft (built-in)
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-1"
}
# HTTPS listener
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/tls.crt"
tls_key_file = "/opt/vault/tls/tls.key"
}
# Addresses for the API and the cluster
api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"
# Log level
log_level = "info"

Unlike the binary installation, you have no directory to create: the package already sets up /opt/vault/data and /opt/vault/tls, both owned by the vault user, the second with mode 0700. Check what you received instead:

Terminal window
sudo ls -la /opt/vault/
# drwxr-xr-x. 4 vault vault 29 ... .
# drwxr-xr-x. 2 vault vault 6 ... data
# drwx------. 2 vault vault 36 ... tls

Two points about this default configuration. The package writes an /etc/vault.d/vault.hcl that uses storage "file", not raft: the block above replaces it. And the /opt/vault/logs directory, needed if you enable the file audit log, is not created: you have to create it.

What is mlock, and do I need to disable it?

By default, Vault uses mlock (a system call that pins memory in RAM) to prevent secrets from being written to swap, the disk area the system uses when RAM is full, where they would persist unencrypted. It is an important protection in production.

EnvironmentRecommendation
Lab / devdisable_mlock = true is acceptable to simplify
ProductionKeep mlock active + disable swap + systemd capabilities

If you installed Vault from the package, you have nothing to do: its systemd unit already grants AmbientCapabilities=CAP_IPC_LOCK and sets LimitMEMLOCK=infinity. The service journal confirms it at startup:

Mlock: supported: true, enabled: true

The problem therefore only arises with an installation from the binary, where you write the unit yourself, or when running in the foreground. Faced with a mlock: operation not permitted:

Option 1 (recommended): add the capabilities in systemd, as the package unit does, with AmbientCapabilities=CAP_IPC_LOCK

Option 2 (lab only): add disable_mlock = true in the configuration

How do I set up TLS certificates?

Vault must use HTTPS, even for a lab. If you installed the package, the self-signed certificate tls.crt and its key tls.key already exist in /opt/vault/tls/: skip the command below, and read tls.crt wherever the rest of this guide writes vault.crt. If you installed the binary, create a self-signed certificate for a first test:

Terminal window
# Self-signed certificate (lab only)
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /opt/vault/tls/vault.key \
-out /opt/vault/tls/vault.crt \
-subj "/CN=vault.example.com"
sudo chown vault:vault /opt/vault/tls/*
sudo chmod 600 /opt/vault/tls/vault.key

How do I start the server?

If the dev server is still running in a terminal, stop it first with Ctrl+C: it already holds port 8200, which the new listener needs. enable registers the service at machine boot, start launches it immediately. The third call is not decorative: with Type=notify, a service that shows active (running) has really finished initializing. If you see activating then a failure, the cause is almost always in the HCL configuration or the permissions of the data directory, and journalctl -u vault -n 50 will give you the exact line.

Terminal window
sudo systemctl enable vault
sudo systemctl start vault
sudo systemctl status vault

How do I check the status?

The vault client does not guess where to reach the server: without VAULT_ADDR, it tries https://127.0.0.1:8200 and fails as soon as the listener is somewhere else. So export the address, then say how to validate the certificate. These two variables belong to your shell; remember to put them back in your profile or in an environment file if you administer the server regularly.

Terminal window
export VAULT_ADDR='https://vault.example.com:8200'
# With a self-signed certificate (lab only!)
export VAULT_CACERT=/opt/vault/tls/vault.crt
# OR (less secure)
export VAULT_SKIP_VERIFY=1
vault status

Expected output (server not initialized):

Key Value
--- -----
Seal Type shamir
Initialized false
Sealed true
...

Shamir vs auto-unseal: which should I choose?

Before initializing Vault, understand the two unlocking mechanisms. Vault always starts sealed: its data is encrypted with a key that it does not hold in clear text. To unseal it is to give it back the means to decrypt that key. Two ways exist: key shares held by people (Shamir), or delegation to an external service (auto-unseal).

Shamir (default)

Vault uses the Shamir's Secret Sharing algorithm to split the master key into several parts (shares). You define:

  • key-shares: total number of parts (e.g. 5)
  • key-threshold: minimum number needed to unseal (e.g. 3)

Advantages:

  • No external dependency
  • Multi-person governance (several key holders)
  • Good for understanding the mechanism

Drawbacks:

  • Human intervention at every restart
  • Complicates automation (CI/CD, auto-scaling)
  • Risk of unavailability if the holders are absent

Vault delegates decryption to a trusted external service:

MethodProviderPrerequisites
AWS KMSAmazon Web ServicesKMS key + IAM role
Azure Key VaultMicrosoft AzureKey Vault + managed identity
GCP Cloud KMSGoogle CloudKMS key + service account
TransitAnother VaultDedicated Vault cluster
HSMPKCS#11Hardware Security Module

Advantages:

  • Automatic unsealing on restart
  • Compatible with automation (Kubernetes, auto-scaling)
  • Better operational experience

Drawbacks:

  • Dependency on an external service
  • Cost of the KMS/HSM service
  • More complex initial configuration

This guide uses Shamir

For this first deployment, we use Shamir because it needs no external infrastructure. Once you are familiar with Vault, set up auto-unseal for your operational environments.

How do I initialize Vault?

Initialization is a one-time operation that generates the master key and the unseal keys.

For a lab (1 key)

On a workstation, splitting the master key into several parts brings nothing: you already hold everything. A single share with a threshold of one shortens every restart to a single unseal command. Still, write down the key and the root token: persistent mode, unlike dev mode, will never display them again.

Terminal window
vault operator init -key-shares=1 -key-threshold=1

For a shared environment (3 of 5)

The 5 shares / threshold 3 pair, the default of vault operator init, balances two opposite risks. A threshold that is too low lets a single person reopen the vault; a threshold equal to the number of shares makes unsealing impossible as soon as one holder is absent or loses their key. With 3 of 5, it takes the collusion of three people to open it, and two keys of margin remain in case of loss.

Terminal window
vault operator init -key-shares=5 -key-threshold=3

Output:

Unseal Key 1: lWF1ue8BgtW3/19Uf49GaAicvaebxtFWlDFvEIKvs3s=
Unseal Key 2: ...
Unseal Key 3: ...
Unseal Key 4: ...
Unseal Key 5: ...
Initial Root Token: hvs.FkLQnkIPosIar9SSeDfdsFEb
Vault initialized with 5 key shares and a key threshold of 3.

How do I unseal Vault?

After every restart, Vault starts sealed. You must unseal it with the Shamir keys.

Why this mechanism?

When Vault is sealed, the data is encrypted and inaccessible. Even if an attacker steals the server or reaches the storage, they cannot read anything without the unseal keys.

The procedure

Unsealing is cumulative and stateless on the client side: each call submits one share, and Vault only reconstructs the master key once the threshold is reached. The holders can therefore each enter their share from their own workstation; there is no need to gather the keys in one place. Repeat the command as many times as the threshold requires:

Terminal window
vault operator unseal <unseal_key_1>
vault operator unseal <unseal_key_2>
vault operator unseal <unseal_key_3>

After each key, Vault shows the progress:

Unseal Progress 2/3

Once the threshold is reached:

Sealed false <-- Unsealed!

How do I log in after unsealing?

Unsealing is not logging in. An unsealed Vault still refuses every read until the client presents a token (the credential Vault checks on each request; it carries a TTL, a time-to-live after which it expires). Use the root token only for this initial setup: its first task should be to create an authentication method and policies, then revoke itself with vault token revoke -self. An authentication method is a way for clients to prove their identity and receive a token in return. If you come from dev mode, first remove the test token from your shell: an environment variable wins over the token that vault login stores.

Terminal window
unset VAULT_TOKEN
vault login <root_token>

How do I enable the Vault audit log?

The audit log is essential for traceability. It records every operation on Vault: who read which secret, when, from which IP.

Enable the file audit device

One behavior to know before enabling auditing: if all the configured audit devices become unreachable (full disk, broken permissions), Vault stops answering requests rather than process an operation without logging it. It is a deliberate choice, but it turns a saturated disk into a complete outage. HashiCorp, by the way, recommends enabling at least two devices in production to avoid this failure. Watch the disk space of the log directory as you watch the service.

Terminal window
# Create the directory (already done with the binary installation)
sudo mkdir -p /opt/vault/logs
sudo chown vault:vault /opt/vault/logs
# Enable the audit device
vault audit enable file file_path=/opt/vault/logs/vault-audit.log

Check that auditing works:

Terminal window
vault audit list
Path Type Description
---- ---- -----------
file/ file n/a

How do I test the audit log?

Create a secret and check that the operation is logged. Unlike dev mode, a persistent server mounts no KV engine on its own: the first command enables one on secret/.

Terminal window
vault secrets enable -path=secret kv-v2
vault kv put secret/test foo=bar
# Check the log
sudo tail -1 /opt/vault/logs/vault-audit.log | jq .

You will see a JSON entry with the operation, the user, the date, and so on.

How do I rotate the audit logs?

The audit log grows fast, one JSON line per API request, and it is precisely the file you must not let saturate the partition. The configuration below keeps 30 days and compresses the archives. delaycompress avoids compressing the file Vault has just closed, and the postrotate sends a SIGHUP so that the process reopens its file descriptor; otherwise it would keep writing into the renamed file. Create /etc/logrotate.d/vault:

/etc/logrotate.d/vault
/opt/vault/logs/*.log {
daily
rotate 30
compress
delaycompress
notifempty
missingok
su vault vault
postrotate
/bin/systemctl reload vault.service
endscript
}

How do I check file permissions at startup?

For a stricter deployment, Vault can check the permissions of its configuration files at startup, which catches a key or a config file readable by other users:

Terminal window
# In the service environment file
# or before starting Vault
export VAULT_ENABLE_FILE_PERMISSIONS_CHECK=true

This produces warnings if the configuration files are readable by other users.

Troubleshooting

Two reflexes before working through this table. First, check that the client targets the right address: echo $VAULT_ADDR alone explains a good half of the connection refused errors. Second, read journalctl -u vault -n 50, where HCL configuration errors appear in clear text with the faulty line number. The table handles the remaining cases, those where the service runs but refuses to answer.

SymptomLikely causeSolution
connection refusedVault is not startedsystemctl start vault
Vault is sealedVault is not unsealedvault operator unseal
permission deniedInvalid or expired tokenvault login with the right token
certificate signed by unknown authoritySelf-signed certificate not trustedexport VAULT_CACERT=/path/to/ca.crt
mlock: operation not permittedMissing capabilitiesCheck AmbientCapabilities in systemd
Listener config not foundHCL syntax errorRead journalctl -u vault -n 50 and fix the indicated line

What this guide does not cover

This guide gives you a working base, but a real production deployment needs additional steps, from high availability to backups. The table lists them, with the reason each one matters.

TopicWhy it matters
High availability (3+ nodes)Fault tolerance, no service interruption
Auto-unseal (KMS/HSM)Automatic restart with no human intervention
Raft backups / snapshotsRecovery after an incident
Monitoring / telemetryDetect problems before they become critical
Load balancingLoad distribution and a single entry point
Certificates signed by a real CAEnd-to-end TLS without VAULT_SKIP_VERIFY
Recovery proceduresWhat to do if you lose unseal keys
Root token lifecycleThe initial root token must not stay active
Namespaces (Enterprise)Multi-tenant isolation
Replication (Enterprise)DR and multi-region performance

On the SOCLE side, installing the vault proves nothing about the lifecycle of the secrets it holds. The whole rotation family stays open after this guide: the renewal policy by criticality and the TTLs (SOCLE-SEC-ROT-1, in French), the emergency revocation test (SOCLE-SEC-ROT-3, in French) and leak detection (SOCLE-SEC-ROT-4, in French) are built with policies and dynamic secrets, not with installation. For day-to-day operations, the guide Auto-unseal and Recovery Keys covers sealing, and Operating Vault in production covers the HA cluster, backup and monitoring. Infrastructure certificates come with the PKI guide (in French).

Key points

  1. Two installation methods: package (recommended) or manual binary
  2. Always verify the checksums and signatures of downloaded binaries
  3. Dev mode: for learning only, never outside a local lab
  4. Shamir vs auto-unseal: Shamir to understand, auto-unseal to operate
  5. mlock: keep it active in production, disable swap
  6. Audit: enable it explicitly from the first deployment
  7. Certificates: self-signed for the lab, a real CA for production
  8. This guide is a starting point, not a complete production recipe
  9. Evidence expected by SOCLE: the initialized, unsealed Raft server proves SOCLE-SEC-STO-1 (in French), secrets in a vault encrypted at rest; the audit file proves SOCLE-SEC-STO-4 (in French), accesses traced; the seal plus audit pair covers the verifiable part here of SOCLE-SEC-STO-5 (in French), the separation of roles remaining to be built with policies

Knowledge check

Check that the essentials of this lesson are in place. The questions only cover what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

3 questions
3 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn