Skip to content
Zever
Home

Secrets

Read named credentials from the environment or Vault, separate from layered config.

1 min readEdit on GitHub

secrets returns one named credential on demand, without it sitting in a YAML file or a log line. Use it for API keys, webhook signing secrets, and provider tokens, separate from layered config.

Terminal window
SECRETS_ADAPTER=env
SECRETS_PREFIX=ZEVER
Terminal window
SECRETS_PREFIX=ZEVER
ZEVER_STRIPE_KEY=sk_live_...
ZEVER_WEBHOOK_SECRET=whsec_...

prefix is required (default ZEVER) and must have no /, .., or spaces; DEMO_KEY then reads ZEVER_DEMO_KEY exactly (reference).

main.go
package main
import (
"context"
"fmt"
"os"
"github.com/zenta-dev/zever/config"
"github.com/zenta-dev/zever/container"
)
func main() {
os.Setenv("ZEVER_DEMO_KEY", "s3cr3t")
c := container.New(config.Default())
ctx := context.Background()
defer c.Close(ctx)
s, err := c.Secrets()
if err != nil {
fmt.Println("resolve error:", err)
return
}
val, _ := s.Get(ctx, "DEMO_KEY")
fmt.Println("bytes:", len(val))
names, _ := s.List(ctx)
fmt.Println("count:", len(names))
}
bytes: 6
count: 1

Assert on value length, never the value. Secrets() resolves lazily; its Close(ctx) takes a context, unlike most services.

env is read-only, so Set/Delete return secrets.ErrNotSupported and rotation means restarting with new env values. For payment credentials use vault (KV v2): Get, Set, Delete, List over HTTP, 5s timeout, values never in errors.

Terminal window
SECRETS_ADAPTER=vault
SECRETS_ADDR=https://vault.internal:8200
SECRETS_MOUNT=secret
SECRETS_TOKEN_FILE=/run/secrets/vault-token

addr (scheme + host, https only unless allow_insecure: true for test setups), mount (no spaces, .., empty or dot segments; each /-separated segment is URL-escaped, so nested mounts like team/secret work and reserved characters cannot shift path segments), and one of token/token_file are required; namespace is optional. token_file must be readable by its owner only (0600 or stricter) unless allow_insecure_token_file_perms: true explicitly permits broader access. Register with vault.Register() (adapters/secrets/vault). Adapters: secrets/env (default, read-only) and secrets/vault; names must match [A-Za-z0-9._-]+ (ValidateName).

  • Prefer secrets over config env for anything that signs money or auth: payment webhook_secret, the auth JWT secret, provider keys.
  • Values never appear in errors, only service and field names (cfg.RedactedServices()).
Secrets() fails at startup with a prefix error

prefix is empty or contains /, .., or a space. Set SECRETS_PREFIX to a plain namespace such as ZEVER.

Get reports “not found” for an exported variable

The lookup is <PREFIX>_<NAME> exactly, case included; with ZEVER, name DEMO_KEY needs ZEVER_DEMO_KEY.

Set always fails

That is the env contract: read-only by design. Store the value in the environment or process manager, or switch to vault.

Payments · Configuration · Container