Skip to main content

Overview

The Anubis package provides the core Server implementation for bot detection and challenge management. Use lib.New() to create a new server instance, and lib.LoadPoliciesOrDefault() to load policy configurations.

Functions

New

Creates a new Anubis server instance with the specified options.
func New(opts Options) (*Server, error)
opts
Options
required
Server configuration options
server
*Server
Configured Anubis server instance
error
error
Error if server creation fails
Example
package main

import (
	"context"
	"log/slog"
	"net/http"
	"time"

	"github.com/TecharoHQ/anubis/lib"
)

func main() {
	ctx := context.Background()
	
	// Load policy configuration
	policy, err := lib.LoadPoliciesOrDefault(ctx, "policy.yaml", 20, "info")
	if err != nil {
		panic(err)
	}
	
	// Create upstream handler
	upstream := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, verified human!"))
	)
	
	// Create Anubis server
	server, err := lib.New(lib.Options{
		Next:             upstream,
		Policy:           policy,
		CookieExpiration: 24 * time.Hour,
		CookieSecure:     true,
		CookieSameSite:   http.SameSiteLaxMode,
		Logger:           slog.Default(),
	)
	if err != nil {
		panic(err)
	}
	
	// Serve requests
	http.ListenAndServe(":8080", server)
}

LoadPoliciesOrDefault

Loads policy configuration from a file or uses the built-in default policies.
func LoadPoliciesOrDefault(ctx context.Context, fname string, defaultDifficulty int, logLevel string) (*policy.ParsedConfig, error)
ctx
context.Context
required
Context for loading policies (may include Thoth client)
fname
string
Path to policy YAML file. If empty, uses built-in default policies
defaultDifficulty
int
required
Default proof-of-work difficulty level (0-64, recommended: 15-25)
logLevel
string
required
Log level: “debug”, “info”, “warn”, or “error”
config
*policy.ParsedConfig
Parsed and validated policy configuration
error
error
Error if policy loading or validation fails
Example
ctx := context.Background()

// Load custom policy file
policy, err := lib.LoadPoliciesOrDefault(ctx, "/etc/anubis/policy.yaml", 20, "info")
if err != nil {
	log.Fatal(err)
}

// Use built-in default policies
policy, err = lib.LoadPoliciesOrDefault(ctx, "", 20, "info")
if err != nil {
	log.Fatal(err)
}

Server Type

The Server type implements http.Handler and manages bot detection, challenge issuance, and request validation.

Server Methods

ServeHTTP

Implements the http.Handler interface. Routes requests to static assets, API endpoints, or the validation middleware.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
Behavior:
  • Static assets (.within.website/static/*) are served directly
  • API endpoints (.within.website/api/*) handle challenges and validation
  • All other requests go through the bot detection and challenge flow
  • Validated requests with valid JWT cookies are proxied to the upstream handler
Example
server, _ := lib.New(opts)

// Use as HTTP handler
http.ListenAndServe(":8080", server)

// Or wrap with middleware
http.Handle("/", loggingMiddleware(server))

MakeChallenge

API endpoint that issues a new challenge for client-side solving. Only available in development builds.
func (s *Server) MakeChallenge(w http.ResponseWriter, r *http.Request)
Request Parameters:
  • redir (query string): Redirect URL after challenge completion
Response: JSON with challenge data
{
  "rules": {
    "algorithm": "fast",
    "difficulty": 20
  },
  "challenge": "hexadecimal random data",
  "id": "challenge UUID"
}
See lib/anubis.go:361-432

PassChallenge

API endpoint that validates a completed challenge and issues a JWT cookie upon success.
func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request)
Request Parameters:
  • redir (query string, required): Redirect URL after successful validation
  • id (query string, required): Challenge ID
  • Challenge-specific validation parameters (varies by algorithm)
Response:
  • On success: HTTP 302 redirect with JWT cookie set
  • On failure: Error page with details
Security:
  • Validates redirect domain against RedirectDomains whitelist
  • Prevents double-spend attacks (challenges can only be solved once)
  • Binds JWT to HTTP header if JWTRestrictionHeader is set
See lib/anubis.go:434-585

HTTP Endpoints

Anubis registers the following endpoints (all prefixed with BasePrefix, default /.within.website):
EndpointMethodPurpose
/api/pass-challengeGETValidate completed challenge
/api/checkAnyAuth check endpoint (returns status only)
/api/imprintGETDisplay impressum/legal page
/api/make-challengePOSTIssue new challenge (dev only)
/api/honeypot/{id}/{stage}GETHoneypot trap endpoints
/static/*GETStatic assets (JS, CSS)
/robots.txtGETRobots file (if enabled)
/*AnyMain validation middleware

  • Challenge - Challenge data structures and interface
  • Policy - Bot detection rules and configuration
  • Store - Storage backend interface

Build docs developers (and LLMs) love