# Nvir – Elixir environment variables made simple
[](https://hex.pm/packages/nvir)
[](https://github.com/lud/nvir/actions/workflows/elixir.yaml)
[](https://hex.pm/packages/nvir)
Nvir is a powerful environment variable loader for Elixir that provides:
* Simple loading of dotenv files with support for inheritance and interpolation.
* Optional loading of dotenv files depending on the `:test`, `:dev` environment, CI environment, operating system, and custom conditions.
* Strong validation and type casting of environment variables.
* Support for custom casters and variables transformers.
This library is inspired from
[Dotenvy](https://github.com/fireproofsocks/dotenvy) and provides a similar
experience.
## Installation
As usual, pull the library from your `mix.exs` file.
```elixir
def deps do
[
{:nvir, "~> 0.12"},
]
end
```
## Basic Usage
You will generally use Nvir from your `config/runtime.exs` file.
* Import the module functions, and call `dotenv!/1` to load your files.
* Use `env!/2` to require a variable and validate it.
* Use `env!/3` to provide a default value.
Note that you do not have to call `dotenv!/1` to use the `env` functions. You can
use this library for validation only.
```elixir
# runtime.exs
import Nvir
dotenv!([".env", ".env.#{config_env()}"])
config :my_app, MyAppWeb.Endpoint,
secret_key_base: env!("SECRET_KEY_BASE", :string!),
url: [host: env!("HOST", :string!), port: 443, scheme: "https"],
http: [ip: {0, 0, 0, 0}, port: env!("PORT", :integer!, 4000)]
config :my_app, MyApp.Repo,
username: env!("DB_USERNAME", :string!),
password: env!("DB_PASSWORD", :string!),
database: env!("DB_DATABASE", :string!),
hostname: env!("DB_HOSTNAME", :string!),
port: env!("DB_PORT", :integer!, 5432)
```
This is most of what you need to know to start using this library. Below is an
advanced guide that covers all configuration and usage options.
## Documentation
Nvir provides advanced capabilities to work with your dotenv files in different
scenarios. This is all described in the [documentation on
hexdocs.pm](https://hexdocs.pm/nvir/readme.html).
## Interoperability
This library is built around the native Elixir support for environment variables:
* The `dotenv!/1` function will patch the actual runtime environment. You do not
have to use `env!/2` or `env!/3` to fetch variables loaded by `dotenv!/1`.
Using `System.fetch_env!/1`, `System.get_env/2`, etc. is perfectly fine.
* The `env!` functions are helpers built around `System.fetch_env!/1` with
support for casting. They do not require `dotenv!/1` to have been called
beforehand and are safe to call wherever you would call `System.fetch_env!/1`
instead.
You may also use another library like
[Enviable](https://github.com/halostatue/enviable) that provides more advanced
casters:
```elixir
import Nvir
import Enviable
dotenv!(".env")
secret_key = fetch_env_as_pem!("SECRET_KEY")
dns_config = fetch_env_as_json!("DNS_CONFIG_JSON")
```
## Difference with Dotenvy
Dotenvy loads the dotenv files in the process dictionary of the process
executing `runtime.exs`. The defined variables are meant to be _part of_ your
application configuration.
The `System.fetch_env/1` function and other variants
cannot see those variables unless you tells the Dotenvy loader to actually patch
the environment.
Nvir philosophy is that the dotenv files are only patches for the environment
_around_ the application, and so the application should always be able to use
those variables from anywhere with `System.fetch_env/1` or `Nvir.env!/2`.
So Nvir will _always_ patch the system environment. The development environment
and production environment will use the same code paths. This also works well
with libraries that expect some environment variables to be defined.