If you’re anything like me, you’ve found that configuring your application using environment variables works really well because it forces you to build an environment-agnostic system that can be deployed to anywhere by adjusting a set of variables that are read by your application at run-time.
This strategy is in-line with 12-factor apps and also works very well with containerized applications.
If you’re anything like me you’ve also found that once you have a local development environment, a CI/CD platform, development, staging, and production environments, and other developers on a team, propagating environmental changes and keeping your configurations sane is a headache.
I released a product today called Environr that aims to solve this and also adds some functional improvements on top.
Over the past few years I’ve seen good and very bad practices in this area:
- Secret keys accidentally being committed to an env/prod.rb file
- URLs being hardcoded into conf/django.py limiting deployments to a single domain name
- Production environment variables set in Elastic Beanstalk environments without any way to prevent accidental changes
- Copying and pasting an .env file back and forth through Slack
Fortunately some developers solve this challenge by using services like Consul, etcd, and Kubernetes ConfigMaps — and while this is more complex than hardcoding configuration values into code, these services provide reliable, distributed, configuration stores for critical applications.
So where does Environr fit into this? Well, there’s still the headache of manually updating environment variables across all of your different platforms anytime a change is made. Plus, managing a distributed key/value store in your own infrastructure doesn’t always mesh well with every product, especially for projects hosted on a platform like Elastic Beanstalk where every container instance must run the same containers. In addition, not all developers are running those services on their local machines during testing, which again thwarts the efforts of having consistent deployments.
With Environr, you authenticate yourself with GitHub, create API keys/secrets for whomever needs to access your configurations, download the CLI tool, and then either import your existing configurations or create them in the console. Then, the CLI tool gets access to environment variables that are all managed in one central location. Update the config in one place and it propagates to where it needs to be.
The easiest way to configure the CLI on your local machine is to run environr-cli configure
. This will prompt you to enter your API key and secret to avoid it being part of your shell’s history, and then an optional “profile”. The configuration process writes a YAML file to ~/.environr/credentials
so you can manage more than one account by giving the --profile
flag to environr-cli
.
The CLI can also be configured by setting two environment variables ENVIRONR_API_KEY
and ENVIRONR_API_SECRET
which effectively bootstraps your environment to then be managed by environr-cli
. This works best in CI platforms like CircleCI and AWS CodeBuild and services like Elastic Beanstalk.
Once configured, the current CLI commands are just environr-cli import
and environr-cli env,
the former for importing or changing existing configurations and the latter for injecting a configuration into the shell or writing it to a file for use with Docker’s --env-file
flag.
There will be a follow-up post for more use case scenarios and a better walkthrough, but until then, feel free to checkout the documentation.
p.s. Environr also comes with a cool “Lock” feature that lets you lock a configuration so no one can accidentally change your production environment variables.
Happy Configuring!