Skip to content

Instantly share code, notes, and snippets.

@bkeepers
Last active Dec 22, 2015
Embed
What would you like to do?
My micro-talk to the Grand Rapids Ruby Group on separating code and configuration.
/$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$ /$$$$$$
/$$__ $$ /$$__ $$| $$$ | $$| $$_____/|_ $$_/ /$$__ $$
| $$ \__/| $$ \ $$| $$$$| $$| $$ | $$ | $$ \__/
| $$ | $$ | $$| $$ $$ $$| $$$$$ | $$ | $$ /$$$$
| $$ | $$ | $$| $$ $$$$| $$__/ | $$ | $$|_ $$
| $$ $$| $$ | $$| $$\ $$$| $$ | $$ | $$ \ $$
| $$$$$$/| $$$$$$/| $$ \ $$| $$ /$$$$$$| $$$$$$/
\______/ \______/ |__/ \__/|__/ |______/ \______/
/$$ /$$
|__/ | $$
/$$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$
| $$ /$$_____/ | $$__ $$ /$$__ $$|_ $$_/
| $$| $$$$$$ | $$ \ $$| $$ \ $$ | $$
| $$ \____ $$ | $$ | $$| $$ | $$ | $$ /$$
| $$ /$$$$$$$/ | $$ | $$| $$$$$$/ | $$$$/
|__/|_______/ |__/ |__/ \______/ \___/
/$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$$$
/$$__ $$ /$$__ $$| $$__ $$| $$_____/
| $$ \__/| $$ \ $$| $$ \ $$| $$
| $$ | $$ | $$| $$ | $$| $$$$$
| $$ | $$ | $$| $$ | $$| $$__/
| $$ $$| $$ | $$| $$ | $$| $$
| $$$$$$/| $$$$$$/| $$$$$$$/| $$$$$$$$
\______/ \______/ |_______/ |________/
Presented with ♥ by @bkeepers
###############################################################################
# Config should be separate from code
###############################################################################
Environments don't scale cleanly:
development, staging, production,
qa, labs, joes-laptop, joes-staging, joes-ec2-dev
Config varies substantially across deploys, code does not.
The Twelve-Factor App
http://12factor.net/config
The twelve-factor app stores config in environment variables
⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ Litmus Test ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛
Can the codebase be made open source at any moment,
without compromising any credentials?
⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛ ⚛
☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼
☼ What is NOT configuration?
☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼☼
* internal application config (conig/routes.rb)
Things that don't change between deployments.
☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂
☂ What is configuration?
☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂☁☂
1. Resource handles to data stores (database, memcached)
2. Credentials to external services (Amazon S3 or Twitter)
3. Per-deploy values such as the canonical hostname for the deploy
Anything that needs changed to deploy a new instance of the application
_ _ _
| | ( ) | _
__| | ___ _ __ |/| |_ (_)
/ _` |/ _ \| '_ \ | __|
| (_| | (_) | | | | | |_ _
\__,_|\___/|_| |_| \__| (_)
<% if Rails.env.production? %>
Google Analytics code with hard-coded ID
<% end %>
_
| | _
__| | ___ (_)
/ _` |/ _ \
| (_| | (_) | _
\__,_|\___/ (_)
<% if ENV['GOOGLE_ANALYTICS_ID'] %>
Google Analytics code with dynamic <%= ENV['GOOGLE_ANALYTICS_ID'] %>
<% end %>
# config/initializers/secret_token.rb
Rails.application.config.secret_key_base = ENV['SECRET_KEY_BASE']
# config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => ENV['S3_ACCESS_KEY'],
:aws_secret_access_key => ENV['S3_SECRET_ACCESS_KEY']
}
config.fog_directory = ENV['S3_BUCKET']
end
,.--.
// \
\\ /
`'--'
,.--.
// \
\\ /
`'--'
,.--.
// \
\\ /
`'--'
,.--.
// \
\\ /
`'--'
,.--.
// \
\\ /
`'--'
,.--.
// \
\\ /
`'--'
888 d8
e88~\888 e88~-_ _d88__ e88~~8e 888-~88e Y88b /
d888 888 d888 i 888 d888 88b 888 888 Y88b /
8888 888 8888 | 888 8888__888 888 888 Y88b/
Y888 888 Y888 ' 888 Y888 , 888 888 Y8/
"88_/888 "88_-~ "88_/ "88___/ 888 888 Y
https://github.com/bkeepers/dotenv
gem 'dotenv-rails'
###############################################################################
# Example .env file from the project I work on every day
###############################################################################
APP_HOST=talks.dev
APP_PROTOCOL=http
FAILBOT_BACKEND=memory
GITHUB_APP_KEY=[redacted]
GITHUB_APP_SECRET=[redacted]
INSTRUMENTAL_API_KEY=[redacted]
MAILGUN_DOMAIN=localhost
S3_ACCESS_KEY=[redacted]
S3_SECRET_ACCESS_KEY=[redacted]
S3_BUCKET=github-talks-dev
ZENCODER_API_KEY=[redacted]
# Tell Resque to properly handle unix signals
TERM_CHILD=1
QUEUE=users,mailer,talks,search,*
# Use local file uploads instead of S3
# S3_UPLOADS=false
# Use github.dev instead of github.com
# LOCAL_GITHUB=true
# These variables should also be defined in production
# IMAGE_PROXY_URL
# GAUGES_ID
# GOOGLE_ANALYTICS_ID
###############################################################################
_ _ _ ___
| | | | | ||__ \
__| | ___ _ __ | | ___ _ _ _ __ ___ ___ _ __ | |_ ) |
/ _` |/ _ \ '_ \| |/ _ \| | | | '_ ` _ \ / _ \ '_ \| __|/ /
| (_| | __/ |_) | | (_) | |_| | | | | | | __/ | | | |_|_|
\__,_|\___| .__/|_|\___/ \__, |_| |_| |_|\___|_| |_|\__(_)
| | __/ |
|_| |___/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment