Open-source project
bkeepers/dotenv avatar
bkeepers/dotenv

bkeepers/dotenv: loading .env files into ENV in Ruby

A Ruby gem to load environment variables from `.env`.

6,764 stars516 forksRubyMIT

At a glance

What is it?
The Ruby gem that reads .env files into ENV at boot, with Rails-specific file precedence and test-time restoration. Its scope is deliberately narrow: development and test, not production configuration management.
Who is it for?
Adopt bkeepers/dotenv if you run a Ruby or Rails app and want .env files loaded into ENV during development and test, with the Rails file precedence table and the autorestore behaviour available out of the box. Do not adopt it as a production secrets system: the README frames it as a development shim, and nothing in it describes key management, rotation or an encrypted store.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 99 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What bkeepers/dotenv actually solves, and for whom

Setting environment variables by hand on a development machine or a CI runner that hosts several projects is awkward. The README puts it plainly: it is "not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run." dotenv is the shim that reads a .env file and writes those pairs into ENV when the application bootstraps.

The intended audience is Ruby developers, and specifically Rails developers. The README describes the gem as a "Shim to load environment variables from `.env` into `ENV` in *development*", and the installation line places it in the development and test groups. That is the whole contract. If you are looking for a secrets manager, a per-environment config server, or something that runs in production, this is not that tool, and the README never claims otherwise.

How the loader decides which value wins

The mechanism is a merge into the process environment, and the ordering rules are the part worth reading closely. `Dotenv.load` looks for `.env` in the current working directory by default. You can pass several files, and they are loaded in order. The README states the rule directly: "The first value set for a variable will win." Existing environment variables are not overwritten unless you pass `overwrite: true`.

That default matters more than it looks. A variable already exported in your shell survives a `Dotenv.load` call, so a developer can override a checked-in default from the terminal without editing files. The cost is the inverse case: when a stale exported variable is the reason your app is misbehaving, dotenv will not correct it, and you have to unset it yourself.

In Rails the file set is not a single file. The README's precedence table lists `.env.<environment>.local` at highest priority, then `.env.local` (except in test, where it is marked N/A), then `.env.<environment>`, and `.env` last. All of them are read during the `before_configuration` callback, which fires when the `Application` constant is defined in `config/application.rb`. If you need earlier loading, the README shows unshifting a filename onto `Dotenv::Rails.files` above the `class Application < Rails::Application` line.

Installing dotenv and loading a first .env file

Add the gem to the Gemfile in the development and test groups and run Bundler. The README gives this line verbatim:

ruby
gem 'dotenv', groups: [:development, :test]

After `bundle install`, create a `.env` file in the project root. The README's example uses two variables:

shell
S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE

In a plain Ruby or Sinatra app, require the load shim as early as possible in the bootstrap. The README shows both forms:

ruby
require 'dotenv/load'

# or
require 'dotenv'
Dotenv.load

Once loaded, the values are ordinary entries in `ENV`, so application code reads them the usual way. The README's example assigns `ENV['S3_BUCKET']` to a configuration attribute. In Rails you do not call anything: the README states that dotenv loads automatically when the app boots.

There is also a command line entry point. The `dotenv` executable loads `.env` before launching a program, and the `-f` flag takes a comma-separated list of files ordered from most to least important. Every file in that list must exist unless you add the ignore flag:

console
$ dotenv -i -f ".env.local,.env" ./script.rb

According to the README, `-i` (or `--ignore`) skips missing files, so the command above still runs when `.env.local` is absent. The README also notes there must be a space between `-f` and its value.

Autorestore, and why tests stop leaking ENV

Since version 3.0, a Rails app restores `ENV` after each test, so a test that mutates an environment variable does not contaminate the next one. The README says this works with both `ActiveSupport::TestCase` and Rspec. Outside Rails you get the same behaviour by requiring `dotenv/autorestore` in the test suite.

Two conditions switch it off. Setting `config.dotenv.autorestore = false` in `config/application.rb` or `config/environments/test.rb` disables it, and it is disabled by default when the app uses climate_control or ice_age. That second rule is sensible, since two libraries restoring the same global hash would fight, but it is also easy to miss: if you add climate_control to an existing suite, autorestore quietly stops, and any test that relied on it needs a second look. The manual equivalents are `Dotenv.save`, `Dotenv.restore` and `Dotenv.modify(hash) { ... }`, which the README links to the API docs.

Where dotenv is the wrong tool

The README's own framing is the limitation: this is a development shim. Nothing in it describes an encrypted store, a key management service, audit logging, or credential rotation. If your requirement is that secrets never sit in plaintext on a disk, dotenv does not address it, and the README's answer to committing `.env` is a hedged "Maybe" in the precedence table.

There are sharper edges. The `-f` flag requires every listed file to exist unless you pass `-i`, so a typo in a filename fails the command rather than degrading. Multi-line values must be wrapped in double quotes, and the old behaviour of expanding `\n` inside quoted strings is deprecated; the README says to set `DOTENV_LINEBREAK_MODE=legacy` before any variables containing `\n` if you still depend on it. Load order is another footgun: gems that read environment variables at require time need dotenv listed earlier in the Gemfile with `require: 'dotenv/load'`, because a gem loaded first will see an empty `ENV`.

Alternatives, and the difference that matters

The nearest Ruby alternatives are Rails credentials and the `ENV` configuration that Rails already provides. Rails credentials store values encrypted in a single file committed to the repository and decrypt them with a key held outside it. dotenv does the opposite: plaintext files, some of them gitignored, resolved at boot with a precedence order. The trade is legibility for secrecy. A `.env` file is easy to read, diff and hand to a new developer; a credentials file is not readable without the key.

Environment-variable managers that inject values at process start, or platform configuration panels that set variables for a deployed service, occupy a different position again: they supply values to production, which dotenv does not claim to do. The honest comparison is that dotenv solves the local and CI case cheaply and stops there, and the README is consistent about that boundary.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-06-22. The most recent release listed is v3.2.0 from 2025-12-03, preceded by v3.1.8 in April 2025 and v3.1.7 in December 2024. Releases are infrequent, which fits a gem whose surface is a file parser and a handful of load hooks.

The upgrade cost concentrates in the 3.0 line. Autorestore arrived in 3.0, and the `\n` expansion change is marked deprecated rather than removed, so a codebase still relying on the old linebreak behaviour needs `DOTENV_LINEBREAK_MODE=legacy` set before the affected variables. The gem is MIT licensed, which permits commercial use and modification; the repository carries a LICENSE file. That is a description of the licence, not legal advice, and anyone redistributing the gem should read the licence text themselves.

Editorial conclusion

Adopt bkeepers/dotenv if you run a Ruby or Rails app and want .env files loaded into ENV during development and test, with the Rails file precedence table and the autorestore behaviour available out of the box. Do not adopt it as a production secrets system: the README frames it as a development shim, and nothing in it describes key management, rotation or an encrypted store. Before committing, verify which files your Rails environment actually loads, confirm whether AUTORESTORE or climate_control has disabled autorestore, and check that your load order in the Gemfile puts dotenv before any gem that reads ENV at require time.

Frequently asked questions

What is bkeepers/dotenv used for?

It loads variables from a .env file into ENV when a Ruby application bootstraps, so configuration such as database handles or API credentials does not have to be set by hand on every development machine or CI runner. The README describes it as a development shim.

Why don't we push .env files?

The README does not give a blanket rule; its precedence table marks .env as "Maybe" for gitignoring, while the environment-specific .local files are marked Yes. The decision rests on whether the values in your .env are secrets, which the README leaves to you.

How do I use a .env file?

Put the variable assignments in a .env file in the project root, then require 'dotenv/load' or call Dotenv.load early in the bootstrap. In a Rails app the README states the files load automatically when the app boots.

How do I install dotenv?

Add gem 'dotenv', groups: [:development, :test] to the Gemfile and run bundle install. The README gives that gem line as the installation step.

Is dotenv still needed?

The README does not discuss the question. It presents dotenv as a shim for loading .env files into ENV during development and test, and does not describe any replacement or deprecation of that role.

Official sources

  1. bkeepers/dotenv on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bkeepers-dotenv.svg)](https://hysenlabs.com/projects/bkeepers-dotenv)