pub struct EnvLoader { /* private fields */ }Expand description
Loads environment files with automatic decryption of encrypted values.
EnvLoader reads .env files in a specific order and automatically
decrypts any encrypted values it encounters. It supports multiple
environment variants and user-specific configuration files.
§Examples
use dotenvage::EnvLoader;
// Load from current directory
EnvLoader::new()?.load()?;
// Now encrypted values are available via std::env::var
let api_key = std::env::var("API_KEY")?;§File Loading Order
Files are loaded in the following order (later files override earlier ones):
.env- Base configuration.env.<ENV>- Environment-specific.env.<ENV>-<ARCH>- Architecture-specific (if<ARCH>is set).env.<USER>- User-specific overrides (if<USER>is set).env.<ENV>.<USER>- User overrides for specific environment.env.<ENV>-<ARCH>.<USER>- User overrides for env+arch combo.env.pr-<PR_NUMBER>- PR-specific (GitHub Actions only)
Note: Separators can be either . or - (e.g., .env.local or
.env-local)
§Placeholders
The following placeholders are resolved from environment variables:
<ENV>: Environment name (seeresolve_env())<ARCH>: Architecture name (seeresolve_arch())<USER>: Username (seeresolve_user())<PR_NUMBER>: Pull request number (seeresolve_pr_number())
Implementations§
Source§impl EnvLoader
impl EnvLoader
Sourcepub fn new() -> SecretsResult<Self>
pub fn new() -> SecretsResult<Self>
Creates a new EnvLoader with a default SecretManager.
This will load the encryption key from standard locations:
0. Auto-discover AGE_KEY_NAME from .env or .env.local files
DOTENVAGE_AGE_KEYenvironment variable (full identity string)AGE_KEYenvironment variable- Key file at path determined by discovered
AGE_KEY_NAME - Default key file at XDG path (e.g.,
~/.local/state/dotenvage/dotenvage.key)
§Errors
Returns an error if no encryption key can be found or loaded.
Sourcepub fn with_manager(manager: SecretManager) -> Self
pub fn with_manager(manager: SecretManager) -> Self
Creates an EnvLoader with a specific SecretManager.
Use this when you want to provide your own encryption key.
§Examples
use dotenvage::{
EnvLoader,
SecretManager,
};
let manager = SecretManager::generate()?;
let loader = EnvLoader::with_manager(manager);
loader.load()?;Sourcepub fn load(&self) -> SecretsResult<()>
pub fn load(&self) -> SecretsResult<()>
Loads .env files from the current directory in standard order.
Decrypted values are loaded into the process environment and can be
accessed via std::env::var().
§Errors
Returns an error if any file cannot be read or parsed, or if decryption fails for any encrypted value.
§Examples
use dotenvage::EnvLoader;
EnvLoader::new()?.load()?;
let secret = std::env::var("API_TOKEN")?;Sourcepub fn load_from_dir(&self, dir: impl AsRef<Path>) -> SecretsResult<()>
pub fn load_from_dir(&self, dir: impl AsRef<Path>) -> SecretsResult<()>
Sourcepub fn resolve_env_paths(&self, dir: &Path) -> Vec<PathBuf>
pub fn resolve_env_paths(&self, dir: &Path) -> Vec<PathBuf>
Computes the ordered list of env file paths to load.
This method uses a power-set generation approach: it resolves ENV, OS, ARCH, and USER from the environment, then generates all possible combinations of these values (maintaining canonical order: ENV, OS, ARCH, USER).
Files are loaded in specificity order - more parts means more specific, which means higher precedence.
§Returns
A vector of paths in load order (later paths override earlier ones).
§Examples
With ENV=local, OS=linux, ARCH=amd64, USER=alice, this
generates:
.env.env.local.env.linux.env.amd64.env.alice.env.local.linux.env.local.amd64.env.local.alice.env.linux.amd64.env.linux.alice.env.amd64.alice.env.local.linux.amd64.env.local.linux.alice.env.local.amd64.alice.env.linux.amd64.alice.env.local.linux.amd64.alice.env.pr-<NUMBER>(if applicable)
Sourcepub fn load_env_file(
&self,
path: &Path,
) -> SecretsResult<HashMap<String, String>>
pub fn load_env_file( &self, path: &Path, ) -> SecretsResult<HashMap<String, String>>
Loads and decrypts a single .env file, returning key/value pairs.
§Errors
Returns an error if the file cannot be read or if decryption fails.
Sourcepub fn parse_and_decrypt(
&self,
content: &str,
path: &Path,
) -> SecretsResult<HashMap<String, String>>
pub fn parse_and_decrypt( &self, content: &str, path: &Path, ) -> SecretsResult<HashMap<String, String>>
Parses env file content and decrypts encrypted values.
§Errors
Returns an error if the content cannot be parsed or if decryption fails.
Sourcepub fn get_var(&self, key: &str) -> SecretsResult<String>
pub fn get_var(&self, key: &str) -> SecretsResult<String>
Gets a decrypted environment variable value from the process environment.
If the value is encrypted, it will be automatically decrypted.
§Errors
Returns an error if the variable is not set or if decryption fails.
Sourcepub fn get_var_or(&self, key: &str, default: &str) -> String
pub fn get_var_or(&self, key: &str, default: &str) -> String
Gets a decrypted environment variable, or returns a default if not set.
§Examples
use dotenvage::EnvLoader;
let loader = EnvLoader::new()?;
let port = loader.get_var_or("PORT", "8080");Sourcepub fn get_all_variable_names(&self) -> SecretsResult<Vec<String>>
pub fn get_all_variable_names(&self) -> SecretsResult<Vec<String>>
Gets all variable names from all .env* files that would be loaded.
This method uses the standard file-loading algorithm (via
resolve_env_paths) to determine which
files would be loaded, then collects all unique variable names across
those files.
Files are processed in the same order as load(), but
this method only collects the variable names without loading them into
the environment.
§Returns
A vector of unique variable names found across all .env* files that
would be loaded. If a variable appears in multiple files, it only
appears once in the result.
Note: AGE key variables (DOTENVAGE_AGE_KEY, AGE_KEY,
EKG_AGE_KEY, AGE_KEY_NAME, and any variable ending with
_AGE_KEY_NAME) are filtered out for security reasons.
§Errors
Returns an error if any file cannot be read or parsed. Unlike
load(), this method fails fast on the first error
encountered.
§Examples
use dotenvage::EnvLoader;
let loader = EnvLoader::new()?;
let variable_names = loader.get_all_variable_names()?;
println!("Found {} variables", variable_names.len());
for name in &variable_names {
println!(" - {}", name);
}Sourcepub fn get_all_variable_names_from_dir(
&self,
dir: impl AsRef<Path>,
) -> SecretsResult<Vec<String>>
pub fn get_all_variable_names_from_dir( &self, dir: impl AsRef<Path>, ) -> SecretsResult<Vec<String>>
Gets all variable names from all .env* files in a specific directory.
Like get_all_variable_names(), but
loads from a specific directory instead of the current directory.
Note: AGE key variables are filtered out for security reasons.
§Errors
Returns an error if any file cannot be read or parsed.
§Examples
use dotenvage::EnvLoader;
let loader = EnvLoader::new()?;
let variable_names = loader.get_all_variable_names_from_dir("./config")?;Sourcepub fn dump_to_writer<W: Write>(&self, writer: W) -> SecretsResult<()>
pub fn dump_to_writer<W: Write>(&self, writer: W) -> SecretsResult<()>
Write all merged .env variables in KEY=VALUE format to a writer.
Automatically filters out AGE key variables (DOTENVAGE_AGE_KEY,
AGE_KEY, EKG_AGE_KEY, AGE_KEY_NAME, and any variable ending
with _AGE_KEY_NAME).
This function:
- Loads all
.env*files in standard order - Merges variables (later files override earlier ones)
- Decrypts encrypted values
- Filters out AGE key variables
- Writes in simple KEY=VALUE format (quotes added when needed)
§Errors
Returns an error if:
- Writing to the writer fails
- .env files cannot be loaded
- Decryption fails for any encrypted value
§Examples
use std::io::Cursor;
use dotenvage::EnvLoader;
let loader = EnvLoader::new()?;
let mut buffer = Vec::new();
loader.dump_to_writer(&mut buffer)?;
let output = String::from_utf8(buffer)?;
println!("{}", output);Sourcepub fn dump_to_writer_from_dir<W: Write>(
&self,
dir: impl AsRef<Path>,
writer: W,
) -> SecretsResult<()>
pub fn dump_to_writer_from_dir<W: Write>( &self, dir: impl AsRef<Path>, writer: W, ) -> SecretsResult<()>
Write all merged .env variables in KEY=VALUE format to a writer from a specific directory.
Same as dump_to_writer but loads from a
specific directory.
§Errors
Returns an error if:
- Writing to the writer fails
- .env files cannot be loaded
- Decryption fails for any encrypted value
Sourcepub fn resolve_env() -> String
pub fn resolve_env() -> String
Resolves the <ENV> placeholder for environment-specific file names.
The environment name is resolved in the following order:
DOTENVAGE_ENVenvironment variable (preferred)EKG_ENVenvironment variable (alternative)VERCEL_ENVenvironment variableNODE_ENVenvironment variable- Defaults to
"local"if none of the above are set
The value is always converted to lowercase.
§Examples
use dotenvage::EnvLoader;
// With DOTENVAGE_ENV=production, returns "production"
// Without any env vars set, returns "local"
let env = EnvLoader::resolve_env();
println!("Environment: {}", env);Sourcepub fn resolve_arch() -> Option<String>
pub fn resolve_arch() -> Option<String>
Resolves the <ARCH> placeholder for architecture-specific file names.
The architecture name is resolved from the first available source:
DOTENVAGE_ARCHenvironment variable (preferred)EKG_ARCHenvironment variable (alternative)CARGO_CFG_TARGET_ARCHenvironment variable (Cargo build-time, e.g., “x86_64”, “aarch64”)TARGETenvironment variable (parsed for arch from target triple, e.g., “x86_64-unknown-linux-gnu” → “x86_64”)TARGETARCHenvironment variable (Docker multi-platform builds, e.g., “amd64”, “arm64”)TARGETPLATFORMenvironment variable (Docker, parsed for arch, e.g., “linux/arm64” → “arm64”)RUNNER_ARCHenvironment variable (GitHub Actions, e.g., “X64”, “ARM64”)- Returns
Noneif none are set
§Supported Architectures
The following architectures are recognized and normalized to canonical names:
amd64: AMD64/x86-64 (aliases:x64,x86_64,x86-64)arm64: ARM 64-bit (aliases:aarch64)arm: ARM 32-bit (aliases:armv7,armv7l,armhf)i386: x86 32-bit (aliases:i686,x86)riscv64: RISC-V 64-bit (aliases:riscv64gc)ppc64le: PowerPC 64-bit LE (aliases:powerpc64le)s390x: IBM System/390
Unknown values are passed through as-is (lowercase) for custom use cases.
§Examples
use dotenvage::EnvLoader;
// With TARGETARCH=arm64 (Docker build), resolves to Some("arm64")
// With RUNNER_ARCH=X64 (GitHub Actions), resolves to Some("amd64")
if let Some(arch) = EnvLoader::resolve_arch() {
println!("Architecture: {}", arch);
}Sourcepub fn resolve_os() -> Option<String>
pub fn resolve_os() -> Option<String>
Resolves the <OS> placeholder for OS-specific file names.
The operating system is resolved from the first available source:
DOTENVAGE_OSenvironment variable (preferred)EKG_OSenvironment variable (alternative)CARGO_CFG_TARGET_OSenvironment variable (Cargo build-time, e.g., “linux”, “macos”, “windows”)TARGETenvironment variable (parsed from target triple, e.g., “x86_64-unknown-linux-gnu” → “linux”)RUNNER_OSenvironment variable (GitHub Actions, e.g., “Linux”, “macOS”, “Windows”)std::env::consts::OS(runtime detection)
§Supported Operating Systems
linux: Linuxmacos: macOS (aliases:darwin,osx)windows: Windows (aliases:win32,win)freebsd: FreeBSDopenbsd: OpenBSDnetbsd: NetBSDandroid: Androidios: iOS
§Examples
use dotenvage::EnvLoader;
// Typically auto-detects from runtime or build-time
if let Some(os) = EnvLoader::resolve_os() {
println!("OS: {}", os);
}Sourcepub fn resolve_user() -> Option<String>
pub fn resolve_user() -> Option<String>
Resolves the <USER> placeholder for user-specific file names.
The username is resolved from the first available environment variable:
DOTENVAGE_USER(preferred)EKG_USERGITHUB_ACTOR(GitHub Actions)GITHUB_TRIGGERING_ACTOR(GitHub Actions)GITHUB_REPOSITORY_OWNER(GitHub Actions)USER(Unix standard)USERNAME(Windows standard)- Returns
Noneif none are set
The value is always converted to lowercase.
§Examples
use dotenvage::EnvLoader;
// Typically resolves from $USER on Unix or %USERNAME% on Windows
if let Some(user) = EnvLoader::resolve_user() {
println!("User: {}", user);
}Sourcepub fn resolve_pr_number() -> Option<String>
pub fn resolve_pr_number() -> Option<String>
Resolves the <PR_NUMBER> placeholder for PR-specific file names.
The PR number is only resolved in GitHub Actions pull request contexts:
- Checks that
GITHUB_EVENT_NAMEstarts with"pull_request" - Reads from
PR_NUMBERenvironment variable - Falls back to parsing
GITHUB_REF(e.g.,refs/pull/123/merge) - Returns
Noneif not in a PR context
§Examples
use dotenvage::EnvLoader;
// In GitHub Actions PR, resolves to Some("123")
// Outside of PR context, returns None
if let Some(pr_number) = EnvLoader::resolve_pr_number() {
println!("PR Number: {}", pr_number);
}