SmartCredentials
SmartCredentials intelligently manages your Rails application credentials by allowing environment variables to override Rails encrypted credentials with automatic fallback. Perfect for development, staging, and production environments where you want the flexibility of ENV variables without losing the security of encrypted credentials.
Features
- Automatic Fallback - ENV variables take priority, falling back to Rails credentials
- Nested Credentials - Full support for deeply nested credential structures
-
Familiar Interface - Works just like
Rails.application.credentials - Multiple Access Patterns - Method chaining, hash-style, and dig support
Installation
Add this line to your application's Gemfile:
gem "smart_credentials"Usage
Basic Usage
Instead of using Rails.application.credentials.api_key, use:
SmartCredentials.api_keyThis will:
- First check for
ENV["API_KEY"] - If not found, fall back to
Rails.application.credentials.api_key
Nested Credentials
For nested credentials like Rails.application.credentials.aws.access_key_id:
SmartCredentials.aws.access_key_idThis will:
- First check for
ENV["AWS_ACCESS_KEY_ID"] - If not found, fall back to
Rails.application.credentials.aws.access_key_id
Hash-Style Access
You can also use hash-style access:
SmartCredentials[:api_key]
SmartCredentials[:aws][:access_key_id]
# or mix and match
SmartCredentials.aws[:access_key_id]
SmartCredentials[:aws].access_key_idDig Method
For deeply nested values:
SmartCredentials.dig(:aws, :s3, :bucket_name)
# Checks ENV["AWS_S3_BUCKET_NAME"]
# Falls back to Rails.application.credentials.aws.s3.bucket_nameConfiguration
SmartCredentials works without any configuration, but you can customize its behavior.
Using an Initializer
Create config/initializers/smart_credentials.rb:
# Block style
SmartCredentials::Config.setup do |config|
config.env_prefix = "MYAPP"
config.env_separator = "__"
end
# or direct assignment style
SmartCredentials::Config.env_prefix = "MYAPP"
SmartCredentials::Config.env_separator = "__"Configuration Options
env_prefix
Add a prefix to all ENV variable lookups:
SmartCredentials::Config.env_prefix = "MYAPP"
# Now looks for ENV["MYAPP_API_KEY"] instead of ENV["API_KEY"]
SmartCredentials.api_keyDefault: nil (no prefix)
env_separator
Change the separator used for nested keys:
SmartCredentials::Config.env_separator = "__"
# Now looks for ENV["AWS__ACCESS_KEY_ID"] instead of ENV["AWS_ACCESS_KEY_ID"]
SmartCredentials.aws.access_key_id
# Also affects prefix separator:
SmartCredentials::Config.env_prefix = "MYAPP"
# Now looks for ENV["MYAPP__AWS__ACCESS_KEY_ID"] instead of ENV["MYAPP_AWS_ACCESS_KEY_ID"]
SmartCredentials.aws.access_key_idDefault: "_" (underscore)
Real-World Examples
Example credentials.yml.enc
production:
api_key: "production_key_from_credentials"
secret_key_base: "long_secret_string"
aws:
access_key_id: "AKIAIOSFODNN7EXAMPLE"
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
region: "us-east-1"
s3:
bucket_name: "my-app-production"
stripe:
publishable_key: "pk_live_123"
secret_key: "sk_live_456"
database:
host: "db.example.com"
username: "app_user"
password: "secure_password"AWS Configuration
# config/initializers/aws.rb
Aws.config.update(
credentials: Aws::Credentials.new(
SmartCredentials.aws.access_key_id,
SmartCredentials.aws.secret_access_key
),
region: SmartCredentials.aws.region
)Stripe Configuration
# config/initializers/stripe.rb
Stripe.api_key = SmartCredentials.stripe.secret_keyDatabase Configuration
# config/database.yml
production:
adapter: postgresql
host: <%= SmartCredentials.database.host %>
username: <%= SmartCredentials.database.username %>
password: <%= SmartCredentials.database.password %>
database: myapp_productionIn Your Application Code
# app/services/api_client.rb
class ApiClient
def initialize
@api_key = SmartCredentials.api_key
@base_url = SmartCredentials.api.base_url
end
def call
HTTParty.get(@base_url, headers: { "Authorization" => "Bearer #{@api_key}" })
end
endUse Cases
Development
Keep encrypted credentials for your team while allowing individual developers to override specific values:
# Developer can use their own AWS credentials without touching credentials file
export AWS_ACCESS_KEY_ID="my_dev_key"
export AWS_SECRET_ACCESS_KEY="my_dev_secret"Staging/Production
Use ENV variables for secrets in production while keeping sensible defaults in credentials for development:
# Always works in any environment
SmartCredentials.stripe.secret_keyBehavior
SmartCredentials behaves like Rails credentials:
# Returns the value if it exists
SmartCredentials.api_key
# => "your_api_key"
# Returns nil if it doesn't exist
SmartCredentials.nonexistent_key
# => nil
# Raises NoMethodError when chaining after nil (like Rails)
SmartCredentials.nonexistent.nested.key
# => NoMethodError: undefined method `nested' for nilContributing
Bug reports and pull requests are welcome.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am "Added some new feature") - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
License
The gem is available as open source under the terms of the MIT License.