# Your first secret

If you successfully completed the steps in Starting the Server, you started the dev server and exported the `VAULT_TOKEN` to the initial root token value so that `vault login` is not required to authenticate. If you have not yet completed those steps, please review that tutorial and do so before proceeding here.

Now that the dev server is up and running, let's get straight to it and read and write your first secret.

### Key/Value secrets engine <a href="#key-value-secrets-engine" id="key-value-secrets-engine"></a>

When running Vault in **dev** mode, Key/Value v2 secrets engine is enabled at `secret/` path. Key/Value secrets engine is a generic key-value store used to store arbitrary secrets within the configured physical storage for Vault. Secrets written to Vault are encrypted and then written to backend storage. Therefore, the backend storage mechanism *never* sees the unencrypted value and doesn't have the means necessary to decrypt it without Vault.

Key/Value secrets engine has **version 1** and **2**. The difference is that v2 provides versioning of secrets and v1 does not.

Use the `vault kv <subcommand> [options] [args]` command to interact with K/V secrets engine.

**Available subcommands:**

<table><thead><tr><th width="184">Subcommand</th><th width="72" align="center">kv v1</th><th width="73" align="center">kv v2</th><th>Description</th></tr></thead><tbody><tr><td>delete</td><td align="center">x</td><td align="center">x</td><td>Delete versions of secrets stored in K/V</td></tr><tr><td>destroy</td><td align="center"></td><td align="center">x</td><td>Permanently remove one or more versions of secrets</td></tr><tr><td>enable-versioning</td><td align="center"></td><td align="center">x</td><td>Turns on versioning for an existing K/V v1 store</td></tr><tr><td>get</td><td align="center">x</td><td align="center">x</td><td>Retrieve data</td></tr><tr><td>list</td><td align="center">x</td><td align="center">x</td><td>List data or secrets</td></tr><tr><td>metadata</td><td align="center"></td><td align="center">x</td><td>Interact with Vault's Key-Value storage</td></tr><tr><td>patch</td><td align="center"></td><td align="center">x</td><td>Update secrets <strong>without</strong> overwriting existing secrets</td></tr><tr><td>put</td><td align="center">x</td><td align="center">x</td><td>Sets or update secrets (this <strong>replaces</strong> existing secrets)</td></tr><tr><td>rollback</td><td align="center"></td><td align="center">x</td><td>Rolls back to a previous version of secrets</td></tr><tr><td>undelete</td><td align="center"></td><td align="center">x</td><td>Restore the deleted version of secrets</td></tr></tbody></table>

To learn more about Key/Value v1 secrets engine, go through the Static Secrets: Key/Value Secrets Engine tutorial.

### Get command help <a href="#get-command-help" id="get-command-help"></a>

You can interact with key/value secrets engine using the `vault kv` command. Get the command help.

```shell-session
$ vault kv -help 

Usage: vault kv <subcommand> [options] [args]

  This command has subcommands for interacting with Vault's key-value
  store. Here are some simple examples, and more detailed examples are
  available in the subcommands or the documentation.

  Create or update the key named "foo" in the "secret" mount with the value
  "bar=baz":

      $ vault kv put -mount=secret foo bar=baz

  Read this value back:

      $ vault kv get -mount=secret foo

  Get metadata for the key:

      $ vault kv metadata get -mount=secret foo

  Get a specific version of the key:

      $ vault kv get -mount=secret -version=1 foo

  The deprecated path-like syntax can also be used, but this should be avoided
  for KV v2, as the fact that it is not actually the full API path to
  the secret (secret/data/foo) can cause confusion:

      $ vault kv get secret/foo

  Please see the individual subcommand help for detailed usage information.

Subcommands:
    delete               Deletes versions in the KV store
    destroy              Permanently removes one or more versions in the KV store
    enable-versioning    Turns on versioning for a KV store
    get                  Retrieves data from the KV store
    list                 List data or secrets
    metadata             Interact with Vault's Key-Value storage
    patch                Sets or updates data in the KV store without overwriting
    put                  Sets or updates data in the KV store
    rollback             Rolls back to a previous version of data
    undelete             Undeletes versions in the KV store
```

### Write a secret <a href="#write-a-secret" id="write-a-secret"></a>

Before you begin, check the command help.

```shell-session
$ vault kv put -help
```

The help provides command examples along with optional parameters that you can use.

Now, write a key-value secret to the path `hello` , with a key of `foo` and value of `world`, using the `vault kv put` command against the mount path `secret`, which is where the KV v2 secrets engine is mounted. This command creates a new version of the secrets and replaces any pre-existing data at the path if any.

```shell-session
$ vault kv put -mount=secret hello foo=world

== Secret Path ==
secret/data/hello

======= Metadata =======
Key                Value
---                -----
created_time       2023-11-12T19:36:54.389113Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            1
```

You will learn about paths in more detail later, but for now, it is important that the mount path to the KV v2 secrets engine is provided with `-mount=secret`, otherwise, this example won't work. The `secret` mount path (which was automatically set up for you when you started your Vault server in `-dev` mode) is where arbitrary secrets can be read and written.

A `flag provided but not defined: -mount` error means you are using an older version of Vault from before this syntax was introduced. Upgrade to at least Vault 1.11, or use the old syntax (`secret/hello` instead of `-mount=secret hello`) for any commands in this guide.

With `kv put` you can even write multiple pieces of data.

```shell-session
$ vault kv put -mount=secret hello foo=world excited=yes

== Secret Path ==
secret/data/hello

======= Metadata =======
Key                Value
---                -----
created_time       2023-11-12T19:49:06.761365Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            2
```

Notice that the `version` is now `2`.

{% hint style="warning" %}
The examples in this tutorial use the `<key>=<value>` input to send secrets to Vault. However, sending data as a part of the CLI command often ends up in the shell history unencrypted. To avoid this, refer to the Static Secrets: Key/Value Secrets Engine tutorial to learn different approaches.
{% endhint %}

### Read a secret <a href="#read-a-secret" id="read-a-secret"></a>

As you might expect, secrets can be retrieved with `vault kv get`.

```shell-session
$ vault kv get -mount=secret hello

== Secret Path ==
secret/data/hello

======= Metadata =======
Key                Value
---                -----
created_time       2023-11-12T01:40:09.888293Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            2

===== Data =====
Key        Value
---        -----
excited    yes
foo        world
```

Vault returns the latest version (in this case version `2`) of the secrets at `secret/hello`.

To print only the value of a given field, use the `-field=<key_name>` flag.

```shell-session
$ vault kv get -mount=secret -field=excited hello

yes
```

Optional JSON output is very useful for scripts. For example, you can use the `jq` tool to extract the value of the `excited` secret.

```shell-session
$ vault kv get -mount=secret -format=json hello | jq -r .data.data.excited

yes
```

### Delete a secret <a href="#delete-a-secret" id="delete-a-secret"></a>

Now that you've learned how to read and write a secret, let's go ahead and delete it. You can do so using the `vault kv delete` command.

```shell-session
$ vault kv delete -mount=secret hello

Success! Data deleted (if it existed) at: secret/data/hello
```

Try to read the secret you just deleted.

```shell-session
$ vault kv get -mount=secret hello

== Secret Path ==
secret/data/hello

======= Metadata =======
Key                Value
---                -----
created_time       2023-11-12T01:40:09.888293Z
custom_metadata    <nil>
deletion_time      2023-11-12T01:40:41.786995Z
destroyed          false
version            2
```

The output only displays the metadata with `deletion_time`. It does not display the data itself once it is deleted. Notice that the `destroyed` parameter is `false` which means that you can recover the deleted data if the deletion was unintentional.

```shell-session
$ vault kv undelete -mount=secret -versions=2 hello

Success! Data written to: secret/undelete/hello
```

Now, the data is recovered.

```shell-session
$ vault kv get -mount=secret hello

======= Metadata =======
Key                Value
---                -----
created_time       2023-11-12T01:40:09.888293Z
custom_metadata    <nil>
deletion_time      n/a
destroyed          false
version            2

===== Data =====
Key        Value
---        -----
excited    yes
foo        world
```

{% hint style="info" %}
This quick start tutorial only touches the surface of the key/value v2 secrets engine capabilities. To learn more, go through the Versioned Key/Value Secrets Engine tutorial which will walk you through the key/value v2 secrets engine in greater depth.
{% endhint %}

### Next <a href="#next" id="next"></a>

In this tutorial, you learned how to use the powerful CRUD features of Vault to store arbitrary secrets. On its own, this is already a useful but basic feature. Key/Value secrets engine is one of the secrets engines that Vault offers.

You may notice other tutorials on our site using the `kv` CLI commands with a different syntax (`$ vault kv get secret/foo` instead of the `$ vault kv get -mount=secret foo` that we've shown you here). Either style will have the same end result, but we recommend the more explicit `-mount` flag syntax when working with **KV secrets engine v2**, as it can avoid confusion later when you need to refer to the secret by its full path (`secret/data/foo`) when writing policies or raw API calls.
