A well-maintained fork of the dotenv crate.
This crate is the suggested alternative for dotenv
in security advisory RUSTSEC-2021-0141.
This library loads environment variables from an env file.
dotenvy
crate - A well-maintained fork of thedotenv
crate.dotenvy_macro
crate - A macro for compile-time .env inspection. This is a fork ofdotenv_codegen
.dotenvy-macros
crate - A runtime macro library containg theload
attribute macro.dotenvy
binary that loads an env file before executing a specified command.
An env file consists of keypairs like so:
.env
HOST=foo
PORT=3000
They are commonly named .env, .env.dev, .env.prod, etc., but any name can be used.
Variables can span multiple lines and also be substituted. For an explanation on substituion rules, please refer to the .env-substitution example file.
This crate contains two APIs, a non-environment-modifying API and an environment-modifying API.
Modifying calls std::env::set_var
internally,
which is marked unsafe in the Rust 2024 edition. For this reason, we recommend using the non-modifying API unless
necesary.
// from a file
let loader1 = EnvLoader::with_path("./.env").sequence(EnvSequence::InputThenEnv);
let loader2 = EnvLoader::new(); // same as loader1
// from a reader
let s = "HOST=foo\nPORT=3000";
let str_loader = EnvLoader::with_reader(Cursor::new(s));
// will load from the env file, override exiting values in the program environment
let overriding_loader = EnvLoader::new().sequence(EnvSequence::EnvThenInput);
Load constuction is infallible. I/O is derred until load
or load_and_modify
is called.
This is to allow support configurations such as dev/prod and
optional loading.
use dotenvy::{EnvLoader};
use std::{error, env};
fn main() -> Result<(), Box<dyn error::Error>> {
let env_map = EnvLoader::new().load()?;
println!("HOST={}", env_map.var("HOST")?);
Ok(())
}
Sometimes, you have to modify the environment. You might spawn a child process or rely
on std::env::var
to read variables.
use dotenvy::{EnvLoader};
use std::{error, env};
fn main() -> Result<(), Box<dyn error::Error>> {
let loader = EnvLoader::new();
let env_map = unsafe { loader.load_and_modify() }?;
println!("HOST={}", env_map.var("HOST")?);
println!("HOST={}", std::env::var("HOST")?);
Ok(())
}
If using async, you must modify the environment before starting the async runtime.
The load
attribute macro can be used to do this. To use it, enable the macros
feature for the dotenvy
crate.
#[dotenvy::load] // will call `load_and_modify` before the async runtime is started
#[tokio::main]
async fn main() -> Result<(), Box<dyn error::Error>> {
println!("HOST={}", env::var("HOST")?);
Ok(())
}
dotenvy::load
must be placed before tokio::main
.
A non-macro example is here.
The dotenv!
macro provided by dotenvy_macro
crate can be used.
We aim to support the latest 8 rustc versions - approximately 1 year. Increasing MSRV is not considered a semver-breaking change.
The original dotenv crate has not been updated since June 26, 2020. Attempts to reach the authors and present maintainer were not successful (dotenv-rs/dotenv #74).
This fork intends to serve as the development home for the dotenv implementation in Rust.
This repo adds:
- non-modifying API
- configurable
EnvLoader
- optional loading, ergonomic dev/prod handling
- reader support, such as reading from any reader that is
io::Read
- more informative
Error
type, containing the file path and variable name load
attribute macro- multiline support
- more examples and docs
For a full list of changes, refer to the changelog.
Thank you very much for considering to contribute to this project! See CONTRIBUTING.md for details.
Note: Before you take the time to open a pull request, please open an issue first.
Legend has it that the Lost Maintainer will return, merging changes from dotenvy
into dotenv
with such thrust that all Cargo.toml
s will lose one keystroke. Only then shall the Rust dotenv crateverse be united in true harmony.
Until then, this repo dutifully carries on the dotenv torch. It is actively maintained.