open-envault 0.3.0

Local-first SOPS-compatible secrets for Git and Rust
Documentation

open-envault

crates.io npm CI License Open Source

Open Source — Local-first, SOPS-compatible secrets for Git and Rust. Push ciphertext to Git; keep private age keys on your machines; inject secrets into child processes only at runtime — no hosted service, no custom crypto. Free and open for everyone to use, learn, and extend.

Built for Rust projects and any language that spawns a child process (Arqen, NestJS, Go via CLI). Encrypted files are plain SOPS age files — sops can decrypt what open-envault encrypts and vice versa.

Features

  • Rust-first, one binary — native Rust, no sops/rage needed at runtime, byte-compatible with sops 3.13 age
  • Push to Gitopen-envault.yaml, config/env.schema.yaml, secrets/*.enc and public age recipients live in Git; private keys never do
  • Fail-closed — bad config/schema/key/ciphertext → non-zero exit, redacted diagnostics
  • Memory-only secrets — data keys and values are zeroized, never logged or written to disk (atomic writes, 0600 key files)
  • Schema & diagnosticsstring/integer/boolean/url/enum/duration + required/secret/env guards, human + stable JSON output
  • Runtime injectionoenv exec dev -- <cmd> merges decrypted values into the child’s env and preserves exit codes/signals

Install

# Rust (binary + library)
cargo install open-envault              # bin `oenv`
# or library for Arqen:
# cargo add open-envault

# Node (binary shim + TypeScript API, wraps the Rust binary)
npm i -D open-envault
# or pnpm / yarn / bun

Prebuilt binaries are attached to each GitHub Release (oenv-<target> + checksums.txt).

Quick start

oenv init                       # creates open-envault.yaml, config/env.schema.yaml, secrets/, .sops.yaml
oenv env create dev
oenv key generate dev           # → prints # public key: age1...  (add it to open-envault.yaml recipients)
# edit open-envault.yaml: recipients: [age1...]
oenv set dev DATABASE_URL       # value read from stdin (never argv)
oenv check dev --format json
oenv exec dev -- npm start

open-envault.yaml example:

project: my-app
environments:
  dev:
    file: secrets/dev.env.enc
    schema: config/env.schema.yaml
    recipients: [age1ql0...]

CLI

oenv init
oenv env create <env>
oenv key generate <env>
open-envault set <env> <VAR>            # reads value from stdin
open-envault edit <env>                 # $EDITOR on a secure temp file
open-envault check <env> [--format human|json]
oenv doctor [--format json]
oenv diff <envA> <envB> [--format json]
oenv rotate <env>
oenv exec <env> -- <cmd> [args...]
oenv example                    # regenerate .env.example from schema

set never takes a value on the command line; exec forwards signals and preserves the child’s exit code; diagnostics never print secret values (one-way HMAC-SHA256 fingerprints only).

Configuration

open-envault.yaml
config/env.schema.yaml
secrets/dev.env.enc
secrets/prod.env.enc
.env.example

Key sources (first match wins): ENVYPT_AGE_KEY / SOPS_AGE_KEY env var → ENVYPT_AGE_KEY_FILE / SOPS_AGE_KEY_FILE~/.config/open-envault/keys/<env>.txt (0600). CI: set SOPS_AGE_KEY as a GitHub Actions secret.

TypeScript / NestJS

import { exec, check } from "open-envault";

await exec("dev", "node", ["server.js"]);
const { findings } = await check("dev");

The npm package is a thin wrapper — it locates the prebuilt open-envault binary in prebuilds/<platform>-<arch>/ and spawns it; no crypto is reimplemented in JS.

Rust / Arqen

[dependencies]
open-envault = "0.1"
let env = open_envault::load_environment("dev")?; // BTreeMap<String,String>, memory-only

Security

See docs/architecture.md and docs/contract.md. Plaintext secrets, decrypted .env files, and private age keys must never be committed (.gitignore covers .env*, *.key, target/). Test fixtures under crates/open-envault/tests/fixtures/ are throwaway and only decrypt fake data.

Docs

  • Architecture — principles, crate map, storage format, key sources
  • Contract — exit codes and stable JSON envelopes for wrappers

License

Code dual-licensed under Apache 2.0 or MIT, at your option. Documentation and course materials additionally available as OpenCourse under CC BY 4.0 — see LICENSE, LICENSE-APACHE, LICENSE-MIT.