A Nushell-native configuration compiler and execution engine for environment and secrets management.
- Generates
.envfrom declarative templates with{{ token }}substitution - Manages secrets: generates, rotates, and delivers them to file or other backends
- Manages PKI certificate chains (Root CA → Intermediate → Leaf) via openssl
- Validates all config against TOML schemas before writing anything
- Tracks versions in
.envctl.lock(commit this) and an audit log in.envctl/state.ndjson(gitignore the.envctl/directory)
- Nushell >= 0.94
openssl>= 3.0 (for secrets and certificates)git(for thegitprovider)
http gethttps://raw.githubusercontent.com/arttet/envctl/main/install.nu|into string|nu-c$inAfter installation, restart your Nushell session — all envctl commands are available globally.
Default install paths:
| OS | Path |
|---|---|
| Linux / macOS | ~/.local/share/envctl |
| Windows | %LOCALAPPDATA%\envctl |
The installer writes an autoload hook to $nu.vendor-autoload-dirs — no manual source needed.
More options (from a cloned repo):
nuinstall.nu--prefix~/.envctl# custom install directorynuinstall.nu--dry-run# preview without writing anythingnuinstall.nu--uninstall# remove files and autoload hookenvctlinitenvctlgenerateenvctlenvfilegenerateenvctlsecretsgenerateenvctlcertsgenerateenvctlhealthCreate .envctl.toml in your project root:
schema = "v1"
[providers]
enabled = ["git", "password"]
[generators]
GIT_ROOT_DIR = "{{ provider:git.top-level-dir }}"
[envfile]
file = ".env"pattern = ".env.example"
[secrets]
base_dir = "."
[secrets.DB_PASSWORD_FILE]
value_source = "{{ provider:password.generate-password }}"targets = ["file"]
[secrets.DB_PASSWORD_FILE.options.file]
path = "{{ GIT_ROOT_DIR }}/secrets/db_password"Then commit .envctl.toml and .envctl.lock. Add .envctl/ and .env to .gitignore.
| Token | Example | Resolves to |
|---|---|---|
{{ IDENT }} | {{ GIT_ROOT_DIR }} | Value from resolved generators |
{{ secret:IDENT }} | {{ secret:DB_PASS_FILE }} | Contents of file at path stored in IDENT |
{{ provider:NAME.FN }} | {{ provider:git.top-level-dir }} | Calls fn from provider manifest |
envctlenvfilegenerate [--stage] [--dry-run] [--quiet] [--config]
envctlenvfilediffenvctlsecretsgenerate [--stage] [--dry-run]
envctlsecretsrotate--keyNAMEenvctlsecretsrotate-allenvctlcertsgenerate [--nameNAME] [--dry-run]
envctlcertsrotate--nameNAMEenvctlcertsrotate-allenvctlcertsstatusenvctlhealth [--profileenvfile|secrets|certs]
envctlpluginslist| Profile | What runs |
|---|---|
envfile | Parse generators + render .env |
secrets | Generate missing secrets via providers, write via backends |
certs | Generate PKI certificate chains |
all | envfile + secrets + certs |
| Variable | Default | Effect |
|---|---|---|
ENVCTL_CONFIG | .envctl.toml | Override config path |
ENVCTL_STAGE | dev | Override stage |
ENVCTL_DRY_RUN | false | Enable dry-run (no writes) |
ENVCTL_QUIET | false | Suppress non-error output |
| Provider | Token | Config |
|---|---|---|
git | {{ provider:git.top-level-dir }} | none (override with ENVCTL_GIT_ROOT) |
password | {{ provider:password.generate-password }} | length, charset, tool |
compose | {{ provider:compose.collect-files }} | base_dir, base_files, services |
certs | (used internally by envctl certs) | tool, key_bits, organization, country |
| Backend | Writes to |
|---|---|
file | Local filesystem path |
justfmt# Format codejustlint# Run linterjusttest# Run testsjustrunenvctlhealth# Run any commandnurun_tests.nu# All testsnurun_tests.nu--unit# Unit tests onlynurun_tests.nu--filetests/unit/grammar_test.nuSee Architecture for the execution flow and layer responsibilities.
MIT — see LICENSE.