Skip to content
camada
Menu

Quickstart

Go quickstart

Module github.com/camada-app/camada-go, on the Go module proxy.

1. Install

go get github.com/camada-app/camada-go

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. Go reads no .env file.

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

import "github.com/camada-app/camada-go"

mux := http.NewServeMux()
mux.HandleFunc("GET /{$}", home)
http.ListenAndServe(":8080", camada.Handler(mux))   // outermost, so camada answers before routing
  • net/http: any router built on http.Handler sits behind it.
  • The first request builds the engine and is answered cold; camada.Default().Stop(ctx) before main returns drains the last batch.

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.

fmt.Fprintf(w, "<html><head>%s</head>…", camada.ScriptTag(r))

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(r, "login_failed", email)   // "" when there is no identifier

Runtime

What it does per request

  1. Refreshes the snapshot off-path on a goroutine at the cadence your tenant config sets (ETag/304, gzip on the wire). A cold start fails open.
  2. Resolves the client IP from r.RemoteAddr per your trusted-proxy setting. Raw X-Forwarded-For is never trusted without it.
  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 response is done ships one batched, redacted event carrying the route pattern (r.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.
  • net/http parses headers into a map, so the event carries the sorted header names, not the wire order; the analyst knows and never scores its absence.
  • The request that builds the engine is answered cold. To enforce from request 1, build it eagerly with camada.Default() at startup and wait for the boot poll (the README shows the bounded loop).
  • camada.Default().Stop(ctx) before main returns drains the last batch within half a second; no signal handlers are installed.
  • CAMADA_SERVERLESS=1 drops the poll goroutine: each request checks staleness, and a stale one kicks one refresh off the request path.

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 Go page.