Veil Keys Docs

CI secret injection

A build needs real secrets — a Stripe key, a database URL — to deploy. The usual answers are bad: commit a .env file (now your secrets are in git history forever) or paste them into each CI platform’s secret store (now they’re scattered across GitHub, GitLab, Vercel, and a wiki, with no shared rotation and no shared audit trail). veil run replaces all of that with one audited, centrally-rotatable, revocable source.

You declare which environment variables map to which Veil services, and veil run resolves them and injects them into your command at the moment it runs — into that child process only, masked out of its output, never written to disk.

veil
$ veil run -- npm run deploy
✓ resolved 2 secrets from veil · injected as env
› deploying… STRIPE_KEY=•••••••• DATABASE_URL=••••••••
✓ deploy complete

If you’ve used 1Password’s op run, this is the same model — pointed at Veil.

The manifest

veil run reads a .veil.json manifest that maps each environment variable to a service (or a specific field of one, with service/field):

{
  "STRIPE_KEY": "stripe",
  "DATABASE_URL": "prod-db/dsn"
}

At runtime, each value on the right is resolved from Veil and set as the env var on the left — but only inside the child process veil run spawns. Your shell never sees the plaintext, and nothing is ever written to a file.

Run it

Mint a CI token in the Veil app (it starts with veil_ci_) and provide it as VEIL_TOKEN:

ci runner
$ export VEIL_TOKEN=veil_ci_…
$ veil run -- ./scripts/deploy.sh
✓ resolved STRIPE_KEY, DATABASE_URL · injected

Want to see what would be injected without exposing anything? veil run --print shows a masked preview of the resolved variables:

veil
$ veil run --print
STRIPE_KEY stripe sk_live_••••••••
DATABASE_URL prod-db/dsn postgres://••••••••

What you actually get

veil run does several concrete things, every run:

  • Resolves secrets from Veil over TLS at runtime — nothing is baked into the image or the repo.
  • Injects them as environment variables into the child process only.
  • Masks them out of the child’s stdout and stderr, so a secret that’s accidentally echoed in a log line comes out redacted.
  • Never writes them to disk — no temp .env, no cache file.

See the full CLI reference for flags, and tokens for how CI tokens differ from agent and SSH tokens.