Example 5: Captcha Challenge (Turnstile / hCaptcha / reCAPTCHA)
Instead of dropping connections or returning static error codes, RouteWarden can serve interactive Captcha challenges on sensitive paths using Cloudflare Turnstile, hCaptcha, or Google reCAPTCHA.
Is a captcha.html File Required?
TIP
No external captcha.html file is required!
RouteWarden has a built-in, mobile-responsive dark-mode HTML template embedded directly into the Go binary. When mode: captcha is enabled, RouteWarden automatically:
- Injects the official provider JavaScript SDK.
- Renders the appropriate widget container.
- Populates your custom title and site key.
(Optional: Pass an HTML template string into response.captcha.template to override the design.)
Supported Providers
| Provider | response.captcha.provider | Injected SDK Script | Widget Class |
|---|---|---|---|
| hCaptcha | hcaptcha | https://js.hcaptcha.com/1/api.js | <div class="h-captcha"> |
| Cloudflare Turnstile | turnstile | https://challenges.cloudflare.com/turnstile/v0/api.js | <div class="cf-turnstile"> |
| Google reCAPTCHA v2 | recaptcha | https://www.google.com/recaptcha/api.js | <div class="g-recaptcha"> |
1. hCaptcha Configuration Example
This example protects /admin and /login with hCaptcha (using the official hCaptcha test site key 10000000-ffff-ffff-ffff-000000000001):
# dynamic_conf.ymlhttp: middlewares: hcaptcha-barrier: plugin: routewarden: enabled: true pathPatterns: - '(?i)^/(admin|login)(/.*)?$' response: mode: captcha statusCode: 403 captcha: provider: "hcaptcha" siteKey: "10000000-ffff-ffff-ffff-000000000001" title: "Human Verification (hCaptcha)" routers: app-router: rule: "Host(`app.example.com`)" entryPoints: - web middlewares: - hcaptcha-barrier service: app-service2. Cloudflare Turnstile Configuration Example
# dynamic_conf.ymlhttp: middlewares: turnstile-barrier: plugin: routewarden: enabled: true pathPatterns: - '(?i)^/login(/.*)?$' - '(?i)^/reset-password(/.*)?$' response: mode: captcha statusCode: 403 captcha: provider: "turnstile" siteKey: "1x00000000000000000000AA" title: "Security Verification Required" routers: login-router: rule: "Host(`login.example.com`)" entryPoints: - web middlewares: - turnstile-barrier service: login-service3. Docker Compose Example
services: traefik: image: traefik:v3.1 command: - "--providers.docker=true" - "--entrypoints.web.address=:80" - "--experimental.plugins.routewarden.modulename=github.com/routewarden/traefik-warden" - "--experimental.plugins.routewarden.version=v1.2.1" ports: - "80:80" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" app: image: nginx:alpine labels: - "traefik.enable=true" - "traefik.http.routers.app.rule=Host(`app.localhost`)" - "traefik.http.routers.app.middlewares=hcaptcha-barrier" - "traefik.http.middlewares.hcaptcha-barrier.plugin.routewarden.enabled=true" - "traefik.http.middlewares.hcaptcha-barrier.plugin.routewarden.pathPatterns=(?i)^/(admin|login)(/.*)?$" - "traefik.http.middlewares.hcaptcha-barrier.plugin.routewarden.response.mode=captcha" - "traefik.http.middlewares.hcaptcha-barrier.plugin.routewarden.response.captcha.provider=hcaptcha" - "traefik.http.middlewares.hcaptcha-barrier.plugin.routewarden.response.captcha.siteKey=10000000-ffff-ffff-ffff-000000000001"