Effortless environment variable loading and management for any workflow.
Manage your application's environment variables with simplicity and power. setnv helps you centralize configuration and sensitive data in easy-to-use .env files, supporting dynamic variable expansion and seamless secret integration. It also supports chaining multiple .env files, allowing for layered configurations.
Store your kopia environment variables in a myconfig.env file, and use setnv to call kopia with the resolved environment variables including gopass secrets.
setnv myconfig kopia [kopia-params]setnvlooks for amyconfig.envfile in current directory, or in~/.config/setnv/myconfig.env- reads
myconfig.envfile and loadsKEY=VALUEpairs, e.g.KOPIA_PASSWORD=$(gopass show test/KOPIA_PASSWORD) - pass these resolved
KEY=VALUEpairs tokopia <params>
For layered configurations, you can chain multiple .env files. For example, default.env defines default settings, and myconfig.env overrides some variables in the default:
setnv default,myconfig kopia [kopia-params]-
Chained Configuration: Specify multiple
.envfiles (e.g.,id1,id2,id3). Variables from later files in the chain override those from earlier ones, enabling powerful layered configurations. -
Intelligent
.envParsing: ReadsKEY=VALUEpairs, gracefully skipping comments and empty lines. -
Smart Value Handling: Supports both double-quoted values (with full escape sequence support like
\n,\") and literal single-quoted values. -
Robust Variable Expansion: Resolve
$VARand${VAR}references within your.envfile. It handles recursive expansions and prevents infinite loops from circular dependencies, resolving unresolvable variables to empty strings with a warning. -
Seamless Gopass Integration: Directly inject secrets from your
gopassstore using$(gopass show <path>)or$(gopass <path>)syntax. This is a specially handled command substitution for convenient secret retrieval, keeping sensitive data out of plain text. -
Command Substitution: Dynamically set variable values by executing shell commands and capturing their standard output.
setnvsupports two main syntaxes for general command execution:-
$(command args): The traditional shell command substitution syntax, e.g.,MY_VAR=$(echo "hello"). While supported, this syntax has limitations with complex nested shell syntax (e.g., unquoted parentheses or backticks) within the command string. -
$[command args]: Recommended for robust command execution, especially when your commands include internal parentheses, backticks, or other complex shell constructs. Example:APP_VERSION=$[git describe --tags --abbrev=0]orCOMPLEX_CMD=$[echo "Current time is $(date) (GMT)"].
-
-
Flexible Execution Modes:
-
Execute a Command: Load variables and run a specified executable with its arguments, with the environment isolated to that process.
-
Launch a Subshell: Load variables and open a new interactive shell, handy for development sessions.
-
Export to Current Shell: Generate
exportcommands forevaling the environment directly into your active shell session. -
View Variables: Safely display the fully resolved environment variables before applying them, useful for debugging.
-
-
Environment Sandboxing (
--sandboxed): Control whethersetnvpasses inherited system environment variables to the target process. With--sandboxed, only variables explicitly defined in your.envfiles are passed, creating a clean, isolated environment. -
Portable & Minimal: Built in Go,
setnvcompiles into a single, self-contained binary, ensuring easy distribution and minimal external dependencies.
setnv first locates your .env file(s) based on the provided IDs, prioritizing the current directory before checking a central configuration directory (e.g., ~/.config/setnv/). When chaining multiple IDs (e.g., base,dev), files are processed in order, with later files overriding variables defined in earlier ones. It then meticulously reads each line, parsing key-value pairs, handling quoted strings, and executing gopass commands or other shell commands to fetch dynamic values.
After the initial parsing and command substitutions, setnv performs an iterative variable expansion process, resolving all $VAR and ${VAR} references within the loaded environment variables, handling nesting and detecting circularities. Finally, based on your chosen mode and the --sandboxed flag:
- For running executables or launching subshells,
setnvusessyscall.Execto replace its own process with the target command, ensuring the environment is seamlessly passed. The environment passed includes variables from.envfiles, optionally merged with the inherited system environment based on the--sandboxedflag. - For exporting variables, it prints shell-compatible
exportcommands to standard output. - For viewing, it simply prints the resolved variables to your terminal.
While other tools exist for managing .env files, setnv aims to be a minimal, self-contained Go binary that's easy to distribute and use, especially in environments where installing Python or Node.js dependencies might be cumbersome. It provides built-in gopass integration for those who manage secrets with it, and clear modes of operation for various workflows. Its ability to chain multiple .env files and offer sandboxed execution provides powerful flexibility for complex configurations.
You can build setnv from source:
git clone https://github.com/revivalstack/setnv.git
cd setnv
go build -o setnv .
sudo mv setnv /usr/local/bin/or via
go install github.com/revivalstack/setnv@latestEnvironment files are expected to be located in ~/.config/setnv/<id>.env.
You can override the base configuration directory by setting the LOAD_ENV_CONFIG_DIR environment variable.
# My project's environment variables
DB_HOST=localhost
DB_PORT=5432
DB_USER=admin
DB_PASS=$(gopass show myproject/database/password) # Fetches password from gopass
BUILD_ID=$[date +%Y%m%d%H%M%S] # Example of robust command substitution using $[]
API_KEY="supersecret_key_with_\"quotes\""
APP_URL=http://$DB_HOST:$DB_PORT/app
MESSAGE='This is a literal string with $ and \' characters.'
To load base.env then dev.env, with dev.env overriding variables from base.env:
setnv base,dev myapp-script.shTo load variables for myproject and then run a command:
setnv myproject node index.js --port 3000To load variables for myproject and launch a new interactive shell:
setnv myprojectTo load variables for myproject into your current shell session (variables will persist):
eval "$(setnv myproject --export)"Warning: Variables exported this way are visible in your shell's environment (env, ps e) and can persist across commands. Use with caution for sensitive data.
To see the resolved environment variables for myproject without running any commands:
setnv myproject --viewWarning: This will print plaintext secrets (if any are resolved from gopass) to your terminal.
To run a command with only the environment variables defined in myproject.env, ignoring inherited system environment variables (unless overridden):
setnv myproject --sandboxed bash -c 'echo "PATH: $PATH, MY_VAR: $MY_VAR"'
# MY_VAR will be whatever is in myproject.env, PATH will likely be empty if not explicitly set there.setnv --version
setnv --helpSeamlessly inject setnv's variables into your containers:
-
Via
--env-file(Podman or Docker): Usesetnv --viewwith your shell's process substitution (<()) to stream resolved variables as an environment file to your container runtime. This is the most robust method for both Podman and Docker.# For Podman: podman run --rm --env-file <(setnv base,dev --view) alpine env # For Docker: docker run --rm --env-file <(setnv base,dev --view) alpine env
- Note: Requires shells supporting process substitution (e.g., Bash, Zsh).
- Security: Output (including secrets) is streamed, not printed to terminal, but the command remains visible in shell history and process lists.
-
Via
--env-host(Podman only): Havesetnvdirectly execute thepodman runcommand. Use--env-hostflag if you want environment variables set bysetnv(and other host variables) to be passed into the container.# setnv sets env for the 'podman' process, and '--env-host' passes them to 'alpine' setnv base,dev podman run --rm --env-host alpine printenv
We welcome contributions to setnv! If you have ideas for new features, bug fixes, or improvements, please feel free to open an issue or submit a pull request.
To contribute:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Make your changes and write tests.
- Ensure all tests pass (
go test -v). - Submit a pull request.
We strive to create a welcoming and inclusive community. Please be respectful and considerate in all your interactions. We expect all contributors to adhere to basic principles of polite and constructive communication. Any behavior that is harassing, discriminatory, or disruptive is not tolerated. Let's keep setnv a friendly place for everyone.
setnv is released under the MIT License.