Envlet

Pull your Envlet environment at runtime. The host platform holds one secret, an Envlet token, and your app loads everything else at boot.

Add envlet to your dependencies:

def deps do
[
{:envlet, "~> 0.1.0"}
]
end

Envlet requires Elixir 1.17 or later and Erlang/OTP 25 or later.

Load values into the process environment:

Envlet.inject!()

inject!/0 fetches every value the token identity can read and sets the process environment. Values already set by the host are not overwritten. Pass override: true to replace host values with Envlet values.

Envlet.inject!(override: true)

Fetch all values or one value without changing the process environment:

values = Envlet.load!()
stripe_key = Envlet.get!("STRIPE_KEY")

The non-bang functions return tagged tuples:

case Envlet.get("STRIPE_KEY") do
{:ok, value} -> value
{:error, %Envlet.Error{code: code, status: status}} -> {code, status}
end

Configuration comes from ENVLET_TOKEN or the :token option. The API URL comes from ENVLET_API_URL, then defaults to https://api.envlet.dev. Use the :api_url option to set it for one call. Network errors and 5xx responses make at most three attempts by default. Pass retry: false to make one attempt.

Envlet.load!(
token: System.fetch_env!("ENVLET_TOKEN"),
api_url: "https://api.envlet.dev",
retry: true
)

Requests never return cached, stale, or partial values. A missing token returns config_missing. A 401 or 403 response keeps the API error code, including token_expired and unauthorized. A withheld or absent value returns not_found with status 404. Network failures return network_error. Injection failures return environment_error without leaving partial changes.

For releases, add Envlet.ConfigProvider so values enter the process environment before applications start:

def project do
[
releases: [
my_app: [
config_providers: [{Envlet.ConfigProvider, []}]
]
]
]
end

The provider accepts the same options as Envlet.inject!/1, including override: true.