Envault Serve: Your Encrypted .env Files Now Have a REST API
You encrypt your secrets with envault. You rotate them with envault. You sync them across environments with envault. But when your MCP server, CI sidecar, or agent runtime needs a secret at runtime, you still write custom decryption glue code.
Not anymore. rh-envault serve exposes your decrypted secrets as a JSON HTTP API with a single command. configured API-key auth. Prefix filtering. Health checks. Zero custom code.
Try it now
pip install git+https://github.com/Coding-Dev-Tools/envault.git · rh-envault serve --port 8080 --api-key YOUR_API_KEY · Your secrets are live over HTTP
View on GitHub →In This Article
The Gap: Encrypted at Rest, Unusable at Runtime
Secrets management tools solve half the problem. You encrypt .env files, rotate keys, and sync across environments. But the other half — getting decrypted secrets to the processes that need them — still requires custom work:
- MCP servers that need API keys at startup — you shell out to
rh-envault decrypt, parse the output, inject into env vars - CI/CD sidecars that fetch secrets for deploy-time injection — you write a script that calls the vault API, handles auth, retries on failure
- AI agent runtimes that need credentials mid-session — you either bake secrets into the agent config (risky) or add a secrets-fetch step to every agent session
Each of these is a small integration project. Small projects add up. And every custom integration is a place where secrets leak, auth breaks, or rotation fails silently.
rh-envault serve eliminates the glue code. Start the server, authenticate with a configured API key, fetch secrets over HTTP. That's it.
How rh-envault serve Works
One command starts the API:
# Start the secrets API on port 8080 (default) rh-envault serve --port 8080 --api-key YOUR_API_KEY # Or specify a custom host and password rh-envault serve --host 0.0.0.0 --port 3000 --password your-master-key --api-key YOUR_API_KEY
The server reads your .envault.yml config, connects to your configured secret store (local .env, AWS SSM, Vault, Doppler, or 1Password), and exposes three endpoints:
GET /health— Store connectivity check (unauthenticated)GET /secrets— List all secret keys, with optional?prefix=XfilteringGET /secrets/{key}— Get the decrypted value for a specific key
Auth Model: Configured API Key
Configure a separate API credential with --api-key or ENVAULT_API_KEY. It is not derived from your encryption password. These examples use the X-API-Key header accepted by the published request handler:
# Replace YOUR_API_KEY with your own API credential rh-envault serve --port 8080 --api-key YOUR_API_KEY # Fetch secret keys with curl curl -H "X-API-Key: YOUR_API_KEY" \ http://localhost:8080/secrets # Filter keys by prefix curl -H "X-API-Key: YOUR_API_KEY" \ "http://localhost:8080/secrets?prefix=STRIPE"
On localhost, starting the server without an API credential permits unauthenticated requests. Set the API key before using the authenticated examples. Keep the encryption password and the API credential separate, and rotate each explicitly.
The executable and authentication examples here follow the current console script and server implementation.
API Reference
GET /health
Connectivity check for the backing store. No auth required.
$ curl http://localhost:8080/health
{
"status": "ok",
"checks": {
"local": { "status": "ok", "path": ".env.production" }
}
}
GET /secrets
List all secret keys. Supports ?prefix=X to filter. Auth required.
$ curl -H "X-API-Key: YOUR_API_KEY" \
http://localhost:8080/secrets?prefix=STRIPE
{
"keys": ["STRIPE_PUBLIC_KEY", "STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET"],
"count": 3
}
GET /secrets/{key}
Get the decrypted value for a single key. Auth required.
$ curl -H "X-API-Key: YOUR_API_KEY" \
http://localhost:8080/secrets/STRIPE_SECRET_KEY
{
"key": "STRIPE_SECRET_KEY",
"value": "sk_live_..."
}
Three Use Cases Where This Matters
1. MCP Server Secret Injection
When you wrap a CLI as an MCP server with click-to-mcp, the server process needs API keys to call external services. Instead of baking secrets into the MCP config or the process environment:
# Start rh-envault serve as a sidecar rh-envault serve --port 8080 --api-key "$ENVAULT_API_KEY" & # Your MCP server fetches secrets at startup STRIPE_KEY=$(curl -s -H "X-API-Key: $ENVAULT_API_KEY" \ http://localhost:8080/secrets/STRIPE_SECRET_KEY | jq -r .value) # MCP server starts with the decrypted key click-to-mcp serve my-tool --env STRIPE_SECRET_KEY=$STRIPE_KEY
No secrets in config files. No secrets in container images. The sidecar pattern keeps the decryption boundary tight.
2. CI/CD Deploy-Time Secret Fetch
In your GitHub Actions deploy step, fetch secrets from envault instead of storing them as GitHub Secrets (which can't be rotated automatically and have a 48-hour cache lag):
# .github/workflows/deploy.yml
- name: Fetch secrets from envault
run: |
curl -s -H "X-API-Key: ${{ secrets.ENVAULT_API_KEY }}" \
http://envault.internal:8080/secrets?prefix=PROD_ | \
jq -r '.keys[]' | while read key; do
val=$(curl -s -H "X-API-Key: ${{ secrets.ENVAULT_API_KEY }}" \
"http://envault.internal:8080/secrets/$key" | jq -r .value)
echo "$key=$val" >> $GITHUB_ENV
done
Pair this with rh-envault rotate-all --env prod in a scheduled job, and your deployment always gets the latest rotated secrets — no manual secret updates in GitHub.
3. AI Agent Runtime Credential Store
AI agents that use tool-calling patterns need credentials mid-session. Instead of embedding secrets in agent config (which gets logged, versioned, and leaked):
# Agent runtime fetches credentials on demand
def get_credential(key: str) -> str:
resp = requests.get(
f"http://localhost:8080/secrets/{key}",
headers={"X-API-Key": os.environ["ENVAULT_API_KEY"]}
)
return resp.json()["value"]
# Agent uses credentials only when needed, never stored in memory long-term
stripe_key = get_credential("STRIPE_SECRET_KEY")
This is the integration pattern recommended by the Agent Vault evaluation (COM-256): rh-envault serve as a lightweight, self-hosted credential store backend for AI agent workflows.
How This Compares to Vault, Doppler, and Infisical
| rh-envault serve | HashiCorp Vault | Doppler | Infisical | |
|---|---|---|---|---|
| Setup | 1 command | Server + storage backend + IAM | Cloud account + CLI + sync | Cloud account + CLI + agents |
| Auth model | Configured API key (X-API-Key) | Tokens, roles, policies | Service tokens + RBAC | Service tokens + RBAC |
| Self-hosted | Yes, fully | Yes | No (cloud only) | Yes (Agent Vault) |
| Secrets stay local | Yes | Yes (with config) | No | Partial |
| Zero external deps | Yes — stdlib only | No — Consul/storage backend | No — cloud API | No — KMS + agents |
| Cost | Free, open source | Free (self-host) / $1.50/hr (HCP) | Free tier / $18/mo+ | Free tier / $8/seat/mo |
| Best for | Small teams, CI/CD sidecars, agent runtimes | Enterprise, multi-team, compliance | SaaS teams, cloud-native | Teams needing agent secrets |
When to choose rh-envault serve: You want a secrets API without standing up a Vault cluster, without sending secrets to a cloud service, and without adding a new dependency to your infrastructure. If you already use envault for encryption and rotation, rh-envault serve is the natural runtime extension — your existing config and stores, with a separate API credential.
When to choose Vault: You need enterprise-grade audit logging, multi-team RBAC, secret leasing with automatic revocation, or PKI/certificate management. Vault is the right choice at scale — rh-envault serve is the right choice when you need a secrets API in 30 seconds.
Security Model and Trade-offs
Honest security posture for rh-envault serve:
- Bind address: Defaults to
127.0.0.1(localhost only). Use--host 0.0.0.0only behind a firewall or reverse proxy. - Transport: No built-in TLS. Run behind a reverse proxy (nginx, Caddy) for HTTPS in production, or use a VPN/service mesh.
- Auth: Configure an API key and send it in the X-API-Key header. No built-in rate limiting; add this at the reverse proxy layer.
- Secrets in memory: The local .env store caches its plaintext key/value mapping in the server process between requests. Restart the server after external file changes or rotation; other store backends may have different caching behavior.
- Rotation: Pair with
rh-envault rotateandrh-envault rotate-allfor automatic key rotation. Restart the server to pick up rotated values.
The intended deployment is a sidecar or internal service — not an internet-facing endpoint. If you need internet-facing secrets distribution, use Vault with proper TLS, IAM policies, and audit logging.
Get Started
# Install envault pip install git+https://github.com/Coding-Dev-Tools/envault.git # Initialize your project rh-envault init my-project # Start the secrets API rh-envault serve --port 8080 --api-key YOUR_API_KEY # Test it curl http://localhost:8080/health curl -H "X-API-Key: YOUR_API_KEY" http://localhost:8080/secrets
Your encrypted secrets were already safe at rest. Now they're accessible at runtime — using your existing config and an explicitly configured API credential.
Start serving your secrets over HTTP
pip install git+https://github.com/Coding-Dev-Tools/envault.git · Apache 2.0 · Free and open source
View on GitHub → Full command docs →DevForge builds 11 open-source CLI tools for developers — from API contract validation to environment variable management to infrastructure cost previews. Every tool is built by autonomous AI agents. See all tools →