tutorial

Uptime monitoring for Hanko authentication service

Hanko is the passkey-first authentication service that handles login, registration, and session management for your users. When Hanko goes down, nobody can s...

Hanko is the passkey-first authentication service that handles login, registration, and session management for your users. When Hanko goes down, nobody can sign in. Password resets fail. Token refresh calls return errors. For applications where authentication is on the critical path — which is every application — an unmonitored Hanko instance is a quiet outage waiting to happen.

This tutorial covers production-grade uptime monitoring for Hanko using Vigilmon. We will walk through:

  • Monitoring the Hanko /health endpoint
  • Monitoring the WebAuthn/passkey API availability
  • Monitoring the token endpoint for session continuity
  • SSL certificate monitoring for auth flows
  • Webhook alerts for DOWN/UP events

Prerequisites

  • Hanko running (Docker, Kubernetes, or bare metal)
  • A free account at vigilmon.online

Part 1: The Hanko health endpoint

Hanko exposes a /health endpoint that returns a JSON status object when the service is operational. It is the primary signal for external monitoring tools.

Start Hanko

# docker-compose.yml
version: "3.8"

services:
  hanko:
    image: ghcr.io/teamhanko/hanko:latest
    command: serve all
    environment:
      DATABASE_URL: "postgres://hanko:hanko@db:5432/hanko"
      SECRETS_KEYS: "your-signing-key-base64"
      WEBAUTHN_RPID: "example.com"
      WEBAUTHN_ORIGIN: "https://example.com"
      SERVICE_PORT: "8000"
    ports:
      - "8000:8000"
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:15
    environment:
      POSTGRES_USER: hanko
      POSTGRES_PASSWORD: hanko
      POSTGRES_DB: hanko
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U hanko"]
      interval: 10s
      timeout: 5s
      retries: 5

Verify the health endpoint

curl http://localhost:8000/.well-known/health

Expected response:

{
  "alive": true,
  "ready": true
}

Hanko returns HTTP 200 with "alive": true and "ready": true when the service is fully initialized and healthy. During startup, ready may be false while database migrations run.

The alive field indicates the process is running. The ready field indicates it can serve traffic. Monitor both — an "alive": true, "ready": false state means Hanko is starting but not yet serving auth requests.


Part 2: HTTP monitoring in Vigilmon

Monitor the health endpoint

  1. Log in to vigilmon.online and click Add Monitor.
  2. Choose HTTP(S) monitor.
  3. Enter: https://auth.example.com/.well-known/health
  4. Set interval to 1 minute.
  5. Add a keyword check: must contain "ready":true.
  6. Click Save.

The keyword check on "ready":true is important: it distinguishes a fully operational Hanko from one that is starting up or has a broken database connection, both of which return HTTP 200 from some endpoints.

Monitor the WebAuthn configuration endpoint

The .well-known/jwks.json endpoint is used by your application to validate JWT tokens. If it goes down, token verification fails across your entire application:

  1. In Vigilmon, click Add Monitor.
  2. Choose HTTP(S) monitor.
  3. Enter: https://auth.example.com/.well-known/jwks.json
  4. Set interval to 1 minute.
  5. Add a keyword check: "keys".
  6. Click Save.
curl https://auth.example.com/.well-known/jwks.json
# Expected: {"keys":[{"kty":"EC","kid":"...","crv":"P-256",...}]}

Monitor the passkey registration endpoint

The WebAuthn passkey registration flow begins with a POST to /registration/initialize. You can monitor this endpoint's availability with a HEAD or OPTIONS request:

curl -I https://auth.example.com/registration/initialize
# Expected: HTTP/2 405 (Method Not Allowed for GET, confirming the endpoint exists)

For Vigilmon, monitoring /.well-known/health and /.well-known/jwks.json gives you full coverage of the auth service without requiring authenticated test requests.


Part 3: Monitoring the token endpoint

Hanko issues short-lived JWTs that your application validates via JWKS. The token endpoint is called on every login and session refresh. Monitor it to confirm the token issuance path is healthy:

# Check that the token endpoint is reachable (returns 400 for missing body, not 5xx)
curl -o /dev/null -s -w "%{http_code}" \
  -X POST https://auth.example.com/token \
  -H "Content-Type: application/json" \
  -d '{}'

A 400 Bad Request response confirms the endpoint is reachable and processing requests. A 502 or 504 indicates a broken proxy or a crashed Hanko process.

In Vigilmon, you can monitor the token endpoint with:

  1. HTTP(S) monitor → https://auth.example.com/token
  2. Method: POST, Body: {}
  3. Expected status: any non-5xx (use keyword check 400 or monitor for absence of 502)

Alternatively, keep your monitoring focused on the health and JWKS endpoints and treat a token endpoint failure as downstream of those.


Part 4: SSL certificate monitoring

Authentication flows are always over HTTPS. A certificate expiry on your Hanko domain breaks every login attempt — users cannot register, sign in, or refresh their sessions. The impact is immediate and total.

Add SSL monitoring in Vigilmon

  1. In Vigilmon, click Add Monitor.
  2. Choose SSL monitor.
  3. Enter: auth.example.com
  4. Set alert threshold to 14 days before expiry.
  5. Add your alert channel.

Add SSL monitors for all domains in your Hanko deployment:

| Domain | Purpose | |---|---| | auth.example.com | Primary Hanko API | | app.example.com | Frontend that calls Hanko |

Set the threshold to 14 days to give yourself time to investigate renewal failures before users are impacted. Let's Encrypt certificates renew at 30 days by default, so 14 days gives you a two-week window after a failed renewal attempt.


Part 5: Kubernetes deployment

If Hanko runs in Kubernetes, expose the health endpoint for external monitoring:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hanko
  namespace: auth
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hanko
  template:
    metadata:
      labels:
        app: hanko
    spec:
      containers:
        - name: hanko
          image: ghcr.io/teamhanko/hanko:latest
          args: ["serve", "all"]
          ports:
            - containerPort: 8000
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: hanko-secrets
                  key: database-url
          livenessProbe:
            httpGet:
              path: /.well-known/health
              port: 8000
            initialDelaySeconds: 10
            periodSeconds: 30
          readinessProbe:
            httpGet:
              path: /.well-known/health
              port: 8000
            initialDelaySeconds: 5
            periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: hanko
  namespace: auth
spec:
  selector:
    app: hanko
  ports:
    - port: 80
      targetPort: 8000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hanko
  namespace: auth
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - auth.example.com
      secretName: hanko-tls
  rules:
    - host: auth.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: hanko
                port:
                  number: 80

Point Vigilmon at https://auth.example.com/.well-known/health as described in Part 2.


Part 6: Webhook alerts

Configure Vigilmon to notify your on-call team the moment Hanko fails — authentication outages affect every user of your application:

// Express.js webhook receiver
import express from 'express';

const app = express();
app.use(express.json());

app.post('/webhook/vigilmon', (req, res) => {
  const { monitor_name, status, url, response_code, checked_at } = req.body;

  if (status === 'down') {
    console.error('[VIGILMON] Hanko auth DOWN', {
      monitor: monitor_name,
      url,
      code: response_code,
      at: checked_at,
    });
    // Authentication outages are P1 — page immediately
    triggerP1Incident({
      title: `Hanko auth service DOWN: ${monitor_name}`,
      url,
    });
  } else if (status === 'up') {
    console.info('[VIGILMON] Hanko auth recovered', {
      monitor: monitor_name,
      at: checked_at,
    });
    resolveIncident({ monitor: monitor_name });
  }

  res.sendStatus(204);
});

Vigilmon sends this payload on DOWN and UP transitions:

{
  "monitor_id": "mon_abc123",
  "monitor_name": "Hanko /health",
  "status": "down",
  "url": "https://auth.example.com/.well-known/health",
  "checked_at": "2026-06-30T08:01:00Z",
  "response_code": 503,
  "response_time_ms": 2104
}

Or use Vigilmon's native Slack integration to post directly to your #incidents channel — no webhook receiver required.


Summary

Your Hanko deployment now has four layers of monitoring:

  1. /health HTTP monitor — confirms Hanko is alive and ready, polled every 60 seconds, with a keyword check on "ready":true to distinguish startup from a healthy state.
  2. JWKS endpoint monitor — confirms token validation infrastructure is available, catching database failures that may not surface on the health endpoint.
  3. SSL monitor — alerts you 14 days before certificate expiry, before login attempts start failing for users.
  4. Webhook/Slack alerts — authentication outages are P1 events; DOWN notifications reach your team within 60 seconds.

Vigilmon handles check scheduling, multi-region polling, alert routing, and uptime history — your users should never know Hanko had a problem.


Monitor your Hanko authentication service free at vigilmon.online

#hanko #passkey #webauthn #authentication #monitoring #devops

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →