Search code examples
rustrust-cargo

Rust Environment Variables without dotenv


I would like to load a set of Rust environment variables depending on my build environment (in my case, dev, uat and live). Ideally, I would like to specify the environment file ay build time.

Looking at online docs, the advice seems to be to use the dotenv crate. However, that crate is a v0 version, and does not appear to be maintained. Is there an idiomatic way to do this without using an old library?


Solution

  • Without external libraries you can use cargo configuration env property and have something like:

    Options A: Single configuration

    • my-project/.cargo/config.toml
    [env]
    MY_ENV="dev"
    MY_DEV_HOST="localhost"
    MY_PROD_HOST="prod.example.com"
    
    • my-project/src/main.rs
    fn main() -> Result<(), Box<dyn Error>> {
        let my_env = env::var("MY_ENV")
            .unwrap_or("dev".to_string())
            .to_uppercase();
        let my_host = env::var(format!("MY_{}_HOST", my_env))?;
    
       // Do something
     
       Ok(())
    }
    

    then you run it with cargo run and it will take the default dev values, with MY_ENV="prod" cargo run will take prod values.

    Option B: Multiple configuration

    Another options if is a configuration per environment and use --config cargo command line option, for example:

    • my-project/stg-config.toml
    [env]
    MY_ENV="stg"
    MY_HOST="stg.example.com"
    
    • my-project/prod-config.toml
    [env]
    MY_ENV="prod"
    MY_HOST="prod.example.com"
    

    and then cargo run --config stg-config.toml, if you have .cargo/config.toml (with default env values) it will merge those.