---
title: "Deploy Vault | (Just Updated) Secrets Manager with KV API, Auto-Unsealed, Root Token Generated, Data Survives Redeploys"
description: "Vault secrets manager: KV API, auto-unseal, generated root token"
category: "Authentication"
url: https://railway.com/deploy/vault-or-just-updated-secrets-manager-wi
---

# Deploy Vault | (Just Updated) Secrets Manager with KV API, Auto-Unsealed, Root Token Generated, Data Survives Redeploys

Vault secrets manager: KV API, auto-unseal, generated root token

**[Deploy Vault | (Just Updated) Secrets Manager with KV API, Auto-Unsealed, Root Token Generated, Data Survives Redeploys on Railway](https://railway.com/template/vault-or-just-updated-secrets-manager-wi)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/vault-or-just-updated-secrets-manager-wi/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Authentication

## Template content

### vault

- **Image:** hashicorp/vault:2.2.1@sha256:962a92876e168d68eaaa24b0b8b49bbce1cb63024060a67bba95cd158a366fc2
- **Start command:** `/bin/sh -c 'exec sh -c "$(echo RD0vdmF1bHQvZmlsZQpJTklUPSIkRC9yYWlsd2F5LWluaXQuanNvbiIKUD0iJHtQT1JUOi04MDgwfSIKSE9TVE49IiR7UkFJTFdBWV9QVUJMSUNfRE9NQUlOOi1sb2NhbGhvc3R9IgpST09UPSIke1ZBVUxUX1RPS0VOOi19Igp1bnNldCBWQVVMVF9UT0tFTgpleHBvcnQgU0tJUF9TRVRDQVA9MQpleHBvcnQgVkFVTFRfQUREUj1odHRwOi8vMTI3LjAuMC4xOjgyMDAKTE9PUD0neyJ0Y3AiOnsiYWRkcmVzcyI6IjEyNy4wLjAuMTo4MjAwIiwidGxzX2Rpc2FibGUiOnRydWV9fScKUFVCPSd7InRjcCI6eyJhZGRyZXNzIjoiWzo6XTonIiRQIiciLCJ0bHNfZGlzYWJsZSI6dHJ1ZX19JwoKY2ZnKCkgewogIGV4cG9ydCBWQVVMVF9MT0NBTF9DT05GSUc9J3sidWkiOnRydWUsImRpc2FibGVfbWxvY2siOnRydWUsInN0b3JhZ2UiOnsiZmlsZSI6eyJwYXRoIjoiL3ZhdWx0L2ZpbGUifX0sImxpc3RlbmVyIjpbJyIkMSInXSwiYXBpX2FkZHIiOiInIiQyIicifScKfQpzdGFydCgpIHsKICAvdXNyL2xvY2FsL2Jpbi9kb2NrZXItZW50cnlwb2ludC5zaCBzZXJ2ZXIgJgogIFBJRD0kIQp9CndhaXRfdXAoKSB7CiAgZm9yIGkgaW4gJChzZXEgMSA5MCk7IGRvCiAgICB2YXVsdCBzdGF0dXMgPi9kZXYvbnVsbCAyPiYxCiAgICBbICQ/IC1uZSAxIF0gJiYgcmV0dXJuIDAKICAgIGtpbGwgLTAgJFBJRCAyPi9kZXYvbnVsbCB8fCB7IGVjaG8gIltib290XSB2YXVsdCBleGl0ZWQgYmVmb3JlIGxpc3RlbmluZyI7IGV4aXQgMTsgfQogICAgc2xlZXAgMQogIGRvbmUKICBlY2hvICJbYm9vdF0gdmF1bHQgZGlkIG5vdCBzdGFydCBsaXN0ZW5pbmciOyBleGl0IDEKfQpmaWVsZCgpIHsgdHIgLWQgJyBcbicgPCAiJElOSVQiIHwgc2VkICdzLy4qIiciJDEiJyI6XFtcezAsMVx9IlwoW14iXSpcKSIuKi9cMS8nOyB9CnRyYXAgJ2tpbGwgLVRFUk0gJFBJRCAyPi9kZXYvbnVsbDsgd2FpdCAkUElEOyBleGl0IDAnIFRFUk0gSU5UCgpta2RpciAtcCAiJEQiCmVjaG8gIltib290XSBkYXRhIGRpciBvd25lcj0kKHN0YXQgLWMgJXU6JWcgIiREIikiCgojIEZpcnN0IGJvb3Q6IGluaXRpYWxpc2Ugb24gdGhlIGxvb3BiYWNrIGFkZHJlc3Mgb25seSwgc28gbm9ib2R5IGNhbiByZWFjaCB0aGUKIyB1bmF1dGhlbnRpY2F0ZWQgaW5pdCBlbmRwb2ludCBiZWZvcmUgdGhlIGtleXMgYXJlIHNhdmVkLgppZiBbICEgLWYgIiRJTklUIiBdOyB0aGVuCiAgaWYgWyAtZCAiJEQvY29yZSIgXSB8fCBbIC1kICIkRC9zeXMiIF0gfHwgWyAtZCAiJEQvbG9naWNhbCIgXTsgdGhlbgogICAgTz0iJEQvb3JwaGFuZWQtJChkYXRlICslcykiCiAgICBta2RpciAiJE8iCiAgICBmb3IgZiBpbiBjb3JlIHN5cyBsb2dpY2FsOyBkbyBbIC1lICIkRC8kZiIgXSAmJiBtdiAiJEQvJGYiICIkTy8iOyBkb25lCiAgICBlY2hvICJbYm9vdF0gc3RvcmFnZSB3aXRob3V0IGtleXMgbW92ZWQgdG8gJE8iCiAgZmkKICBjZmcgIiRMT09QIiAiaHR0cDovLzEyNy4wLjAuMTo4MjAwIgogIHN0YXJ0CiAgd2FpdF91cAogIHVtYXNrIDA3NwogIHZhdWx0IG9wZXJhdG9yIGluaXQgLWtleS1zaGFyZXM9MSAta2V5LXRocmVzaG9sZD0xIC1mb3JtYXQ9anNvbiA+ICIkSU5JVC50bXAiICYmIG12ICIkSU5JVC50bXAiICIkSU5JVCIgfHwgeyBlY2hvICJbYm9vdF0gaW5pdCBmYWlsZWQiOyBleGl0IDE7IH0KICBlY2hvICJbYm9vdF0gdmF1bHQgaW5pdGlhbGlzZWQsIGtleXMgc2F2ZWQgb24gdGhlIHZvbHVtZSIKICBraWxsIC1URVJNICRQSUQ7IHdhaXQgJFBJRApmaQoKS0VZPSIkKGZpZWxkIHVuc2VhbF9rZXlzX2I2NCkiClJUPSIkKGZpZWxkIHJvb3RfdG9rZW4pIgpjZmcgIiRMT09QLCRQVUIiICJodHRwczovLyRIT1NUTiIKc3RhcnQKd2FpdF91cAoKdmF1bHQgc3RhdHVzID4vZGV2L251bGwgMj4mMQppZiBbICQ/IC1lcSAyIF07IHRoZW4KICB2YXVsdCBvcGVyYXRvciB1bnNlYWwgIiRLRVkiID4vZGV2L251bGwgfHwgeyBlY2hvICJbYm9vdF0gdW5zZWFsIGZhaWxlZCI7IGV4aXQgMTsgfQogIGVjaG8gIltib290XSB2YXVsdCB1bnNlYWxlZCIKZmkKCiMgVGhlIHJvb3QgdG9rZW4gdGhlIGRlcGxveWVyIHNlZXMgaXMgVkFVTFRfVE9LRU4gKGdlbmVyYXRlZCBieSB0aGUgdGVtcGxhdGUpLgojIFZhdWx0IGdlbmVyYXRlcyBpdHMgb3duIGluaXRpYWwgcm9vdCB0b2tlbiBhdCBpbml0LCBzbyBtaW50IHRoZSB0ZW1wbGF0ZSdzIG9uZQojIGFzIGEgcm9vdCB0b2tlbiB3aXRoIHRoYXQgZXhhY3QgaWQsIG9uY2UuCmlmIFsgLW4gIiRST09UIiBdOyB0aGVuCiAgaWYgISBWQVVMVF9UT0tFTj0iJFJPT1QiIHZhdWx0IHRva2VuIGxvb2t1cCA+L2Rldi9udWxsIDI+JjE7IHRoZW4KICAgIFZBVUxUX1RPS0VOPSIkUlQiIHZhdWx0IHRva2VuIGNyZWF0ZSAtaWQ9IiRST09UIiAtcG9saWN5PXJvb3QgLWRpc3BsYXktbmFtZT1yYWlsd2F5LXJvb3QgPi9kZXYvbnVsbCB8fCB7IGVjaG8gIltib290XSBjb3VsZCBub3QgY3JlYXRlIHRoZSBWQVVMVF9UT0tFTiByb290IHRva2VuIjsgZXhpdCAxOyB9CiAgICBlY2hvICJbYm9vdF0gVkFVTFRfVE9LRU4gcm9vdCB0b2tlbiBjcmVhdGVkIgogIGZpCiAgVVNFPSIkUk9PVCIKZWxzZQogIFVTRT0iJFJUIgogIGVjaG8gIltib290XSBWQVVMVF9UT0tFTiBpcyBub3Qgc2V0OyBpbml0aWFsIHJvb3QgdG9rZW4gaXMgaW4gJElOSVQiCmZpCmlmICEgVkFVTFRfVE9LRU49IiRVU0UiIHZhdWx0IHNlY3JldHMgbGlzdCAyPi9kZXYvbnVsbCB8IGdyZXAgLXEgJ15zZWNyZXQvJzsgdGhlbgogIFZBVUxUX1RPS0VOPSIkVVNFIiB2YXVsdCBzZWNyZXRzIGVuYWJsZSAtcGF0aD1zZWNyZXQgLXZlcnNpb249MiBrdiA+L2Rldi9udWxsICYmIGVjaG8gIltib290XSBrdiB2MiBlbmFibGVkIGF0IHNlY3JldC8iCmZpCmVjaG8gIltib290XSByZWFkeSBvbiBwb3J0ICRQIgp3YWl0ICRQSUQK | base64 -d)"'`
- **Health check:** /ui/
- **Public domain:** Yes

## Documentation

# Deploy and Host Vault on Railway

**Built for an LLM agent to deploy and use.** There is no initialise or unseal step to perform and nothing to type into the deploy form: Vault is initialised on first boot, unsealed on every boot, a root token is generated, and a KV v2 secrets engine is already mounted. The contract below lists every address, variable name and one script that writes and reads a secret.

Vault is a secrets manager. Apps and agents store API keys, database passwords and certificates in it and read them back over an HTTP API with a token, instead of keeping them in files and environment variables. This template runs a single Vault server with file storage on a volume.

## About Hosting Vault

This template runs one service: the official `hashicorp/vault` v2.2.1 image, pinned by digest, with a volume on `/vault/file`. The volume holds the encrypted storage and the unseal key, so secrets, policies and tokens survive redeploys.

Vault normally starts sealed and needs a human to run `vault operator init` and `vault operator unseal`. The start command does both. On first boot it initialises Vault on the loopback address only, so nobody can reach the unauthenticated init endpoint before the keys are saved, stores the unseal key on the volume, and then starts the real server on all interfaces. On every later boot it unseals with the stored key. It then creates the root token `VAULT_TOKEN` (a 40-character generated secret) and mounts a KV v2 engine at `secret/`.

The trade-off is that the unseal key lives next to the data, so anyone who can read the volume can read the secrets. That suits dev, staging and agent workloads; for a high-assurance deployment, use Vault's cloud auto-unseal instead.

### Agent contract

- Public URL: `VAULT_PUBLIC_URL` (`https://` plus the service's `RAILWAY_PUBLIC_DOMAIN`). The web UI is at `/ui/`, the API under `/v1/`.
- Private URL: `http://vault.railway.internal:8080` (`VAULT_PRIVATE_URL`).
- Credentials: `VAULT_TOKEN`, a root token. Keep it out of app code; create narrower tokens and policies for apps.
- Auth: send the header `X-Vault-Token: $VAULT_TOKEN` on every `/v1/` call.
- Health: `GET /v1/sys/health` returns 200 when initialised, unsealed and active. The deploy healthcheck is `GET /ui/`. The web UI answers 502 to a client that sends `Accept-Encoding: identity`, so use the API for scripted checks.
- API: `GET` and `PUT /v1/secret/data/PATH` (KV v2), `GET /v1/sys/mounts`, `POST /v1/sys/policies/acl/NAME`, `POST /v1/auth/token/create`.

```bash
# run with VAULT_PUBLIC_URL and VAULT_TOKEN set
U="$VAULT_PUBLIC_URL"; T="$VAULT_TOKEN"
curl -s -o /dev/null -w "health: %{http_code}\n" "$U/v1/sys/health"
curl -s -o /dev/null -w "no token: %{http_code}\n" "$U/v1/secret/data/agent-test"
curl -s -o /dev/null -w "write: %{http_code}\n" -H "X-Vault-Token: $T" -H "Content-Type: application/json" -d '{"data":{"api_key":"s3cret"}}' "$U/v1/secret/data/agent-test"
curl -s -H "X-Vault-Token: $T" "$U/v1/secret/data/agent-test" | grep -o '"api_key":"[^"]*"'
curl -s -o /dev/null -w "delete: %{http_code}\n" -X DELETE -H "X-Vault-Token: $T" "$U/v1/secret/metadata/agent-test"
```

A fresh deploy prints `health: 200`, `no token: 403`, `write: 200`, `"api_key":"s3cret"` and `delete: 204`. In your own app, point the Vault client at `VAULT_PUBLIC_URL` (or the private URL from another Railway service) and authenticate with a token you created for it.

## Why Deploy Vault on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Vault on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

- **Agent-ready** - generated root token, initialised and unsealed on boot, KV v2 already mounted; nothing to type into the deploy form.
- **No exposed init window** - Vault is initialised on loopback before the public listener opens.
- **Restarts do not lock you out** - the unseal key is kept on the volume, so a redeploy comes back unsealed instead of sealed.
- **State survives redeploys** - storage lives on a volume and the image is pinned by digest.
- **A healthcheck that works** - the web UI is checked on every deploy, so a bad deploy is caught instead of served.

## Common Use Cases

- **Secrets store for AI agents** - an agent reads its API keys from Vault with a scoped token instead of holding them in its prompt or environment.
- **Central secrets for Railway services** - one place for database passwords and third-party keys that several services fetch at start.
- **Short-lived credentials** - enable the database or AWS secrets engines through the API to hand out credentials that expire.

## Dependencies for Vault Hosting

- One Railway volume on `/vault/file`, created by the template.

### Deployment Dependencies

- [Vault repository](https://github.com/hashicorp/vault)
- [Official image](https://hub.docker.com/r/hashicorp/vault)
- [Vault documentation](https://developer.hashicorp.com/vault/docs)

### Implementation Details

| Variable | Purpose |
| --- | --- |
| `VAULT_TOKEN` | Root token, generated per deploy. Created at first boot with this exact value. |
| `VAULT_PUBLIC_URL` | HTTPS address of the instance. Also used as Vault's `api_addr`. |
| `VAULT_PRIVATE_URL` | Address on the private network. |
| `RAILWAY_RUN_UID` | Set to 0 so the start command can write the root-owned volume. |

Vault is licensed under the Business Source License 1.1. Using it to store your own secrets is permitted. Tokens created with a chosen id use SHA1 hashing, which Vault warns about; create narrower tokens without a chosen id for apps. The unseal key and initial root token are saved at `/vault/file/railway-init.json`.


## Similar templates

- [Keycloak](https://railway.com/deploy/mSwigX) — [2026-11-04] Keycloak with keywind theme + Apple & Discord providers
- [lua-protector](https://railway.com/deploy/lua-protector) — Test deployed my project first
- [bknd](https://railway.com/deploy/p4nTYL) — Feature-rich yet lightweight backend

Open this page in a browser: https://railway.com/deploy/vault-or-just-updated-secrets-manager-wi
