Skip to content

Cosmic-Chimps/bella-baxter-ruby

Repository files navigation

bella_baxter Ruby SDK

Ruby client for Bella Baxter — load secrets into your Ruby or Rails application with zero runtime dependencies.

Features

  • Zero runtime dependencies — uses only Ruby's stdlib (openssl, net/http, json)
  • Rails Railtie — auto-loads secrets before database.yml is evaluated
  • End-to-end encryption — optional E2EE using ECDH-P256-HKDF-SHA256-AES256GCM (stdlib OpenSSL)
  • Thread-safe — singleton client, mutex-protected HTTP
  • ENV injectionload_into_env! respects existing values (local dev overrides work)

Installation

# Gemfile gem "bella_baxter"
bundle install

Quick start

require "bella_baxter" client = BellaBaxter::Client.new( baxter_url: "https://baxter.example.com", api_key: "bax-...", project: "my-app", environment: "production" ) secrets = client.all_secrets.secrets puts secrets["DATABASE_URL"]

Rails integration

Add the gem to your Gemfile. That's all.

The gem ships a Railtie that injects all secrets into ENV during Rails' before_configuration hook — before database.yml is parsed, before any initializers run.

Environment variables to set on your host (the only secrets you need there):

BELLA_BAXTER_URL=https://baxter.example.com BELLA_API_KEY=bax-... BELLA_PROJECT=my-app # BELLA_ENV defaults to Rails.env # BELLA_E2EE=true to enable end-to-end encryption

database.yml — nothing secret lives here:

production: adapter: postgresql url: <%= ENV.fetch("DATABASE_URL") %>

DATABASE_URL is injected by Bella Baxter before Rails reads this file.

Boot order

1. Gemfile loaded → Railtie registered 2. config/application.rb starts 3. [before_configuration] ← Bella Baxter injects ENV here 4. database.yml evaluated ← ENV["DATABASE_URL"] available ✓ 5. config/initializers/ 6. App boots 

ENV injection

# Inject into ENV (existing values are NOT overwritten — local dev wins) count = BellaBaxter.load_into_env! puts "Loaded #{count} secrets" # Force overwrite (e.g. secret rotation without restart) BellaBaxter.load_into_env!(overwrite: true)

End-to-end encryption

client = BellaBaxter::Client.new( baxter_url: "https://baxter.example.com", api_key: "bax-...", project: "my-app", environment: "production", enable_e2ee: true # Client generates P-256 keypair; server encrypts the response ) # Decryption is transparent — same API secrets = client.all_secrets.secrets

Algorithm: ECDH-P256 → HKDF-SHA256 → AES-256-GCM. All operations use Ruby's built-in openssl — no extra gems required.

Write operations

# Create client.create_secret( provider: "my-vault", # provider slug key: "DATABASE_URL", value: "postgres://...", description: "Primary database" ) # Update client.update_secret( provider: "my-vault", key: "DATABASE_URL", value: "postgres://new-host/..." ) # Delete client.delete_secret(provider: "my-vault", key: "DATABASE_URL")

Lightweight version check

Avoid transferring all secret values just to check if anything changed:

v = client.secrets_version puts "Version #{v.version}, last changed #{v.last_modified}"

Global configuration (optional)

# config/initializers/bella_baxter.rb BellaBaxter.configure do |c| c.baxter_url = ENV["BELLA_BAXTER_URL"] c.api_key = ENV["BELLA_API_KEY"] c.project = "my-app" c.environment = Rails.env c.enable_e2ee = Rails.env.production? end # Access the singleton client anywhere BellaBaxter.client.all_secrets

Samples

Sample Description
samples/01-standalone/ Pure Ruby script — all usage patterns
samples/02-rails/ Rails integration with database.yml example

Typed Secret Code Generation

bella secrets generate ruby fetches the secrets manifest (key names + type hints, no values) from the Bella API and generates a typed AppSecrets module. Each method calls ENV.fetch at runtime — no secret values are ever embedded in the generated file.

bella secrets generate ruby \ --project my-app \ --environment production \ --output app_secrets.rb

Generated app_secrets.rb:

# Auto-generated by bella secrets generate ruby — do not edit manually. module AppSecrets def self.database_url ENV.fetch('DATABASE_URL') { raise "Secret 'DATABASE_URL' is not set." } end def self.port ENV.fetch('PORT') { raise "Secret 'PORT' is not set." }.to_i end def self.enable_feature_x v = ENV.fetch('ENABLE_FEATURE_X') { raise "Secret 'ENABLE_FEATURE_X' is not set." } %w[1 true yes].include?(v.downcase) end end

Usage alongside the Ruby SDK

# The Railtie or BellaBaxter.load_into_env! has already populated ENV. require_relative "app_secrets" db_url = AppSecrets.database_url # String — raises if missing port = AppSecrets.port # Integer — parsed automatically

Because each method calls ENV.fetch on every invocation (not memoized), secrets injected or refreshed at any point are always current.

Options

Option Default Description
-p, --project <slug> .bella context Project slug
-e, --environment <slug> .bella context Environment slug
--provider <slug> default Provider slug
-o, --output <path> app_secrets.rb Output file path
--class-name <name> AppSecrets Module name
--dry-run Print to stdout without writing

Requirements

  • Ruby >= 2.7
  • No runtime gem dependencies

License

Elastic License 2.0 (ELv2)

About

Bella Baxter ruby

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors