Skip to main content
Traefik is a modern HTTP reverse proxy with automatic service discovery. This guide shows how to deploy Anubis with Traefik using Docker labels or Kubernetes.

Deployment Architecture

Traefik uses Anubis as a ForwardAuth middleware:

Docker Compose Configuration

Here’s a complete working example with Traefik v3.3: compose.yml:
services:
  traefik:
    image: traefik:v3.3
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./letsencrypt:/letsencrypt
      - ./traefik.yml:/traefik.yml:ro
    networks:
      - traefik
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      
      # Define Anubis ForwardAuth middleware
      - traefik.http.middlewares.anubis.forwardauth.address=http://anubis:8080/.within.website/x/cmd/anubis/api/check
      
      # Redirect HTTP to HTTPS
      - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
      - traefik.http.routers.web.rule=PathPrefix(`/`)
      - traefik.http.routers.web.entrypoints=web
      - traefik.http.routers.web.middlewares=redirect-to-https
      - traefik.http.routers.web.tls=false

  anubis:
    image: ghcr.io/techarohq/anubis:main
    environment:
      # Listen for Traefik
      BIND: ":8080"
      # Empty target - Anubis only validates, doesn't proxy
      TARGET: " "
      # Allowed redirect domains
      REDIRECT_DOMAINS: "example.com,anubis.example.com"
      # Public URL for Anubis
      PUBLIC_URL: "https://anubis.example.com"
      # Cookie domain
      COOKIE_DOMAIN: "example.com"
    networks:
      - traefik
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - traefik.http.routers.anubis.rule=Host(`anubis.example.com`)
      - traefik.http.routers.anubis.entrypoints=websecure
      - traefik.http.services.anubis.loadbalancer.server.port=8080
      - traefik.http.routers.anubis.service=anubis
      - traefik.http.routers.anubis.tls.certresolver=le

  # Protected by Anubis
  target:
    image: traefik/whoami:latest
    networks:
      - traefik
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - traefik.http.routers.target.rule=Host(`example.com`)
      - traefik.http.routers.target.entrypoints=websecure
      - traefik.http.services.target.loadbalancer.server.port=80
      - traefik.http.routers.target.service=target
      - traefik.http.routers.target.tls.certresolver=le
      # Use Anubis middleware
      - traefik.http.routers.target.middlewares=anubis@docker

  # Not protected by Anubis
  target2:
    image: traefik/whoami:latest
    networks:
      - traefik
    labels:
      - traefik.enable=true
      - traefik.docker.network=traefik
      - traefik.http.routers.target2.rule=Host(`another.example.com`)
      - traefik.http.routers.target2.entrypoints=websecure
      - traefik.http.services.target2.loadbalancer.server.port=80
      - traefik.http.routers.target2.service=target2
      - traefik.http.routers.target2.tls.certresolver=le
      # No middleware - not protected

networks:
  traefik:
    name: traefik
traefik.yml:
api:
  insecure: false  # Don't enable in production

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

certificatesResolvers:
  le:
    acme:
      tlsChallenge: {}
      email: "[email protected]"
      storage: "/letsencrypt/acme.json"

providers:
  docker: {}

How It Works

  1. User requests https://example.com
  2. Traefik checks middleware - ForwardAuth sends request to http://anubis:8080/.within.website/x/cmd/anubis/api/check
  3. Anubis validates:
    • If validated: Returns 200, Traefik forwards to backend
    • If not validated: Returns 401 with redirect to challenge page
  4. User completes challenge at https://anubis.example.com
  5. Anubis redirects back to https://example.com
  6. Request succeeds - cookie is set, future requests pass validation

ForwardAuth Middleware

The key configuration is the ForwardAuth middleware:
traefik.http.middlewares.anubis.forwardauth.address=http://anubis:8080/.within.website/x/cmd/anubis/api/check
This tells Traefik to send an auth check to Anubis before forwarding to the backend.

Additional ForwardAuth Options

labels:
  # Basic ForwardAuth
  - traefik.http.middlewares.anubis.forwardauth.address=http://anubis:8080/.within.website/x/cmd/anubis/api/check
  
  # Trust forwarded headers
  - traefik.http.middlewares.anubis.forwardauth.trustForwardHeader=true
  
  # Forward auth headers to backend
  - traefik.http.middlewares.anubis.forwardauth.authResponseHeaders=X-Anubis-Verified,X-Real-IP

Multiple Protected Services

Protect different services with the same Anubis instance:
services:
  app1:
    image: app1:latest
    labels:
      - traefik.http.routers.app1.rule=Host(`app1.example.com`)
      - traefik.http.routers.app1.middlewares=anubis@docker
      - traefik.http.routers.app1.tls.certresolver=le

  app2:
    image: app2:latest
    labels:
      - traefik.http.routers.app2.rule=Host(`app2.example.com`)
      - traefik.http.routers.app2.middlewares=anubis@docker
      - traefik.http.routers.app2.tls.certresolver=le
Update Anubis environment:
anubis:
  environment:
    REDIRECT_DOMAINS: "app1.example.com,app2.example.com,anubis.example.com"
    COOKIE_DOMAIN: "example.com"

Path-Based Protection

Protect only specific paths:
labels:
  # Protect /admin paths only
  - traefik.http.routers.app-admin.rule=Host(`example.com`) && PathPrefix(`/admin`)
  - traefik.http.routers.app-admin.middlewares=anubis@docker
  
  # Public paths (no middleware)
  - traefik.http.routers.app-public.rule=Host(`example.com`) && PathPrefix(`/`)
  - traefik.http.routers.app-public.priority=1
Note: Higher priority rules are evaluated first.

Kubernetes Deployment

For Kubernetes with Traefik ingress controller, see the Kubernetes deployment guide. Quick example using Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: protected-app
  annotations:
    traefik.ingress.kubernetes.io/router.middlewares: default-anubis@kubernetescrd
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app
                port:
                  number: 80

Custom Middleware Chain

Combine Anubis with other Traefik middlewares:
labels:
  # Define middleware chain
  - traefik.http.middlewares.secure-chain.chain.middlewares=rate-limit,anubis,compression
  
  # Rate limiting
  - traefik.http.middlewares.rate-limit.ratelimit.average=100
  - traefik.http.middlewares.rate-limit.ratelimit.burst=50
  
  # Compression
  - traefik.http.middlewares.compression.compress=true
  
  # Apply to router
  - traefik.http.routers.app.middlewares=secure-chain
Middleware execution order: rate-limit → anubis → compression

Health Checks

Configure Traefik to health check Anubis:
labels:
  - traefik.http.services.anubis.loadbalancer.healthcheck.path=/healthz
  - traefik.http.services.anubis.loadbalancer.healthcheck.port=9090
  - traefik.http.services.anubis.loadbalancer.healthcheck.interval=10s

Load Balancing Multiple Anubis Instances

services:
  anubis1:
    image: ghcr.io/techarohq/anubis:main
    environment:
      BIND: ":8080"
      ED25519_PRIVATE_KEY_HEX_FILE: "/secrets/anubis-key.txt"
    volumes:
      - ./secrets:/secrets:ro

  anubis2:
    image: ghcr.io/techarohq/anubis:main
    environment:
      BIND: ":8080"
      ED25519_PRIVATE_KEY_HEX_FILE: "/secrets/anubis-key.txt"
    volumes:
      - ./secrets:/secrets:ro

  traefik:
    labels:
      - traefik.http.middlewares.anubis.forwardauth.address=http://anubis/.within.website/x/cmd/anubis/api/check
      - traefik.http.services.anubis.loadbalancer.servers[0].url=http://anubis1:8080
      - traefik.http.services.anubis.loadbalancer.servers[1].url=http://anubis2:8080
All instances must use the same signing key for JWT validation.

Troubleshooting

Redirect Loops

Check:
  1. REDIRECT_DOMAINS includes all your domains
  2. PUBLIC_URL matches Anubis router hostname
  3. COOKIE_DOMAIN is set correctly

502 Bad Gateway on Auth Request

Verify:
  1. Anubis is running: docker ps
  2. Network connectivity: docker exec traefik wget -O- http://anubis:8080/.within.website/x/cmd/anubis/api/check
  3. Check Traefik logs: docker logs traefik

Certificates Not Working

Ensure:
  1. DNS points to your server
  2. Ports 80 and 443 are accessible
  3. Email is configured in traefik.yml
  4. Check Let’s Encrypt rate limits

ForwardAuth Not Triggering

Verify:
  1. Middleware is attached to router: middlewares=anubis@docker
  2. Middleware name matches: traefik.http.middlewares.anubis.forwardauth.address=...
  3. Check Traefik dashboard for middleware configuration

Testing

Test the ForwardAuth flow:
# Without valid cookie - should return 401
curl -v http://anubis:8080/.within.website/x/cmd/anubis/api/check

# Check Traefik routing
curl -v https://example.com

# View Traefik logs
docker logs -f traefik

Resources

Build docs developers (and LLMs) love