Skip to content
camada
Menu

Quickstart

Rails quickstart

Package camada, on RubyGems.

1. Install

bundle add camada

2. Environment

The key is printed once when you create a project in the app. Set these as environment variables: export them in the shell that starts your app, or add them in your host's settings. Rack and Rails read no .env file (Rails needs the dotenv-rails gem for that).

shell
export CAMADA_KEY=<ingest_token>.<snap_token>
export CAMADA_INGEST_URL=http://localhost:8787   # dev only; defaults to production ingest

3. Wire it in

# config.ru — Sinatra, Hanami, or any Rack app
require "camada"
use Camada::Rack      # first, so camada answers before routing
run App

# Rails — nothing to add: the Railtie inserts Camada::Rack at the top of the middleware stack
  • One gem, one Rack middleware; the Railtie mounts it for Rails.
  • Never request.ip: the middleware reads REMOTE_ADDR and applies your trusted-proxy rules itself.

4. Add the beacon to HTML pages

Optional but recommended. The beacon cuts false positives by showing which sessions are real browsers. Use the helper.

"<html><head>#{Camada.script_tag(env)}</head>…"   # Sinatra: env; Rails: request.env

5. Send app outcomes

Login failures, signups and checkout declines are the signals no edge position sees. The identifier is HMAC-hashed in your process. How they catch credential stuffing.

Camada.track(env, "login_failed", user: email)   # Sinatra: env; Rails: request.env

Runtime

What it does per request

  1. Refreshes the snapshot off-path on a thread at the cadence your tenant config sets (ETag/304, gzip on the wire). A cold start fails open.
  2. Resolves the client IP from REMOTE_ADDR per your trusted-proxy setting — never request.ip, which trusts X-Forwarded-For from anyone.
  3. Your ordered custom rules first, then allow, block, challenge. A block gets a 403 with x-block-reason before your app runs; a challenge serves the proof-of-work page on a page load, and an API call reaches your app with an x-camada-challenge: 1 response header. The event still ships.
  4. Serves /_cam/b.js (the beacon, first-party) and relays /_cam/fp posts onto the event batch with the resolved client IP.
  5. Sets x-rid and the _sfp session cookie, and when the server closes the body ships one batched, redacted event carrying the matched route pattern (sinatra.route, Rails route_uri_pattern).

Limits

Caveats at this position

  • Enforcement at this position covers IP, path, user-agent and request-header conditions. ASN, country and TLS-fingerprint entries fail open in-app.
  • The Rack env carries no wire header order, so the analyst reads no HEADER_ORDER signal from this tap and never scores its absence.
  • The request that builds the engine is answered cold. Warm it in an initializer by waiting for the boot poll (the README shows the bounded loop).
  • Threads do not survive a fork: the SDK compares Process.pid on every call and starts over in a forked worker. Puma cluster mode, Unicorn and Passenger need nothing added.
  • CAMADA_SERVERLESS=1 switches to a per-request staleness check with no poll thread.

Kill switch: CAMADA_DISABLED=1, checked per request. All other variables are listed in the docs index; the package's options and deployment notes are on the Ruby page.