Dot Your Environment

Env::Dot

In the category of “scratching my itch”.

Background

An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc). The Twelve-Factor App

Storing the often changing parts of configuration in environment variables is one of the principles of The Twelve-Factor App.

From this principle follows the need to store those environment variables and their values in an easily accessible way. Hence, every developer maintains his or her own project specific .env files next to the project files in the same directory where they are used, for instance, when running locally or testing locally.

Yet Another Dotenv Solution

As if we didn’t have these enough already…

What is different with this one, except the name Env::Dot?

Flexibility in input

  • .env files come in two formats: Shell compatible and Docker combatible. Env::Dot supports both.
  • If no .env file is present, then do nothing.
  • If your .env file is located in another path, not the current working directory, you can use the environment variable DOTENV_FILEPATHS to tell where your dotenv file is located. You can specify several file paths; just separate them by :. Dot::Env will load all the files in the order you specify them.

Flexibility in output

  • Just use Env::Dot in your program and your %ENV will grow with the variables defined in .env file.
  • There is also a command line executable, envdot, to read the .env file and write out commands to create the environment variables.
  • Command envdot can write the env vars in sh (sh/Bash/Zsh), csh (C shell/tcsh) and fish (Fish) shell formats.
  • Command envdot will by default also export variables but you can prevent this if you don’t want the variables to be present in subshells and programs. This would make the variables only local to your current shell.

Existing Environment Takes Precedence

Existing environment variables always take precedence to dotenv variables!

A dotenv variable (variable from a file) does not overwrite an existing environment variable. This is by design because a dotenv file is to augment the environment, not to replace it.

This means that you can override a variable in .env file by creating its counterpart in the environment. For instance:

unset VAR
echo "VAR='Good value'" >> .env
perl -e 'use Env::Dot; print "VAR:$ENV{VAR}\n";'
# VAR:Good value
VAR='Better value'; export VAR
perl -e 'use Env::Dot; print "VAR:$ENV{VAR}\n";'
# VAR:Better value

DotEnv File Meta Commands

The file: commands affect all rows following its use.

The var: commands affect only the subsequent variable definition. If there is another envdot command, the second overwrites the first and default values are applied again.

file:type

Changes how Env::Dot reads lines below from this commands. Default is:

# envdot (file:type=shell)
VAR="value"

Other possible value of file:type is plain. Docker is using these kinds of .env files. Variable name is followed by = and value is the rest of the row before linefeed.

# envdot (file:type=plain)
VAR=My var value

var:allow_interpolate

By default, when writing variable definitions for the shell, every variable is treated as static and surrounded with single quotation marks (‘) in Unix shell which means shell will read the variable content as is. By setting this to 1 or true, you allow shell to interpolate. This meta command is only useful when running envdot command to create variable definitions for eval command to read.

# envdot (var:allow_interpolate)
DYNAMIC_VAR="$(pwd)/${ANOTHER_VAR}"

Usage

use Env::Dot;
print $ENV{'VAR_DEFINED_IN_DOTENV_FILE'};

envdot

envdot is a shell command which translates the dotenv files into shell commands. The file .env is of course the default input.

envdot
# VAR='Good value'; export VAR

It has the following parameters:

—export, —no-export

Write commands to set variables for local shell or for exporting them. You usually want to export the variables to all subsequent programs and subshells, i.e. make them into environment variables.

Default: export

-s, —shell

Which shell (family) are you using? Supported: sh, csh, fish.

-e, —dotenv

Path to .env file.

Default: current directory .env

Installation

If you need to use the envdot command in a restricted environment, such as a docker image build, there is a FatPacked executable ready. Usable when using CPAN is overkill.

curl -LSs -o envdot https://raw.githubusercontent.com/mikkoi/env-dot/master/envdot.self-contained
chmod +x ./envdot

Or you can do this in a Dockerfile:

RUN curl -LSs -o /usr/local/bin/envdot \
    https://raw.githubusercontent.com/mikkoi/env-dot/master/envdot.self-contained
RUN chmod +x /usr/local/bin/envdot

There is no extra dependencies outside Perl’s standard distribution, so envdot is as lean as it can be. And Perl, of course, is present in every more or less standard Linux distribution.

Leave a comment

About Mikko Koivunalho

user-pic Perl Programmer for fun and office. CPAN modules and command line tools.