Skip to content
Open Beta Hansestack is completely free during the current phase. 🐙 Submit feedback on GitHub

Caddy v2 Plugin (Zero-Code)

The official Caddy v2 plugin for Hansestack enables Decoupled Security: You can attach the k-Anonymity leak check directly to your reverse proxy without touching a single line of code in your backend.

The plugin intercepts requests, securely checks contained passwords, and enriches the request or response with the outcome. Your backend never has to import a client library or call an API.

Resources & Hands-on

  • 🐙 Source Code: Find the source code, releases, and issue tracker in the caddy-hansestack repository.
  • 👾 Try the Sandbox: Want to see the plugin in action? Clone our Demo Repo, type docker-compose up, and watch the provided Grafana dashboard to see exactly how the leak check (and the fail-open fallback) performs under load.

Installation

There are two ways to deploy the plugin in your infrastructure.

Option A: Build with xcaddy (Recommended)

If you build your own Caddy binaries, use xcaddy:

xcaddy build --with github.com/hansestack/caddy-hansestack

Option B: Pre-built Docker Image

We provide a pre-built Docker image based on the official Caddy image:

# docker-compose.yml
services:
  caddy:
    image: ghcr.io/hansestack/caddy-hansestack:latest
    ports:
      - "80:80"
      - "443:443"

(Tip: In production, pin a specific version instead of :latest, e.g. :v1.0.0)

Configuration (Caddyfile)

Configuration is handled natively via the Caddyfile. The plugin registers itself to always run before the reverse_proxy directive in Caddy's execution order.

:443 {
    hansestack /login* leakcheck {
        api_key {$HANSESTACK_API_KEY}
        mode enrich_response
        password_field "password"
        
        # Optional circuit breaker tuning for high resilience
        timeout 500ms
        circuit_breaker_threshold 5
        circuit_breaker_cooldown 30s
    }

    reverse_proxy backend:8080
}

Configuration Directives

DirectiveDefaultDescription
api_key(Required)Your Hansestack API key. (Use {$ENV_VAR} to inject via env variables).
modeenrich_requestExecution mode: enrich_request, enrich_response or block.
password_fieldpasswordThe key in the JSON or form-data body holding the password.
header_leakedX-Hansestack-LeakedHeader containing the result (true/false).
header_countX-Hansestack-Leak-CountHeader containing the number of breach occurrences.
block_status401HTTP status code returned when mode=block triggers.
timeout500msMaximum wait time for the API call (fail-open takes over after this).
circuit_breaker_thresholddisabled (0)Number of consecutive failures before the breaker trips.
circuit_breaker_cooldown30sHow long the circuit stays open, locally skipping checks instantly.

Operation Modes

Depending on your auth flow architecture, the plugin offers three modes:

  1. enrich_response (Recommended): Asynchronous. The leak check runs concurrently with your backend processing. It adds zero latency to your login. The leak headers are injected into the outgoing response back to the client.
    sequenceDiagram
    participant C as Client
    participant P as Caddy (Plugin)
    participant B as Your Backend
    participant H as Hansestack API

    C->>P: POST /login (Credentials)
    
    par Asynchronous Leak-Check
        P->>H: Send Hash Prefix
        H-->>P: Suffix List (No Leak)
    and Normal Login Flow
        P->>B: POST /login (Original Body)
        Note over B: Backend verifies Login
        B-->>P: HTTP 201 (Session Token)
    end
    
    P-->>C: HTTP 201 + X-Hansestack-Leaked Header
  
  1. enrich_request: Synchronous. Waits for the API (max timeout) and injects the leak headers into the incoming request. Your backend can read these headers and decide how to act.
  2. block: Synchronous. The only mode capable of rejecting a request. Only if a leak is affirmatively confirmed will Caddy short-circuit the request and return e.g. HTTP 401. Your backend is never invoked in this scenario.
Fail-Open by Design
In all modes: In case of API timeouts, rate limits, or network errors, the request is always passed through unmodified. A disruption in the leak check service will never lock your legitimate users out of their accounts.

Metrics (Prometheus)

If you enable Caddy's global metrics option, the plugin exposes its own metrics on the admin endpoint. These are perfect for Grafana dashboards to visualize credential stuffing attacks:

  • hansestack_leakcheck_checks_total{result="leaked|not_leaked"}
  • hansestack_leakcheck_check_outcomes_total{outcome="..."} (Details whether a check succeeded or a timeout/circuit breaker intervened)
  • hansestack_leakcheck_check_errors_total