ALTCHA setup
ALTCHA is the choice when you want bot protection but don’t want to depend on (or send visitors to) a third party like Cloudflare. The browser solves a small computational puzzle on submit; your server issues and verifies it using a secret you control.
1. Generate an HMAC key
Section titled “1. Generate an HMAC key”ALTCHA challenges are signed with a secret that never leaves your server. Generate a strong random one:
openssl rand -hex 322. Set the environment variables
Section titled “2. Set the environment variables”CAPTCHA_PROVIDER=altchaALTCHA_HMAC_KEY=your-generated-secret# Optional — proof-of-work difficulty (max number the browser brute-forces). Higher = harder for# bots but slightly slower for legitimate visitors. Default is fine for most instances.ALTCHA_MAX_NUMBER=100000CAPTCHA_PROVIDER=altcha activates both the client-side widget on the booking form and server-side verification. calit fails fast at startup if CAPTCHA_PROVIDER=altcha is set without ALTCHA_HMAC_KEY, so a misconfiguration can never silently accept forged solutions.
3. Reverse proxy
Section titled “3. Reverse proxy”The widget fetches its challenge from GET /altcha/challenge on your instance (public, unauthenticated, cheap). No special proxy configuration is needed beyond forwarding normal traffic — if you already proxy the app, the endpoint works. The widget script is served by calit itself (no CDN), so it also works on fully air-gapped deployments.
4. What it protects
Section titled “4. What it protects”ALTCHA challenges the public booking form on submission. It is layered with two abuse controls that are always active:
- A honeypot field to catch naive bots.
- A per-email daily cap (
PER_EMAIL_DAILY_CAP, default 10) limiting how many bookings a single email address can submit per day.
Localisation
Section titled “Localisation”The widget’s own strings (“I’m not a robot”, “Verifying…”) are localised automatically from the page language — English, German, and Hebrew (right-to-left) are all covered, matching calit’s own UI languages. No extra configuration.
- Enabling any CAPTCHA provider makes the booking form require JavaScript (the proof-of-work runs in the browser). With
CAPTCHA_PROVIDER=none(default) the form works without JavaScript. - The widget JavaScript is bundled with calit and served from your instance — nothing is fetched from a CDN at runtime.