From HashiCorp Vault
Move from HashiCorp Vault to ScaiVault. The recommended path: federate first (ScaiVault fronts your Vault), migrate per-path subtrees, retire Vault when nothing reads from it.
You don't need a maintenance window. Reads continue working throughout. The risky steps are obvious and isolated.
When this fits#
- You're already running Vault in production.
- You want unified identity (ScaiKey), unified audit, and managed PKI / dynamic secrets without standing up Vault Enterprise.
- You have time to move incrementally. Lift-and-shift in one weekend is technically possible but unwise.
If you have very simple Vault usage (KV v2 only, a few hundred secrets, one team), skip federation and do direct import — see step 5.
What you need#
- A ScaiVault token with
secrets:write,policies:write,federation:write,admin. - Vault credentials with read access to the KV mounts you want to migrate. AppRole is the recommended auth method.
- 30 minutes for setup; a few weeks for an incremental migration of any non-trivial Vault.
1. Inventory your Vault#
Before anything moves, list what you have:
1 2 3 4 5 6 7 8 9 10 11 | |
Categorize by mount:
- KV v1 / v2 — move via federation or direct import.
- PKI — re-create CAs and roles in ScaiVault, gradually replace.
- Database — recreate dynamic engines in ScaiVault, point apps at the new ones.
- AWS / Azure / GCP — same as Database.
- Transit — ScaiVault doesn't currently expose a Transit-equivalent encryption API. Keep Vault for this if you need it, or migrate to KMS-native crypto.
This guide focuses on KV migration. Other backends follow the same federate-then-migrate pattern; the per-backend specifics live in the Federation Reference.
2. Set up AppRole auth for ScaiVault#
Inside Vault, create an AppRole that ScaiVault can use:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Save ROLE_ID and SECRET_ID.
3. Store the AppRole credentials in ScaiVault#
1 2 3 4 5 6 7 | |
4. Configure federation#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
mode: "proxy" means reads pass through in real time. Vault stays authoritative; nothing in ScaiVault is a copy yet.
Verify with a read:
1 2 3 4 | |
You should see the value Vault holds. ScaiVault's audit log records this read; Vault's audit log records the underlying read it proxied. Both trails exist.
5. Migrate one subtree#
Pick the smallest, lowest-risk subtree. For each path, decide its new home in ScaiVault.
Typical mapping:
| Vault path | New ScaiVault path |
|---|---|
kv/data/apps/billing/db |
environments/production/billing/database |
kv/data/apps/billing/stripe |
environments/production/billing/stripe |
kv/data/shared/salesforce |
shared/integrations/salesforce/oauth |
The new scheme reflects what should be true going forward — see the .env migration tutorial for path-scheme guidance.
Copy the secrets:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
Verify each migrated value matches what Vault returned. A diff script:
1 2 3 4 5 | |
Zero output means clean.
6. Update one consumer to read from the new path#
Pick one service that uses the migrated secret. Update its code to read the ScaiVault path instead of the Vault path. Keep both code paths available behind a config flag — like the .env tutorial describes for env vars.
Verify in production. Audit log shows the service reading the new path:
1 2 | |
7. Update remaining consumers#
Repeat step 6 for every service reading the migrated secret. Use Vault's audit log to find them:
1 2 3 4 | |
Each consumer migration is independent. After a week or so with no Vault reads, you can be confident nothing left behind.
8. Retire the Vault path#
Now's the time to decide: keep Vault as the long-term store too (and let ScaiVault sync from it), or remove it.
To remove: vault kv delete kv/data/apps/billing/db. ScaiVault still has the value — Vault doesn't.
To keep but flip authority: change the federation backend's mode from proxy to sync, with the ScaiVault paths becoming primary. Vault becomes a backup.
1 2 3 4 | |
9. Repeat for the next subtree#
Take the next set of Vault paths. Steps 5-8 again. Different subtrees migrate independently — there's no coordination required across teams.
Migration of non-KV backends#
PKI: Vault PKI roles map cleanly to ScaiVault PKI roles. Create new CAs in ScaiVault, issue new certs from there, let old certs from Vault PKI expire naturally. Don't re-issue Vault-PKI certs in ScaiVault — that just delays the migration.
Database engines: Recreate the engine in ScaiVault pointing at the same database with new root credentials. Update consumers to call ScaiVault's /v1/dynamic/engines/.../creds/... instead of Vault's /v1/database/creds/.... Existing Vault-issued leases keep working until they expire.
AWS / Azure / GCP: Same pattern. Create the engine in ScaiVault, update consumers, let Vault leases drain.
Transit: Out of scope today. If you use Transit heavily, keep Vault for that one workload.
Common questions#
"Do I need to keep Vault and ScaiVault in sync during migration?" No. While you're using federation in proxy mode, Vault is the only source of truth. After you copy a path into ScaiVault and start using the new path, that path is moot in Vault — let it diverge.
"What if my Vault uses Vault Namespaces?" Pass the namespace in the federation config: config.namespace: "acme/finance". ScaiVault scopes reads to that namespace.
"What about tokens issued by Vault?" Vault tokens stop working once you move off Vault. Plan ScaiVault token rollout (via ScaiKey-issued JWTs) in parallel.
"Can ScaiVault federate to multiple Vault instances at once?" Yes. Create multiple federation backends, each with its own path_mapping. Useful when migrating from a multi-region Vault setup.
What's next#
- Federation Deep Dive — modes, conflicts, sync internals.
- Migrate from .env files — the path-scheme discussion applies here too.
- Dynamic Postgres tutorial — replacing Vault's
database/backend.