Skip to content

Mandible Configuration

Configure the Mandible REST API server for your deployment.

Mandible searches for a config file named mandible (e.g., mandible.toml) in the current directory using the config crate. All settings can be overridden with environment variables using the MANDIBLE__ prefix with double underscore separators.

HTTP server settings.

[server]
host = "0.0.0.0"
port = 3000
request_timeout_secs = 30
external_url = "https://api.mantis.example.com"
FieldTypeDefaultRequiredDescription
hoststring"0.0.0.0"NoIP address to bind
portinteger3000NoHTTP port
request_timeout_secsinteger30NoRequest timeout in seconds
external_urlstring-NoExternal URL for OAuth2 discovery endpoints. If not set, derived from host:port

Optional TLS configuration for direct HTTPS termination. Leave unconfigured if using a reverse proxy for TLS.

[server.tls]
cert_path = "/etc/mantis/certs/server.crt"
key_path = "/etc/mantis/certs/server.key"
FieldTypeDefaultRequiredDescription
cert_pathstring-Yes (if TLS enabled)Path to TLS certificate PEM file
key_pathstring-Yes (if TLS enabled)Path to TLS private key PEM file

PostgreSQL connection settings.

[database]
url = "postgres://mantis:password@localhost:5432/mantis"
max_connections = 10
min_idle = 2
connection_timeout_secs = 10
FieldTypeDefaultRequiredDescription
urlstringDATABASE_URL env varYesPostgreSQL connection URL. Startup fails with a config error if not set
max_connectionsinteger10NoMaximum connection pool size
min_idleinteger2NoMinimum idle connections
connection_timeout_secsinteger10NoConnection timeout in seconds

JWT authentication token configuration. Supports HS256 (symmetric) and RS256 (asymmetric) algorithms.

[jwt]
algorithm = "HS256"
secret = "your-256-bit-secret-key-at-least-32-characters-long"
access_token_expiry_secs = 3600
refresh_token_expiry_secs = 2592000
issuer = "mandible"
audience = "lens"
key_id = "k1"
FieldTypeDefaultRequiredDescription
algorithmstring"HS256"NoSigning algorithm: HS256 or RS256
secretstring""Yes (HS256)HMAC secret key (min 32 characters). Set via MANDIBLE__JWT__SECRET
private_key_pathstring-Yes (RS256)Path to RSA private key PEM file
public_key_pathstring-Yes (RS256)Path to RSA public key PEM file
key_idstring"k1"NoKey ID for the current signing key (for key rotation)
previous_secretstring-NoPrevious secret for graceful HS256 key rotation
previous_public_key_pathstring-NoPrevious public key path for graceful RS256 key rotation
previous_key_idstring-NoKey ID for the previous key
issuerstring"mandible"NoJWT issuer claim
audiencestring"lens"NoJWT audience claim
access_token_expiry_secsinteger3600NoAccess token lifetime (1 hour)
refresh_token_expiry_secsinteger2592000NoRefresh token lifetime (30 days)

Cross-Origin Resource Sharing settings.

[cors]
allowed_origins = ["https://lens.example.com"]
allowed_methods = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
allowed_headers = ["Content-Type", "Authorization", "Accept", "X-Request-ID"]
allow_credentials = true
max_age_secs = 3600
FieldTypeDefaultRequiredDescription
allowed_originsarray["https://localhost:5173", "http://localhost:5173", "https://localhost:4173", "http://localhost:4173"]NoAllowed origins
allowed_methodsarray["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]NoAllowed HTTP methods
allowed_headersarray["Content-Type", "Authorization", "Accept", "X-Request-ID"]NoAllowed headers
allow_credentialsbooleantrueNoWhether to allow credentials
max_age_secsinteger3600NoPreflight cache duration in seconds

Cookie settings for authentication refresh tokens.

[cookie]
refresh_token_name = "mantis_refresh_token"
secure = true
same_site = "Lax"
path = "/"
domain = ".example.com"
FieldTypeDefaultRequiredDescription
refresh_token_namestring"mantis_refresh_token"NoCookie name for the refresh token
securebooleantrue (release), false (debug)NoHTTPS-only cookies
same_sitestring"Lax"NoSameSite policy: Strict, Lax, or None
pathstring"/"NoCookie path scope
domainstring-NoCookie domain. If not set, defaults to the origin domain

Authentication redirect settings.

[auth]
lens_base_url = "https://lens.example.com/login"
FieldTypeDefaultRequiredDescription
lens_base_urlstring"https://localhost:5173/login"NoLens UI login URL for redirects. Must be a valid HTTP/HTTPS URL

gRPC client settings for connecting to Thorax.

[grpc]
orchestration_url = "https://thorax.example.com:50051"
connect_timeout_secs = 5
request_timeout_secs = 300
tls_ca_cert_path = "/etc/mantis/certs/ca.crt"
tls_cert_path = "/etc/mantis/certs/client.crt"
tls_key_path = "/etc/mantis/certs/client.key"
FieldTypeDefaultRequiredDescription
orchestration_urlstring"https://localhost:50051"NoThorax gRPC URL. Env: MANDIBLE__GRPC__ORCHESTRATION_URL
connect_timeout_secsinteger5NoConnection timeout
request_timeout_secsinteger300NoRequest timeout (5 minutes for long-running operations)
tls_ca_cert_pathstring-NoCA certificate for TLS verification. Env: MANDIBLE__GRPC__TLS_CA_CERT_PATH
tls_cert_pathstring-NoClient certificate for mTLS. Env: MANDIBLE__GRPC__TLS_CERT_PATH
tls_key_pathstring-NoClient private key for mTLS. Env: MANDIBLE__GRPC__TLS_KEY_PATH

Retry configuration for transient gRPC failures. Only read-only operations are retried.

FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable retry for read-only operations
max_retriesinteger3NoMaximum retry attempts
initial_delay_msinteger100NoInitial delay before first retry (ms)
max_delay_msinteger5000NoMaximum delay between retries (ms)

Circuit breaker to prevent cascading failures.

FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable circuit breaker
failure_thresholdinteger5NoConsecutive failures before circuit opens
success_thresholdinteger2NoSuccesses in half-open state before closing
cooldown_secsinteger30NoHow long circuit stays open (seconds)

Internal gRPC server for Thorax-to-Mandible communication. Uses mTLS for authentication.

[internal_grpc]
enabled = true
host = "0.0.0.0"
port = 50052
tls_cert_path = "/etc/mantis/certs/internal.crt"
tls_key_path = "/etc/mantis/certs/internal.key"
tls_ca_cert_path = "/etc/mantis/certs/ca.crt"
FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoEnable the internal gRPC server. Also reads MANDIBLE__INTERNAL_GRPC__ENABLED
hoststring"0.0.0.0"NoBind address. Also reads MANDIBLE__INTERNAL_GRPC__HOST
portinteger50052NoListen port. Also reads MANDIBLE__INTERNAL_GRPC__PORT
tls_cert_pathstring-Yes (if enabled)Server TLS certificate. Also reads MANDIBLE__INTERNAL_GRPC__TLS_CERT_PATH
tls_key_pathstring-Yes (if enabled)Server TLS private key. Also reads MANDIBLE__INTERNAL_GRPC__TLS_KEY_PATH
tls_ca_cert_pathstring-Yes (if enabled)CA certificate for client verification. Also reads MANDIBLE__INTERNAL_GRPC__TLS_CA_CERT_PATH
request_timeout_secsinteger300NoRequest timeout (seconds)
max_connectionsinteger100NoMaximum concurrent connections

API rate limiting settings.

[rate_limit]
enabled = true
requests_per_second = 100
burst_size = 200
FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable rate limiting
requests_per_secondinteger100NoMax requests per second per IP
burst_sizeinteger200NoBurst size (max instant requests)

Authentication-specific rate limiting for brute force protection.

FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable auth rate limiting
login_attempts_per_minuteinteger10NoMax failed login attempts per minute per IP
lockout_duration_secsinteger900NoLockout duration after exceeding limit (15 minutes)
password_change_attempts_per_hourinteger10NoMax password-change attempts per hour per IP (not yet enforced — reserved)
registration_attempts_per_hourinteger10NoMax registration attempts per hour per IP (not yet enforced — reserved)

Trusted reverse proxy configuration for X-Forwarded-For header processing.

FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoTrust X-Forwarded-For from configured proxies
addressesarray[]NoTrusted proxy IP addresses or CIDR ranges

Server identity for the /server/info discovery endpoint.

[identity]
server_name = "Mandible Server"
server_cert_path = "/etc/mantis/certs/server.crt"
registration_enabled = true
FieldTypeDefaultRequiredDescription
server_namestring"Mandible Server"NoHuman-readable server name
server_cert_pathstring-NoPath to server TLS certificate for thumbprint calculation
server_thumbprintstring-NoPre-calculated server thumbprint (SHA256 hex)
registration_enabledbooleantrueNoWhether new client registration is enabled

Tokio-console settings for async runtime debugging. Only active when the tokio-console feature is enabled.

[console]
enabled = true
address = "127.0.0.1"
port = 6670
retention_secs = 60
publish_interval_ms = 1000
FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoEnable the tokio-console server
addressstring"127.0.0.1"NoBind address
portinteger0NoConsole port. The serde default is the sentinel 0 (OS-assigned ephemeral port). Set this explicitly to 6670 (the conventional Mandible port) to use tokio-console; leaving it unset binds to an unpredictable ephemeral port
retention_secsinteger60NoHow long to retain completed task data
publish_interval_msinteger1000NoUpdate interval for connected clients (ms)
recording_pathstring-NoPath to record console data for offline analysis

Audit logging configuration with per-tenant cryptographic hash chains.

[audit]
enabled = true
batch_size = 100
flush_interval_secs = 1
channel_buffer = 10000
max_retries = 3
FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable audit logging
batch_sizeinteger100NoMaximum batch size before forced flush
flush_interval_secsinteger1NoMaximum time between flushes (seconds)
channel_bufferinteger10000NoAsync channel buffer size
max_retriesinteger3NoMaximum total attempts for database writes
dead_letter_pathstring-NoPath for dead-letter queue file (failed entries)

Server-Sent Events session and token configuration.

[sse]
token_ttl_secs = 60
session_ttl_secs = 3600
audience = "mantis-sse"
redis_url = "redis://127.0.0.1:6379"
redis_namespace = "default"
FieldTypeDefaultRequiredDescription
token_ttl_secsinteger60NoSSE token time-to-live (single-use, short-lived)
session_ttl_secsinteger3600NoSSE session time-to-live (1 hour)
audiencestring"mantis-sse"NoSSE token audience claim
redis_urlstring"redis://127.0.0.1:6379"NoRedis URL for SSE state. Also reads SSE_REDIS_URL env var
redis_namespacestring"default"NoRedis key namespace

RabbitMQ queue settings for command dispatch. TLS is mandatory.

[queue]
enabled = true
host = "rabbitmq.internal"
port = 5671
username = "mantis"
password = "secret"
vhost = "/"
ca_cert_path = "/etc/mantis/certs/rabbitmq-ca.crt"
prefetch_count = 10
publisher_confirms = true
fallback_on_failure = true
health_check_interval_secs = 10
FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoEnable RabbitMQ dispatch. Also reads MANDIBLE__QUEUE__ENABLED
hoststring"localhost"NoRabbitMQ host. Also reads MANDIBLE__QUEUE__HOST
portinteger5671NoAMQPS port (TLS only). Also reads MANDIBLE__QUEUE__PORT
usernamestring""NoRabbitMQ username. Also reads MANDIBLE__QUEUE__USERNAME
passwordstring""NoRabbitMQ password. Also reads MANDIBLE__QUEUE__PASSWORD
vhoststring"/"NoVirtual host. Also reads MANDIBLE__QUEUE__VHOST
ca_cert_pathstring-Yes (if enabled)CA certificate for TLS. Also reads MANDIBLE__QUEUE__CA_CERT_PATH
client_cert_pathstring-NoClient certificate for mTLS
client_key_pathstring-NoClient private key for mTLS
prefetch_countinteger10NoConsumer prefetch count
publisher_confirmsbooleantrueNoEnable publisher confirms for guaranteed delivery
fallback_on_failurebooleantrueNoFall back to polling when RabbitMQ is unavailable. Also reads MANDIBLE__QUEUE__FALLBACK_ON_FAILURE
health_check_interval_secsinteger10NoHealth check interval (seconds). Also reads MANDIBLE__QUEUE__HEALTH_CHECK_INTERVAL_SECS

OIDC/SSO settings for redirect URL validation.

[oidc]
allowed_redirect_urls = ["https://app.example.com"]
allowed_redirect_domains = ["*.example.com"]
allow_localhost_redirect = false
allow_any_redirect = false
FieldTypeDefaultRequiredDescription
allowed_redirect_urlsarray[]NoExplicit list of allowed redirect URLs
allowed_redirect_domainsarray[]NoAllowed domains (supports *.example.com wildcards)
allow_localhost_redirectbooleantrue (debug), false (release)NoAllow redirects to localhost
allow_any_redirectbooleantrue (debug), false (release)NoAllow any redirect when no allowlist configured

Encryption settings for credential protection at rest (AES-256-GCM).

[encryption]
key = "base64-encoded-32-byte-key"
FieldTypeDefaultRequiredDescription
keystring-YesBase64-encoded 32-byte encryption key. Also reads MANTIS_ENCRYPTION_KEY or MANDIBLE__ENCRYPTION__KEY env var. Generate with: openssl rand -base64 32

File cache settings for S3/Git storage content caching.

[file_cache]
enabled = true
memory_max_size_bytes = 104857600
FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable file caching. Also reads MANDIBLE__FILE_CACHE__ENABLED
memory_max_size_bytesinteger104857600 (100 MB)NoMaximum memory cache size in bytes. Also reads MANDIBLE__FILE_CACHE__MEMORY_MAX_SIZE_BYTES

AI log analyzer for automated deployment failure analysis using LLM providers (Ollama, OpenAI-compatible).

[log_analyzer]
provider_type = "ollama"
api_url = "http://ollama:11434"
model = "granite4"
timeout_secs = 60
check_interval_secs = 5
batch_size = 10
max_input_length = 8192
temperature = 0.1
top_p = 0.9
max_tokens = 768
FieldTypeDefaultRequiredDescription
provider_typestring"ollama"NoLLM provider type: ollama or openai. Env: MANDIBLE__LOG_ANALYZER__PROVIDER_TYPE
api_urlstring"http://ollama:11434"NoLLM provider API URL. Also reads MANDIBLE__LOG_ANALYZER__API_URL
modelstring"granite4"NoModel name. Also reads MANDIBLE__LOG_ANALYZER__MODEL
timeout_secsinteger60NoRequest timeout. Also reads MANDIBLE__LOG_ANALYZER__TIMEOUT_SECS
check_interval_secsinteger5NoInterval between processing batches. Also reads MANDIBLE__LOG_ANALYZER__CHECK_INTERVAL_SECS
batch_sizeinteger10NoMax requests per batch. Also reads MANDIBLE__LOG_ANALYZER__BATCH_SIZE
max_input_lengthinteger8192NoMax log text input length (chars). Also reads MANDIBLE__LOG_ANALYZER__MAX_INPUT_LENGTH
temperaturefloat0.1NoLLM temperature. Also reads MANDIBLE__LOG_ANALYZER__TEMPERATURE
top_pfloat0.9NoNucleus sampling threshold. Also reads MANDIBLE__LOG_ANALYZER__TOP_P
max_tokensinteger768NoMax tokens to generate. Also reads MANDIBLE__LOG_ANALYZER__MAX_TOKENS
tls_ca_cert_pathstring-NoPath to custom CA certificate for TLS verification when connecting to LLM provider

Optional WireGuard transport configuration.

[wireguard]
enabled = true
relay_url = "wss://relay.example.com"
turn_shared_secret = "shared-secret"
FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoEnable WireGuard transport
turn_serversarray-NoTURN servers for NAT traversal
turn_shared_secretstring-NoShared secret for TURN credentials
relay_urlstring-NoWebSocket relay URL for fallback transport
udp_endpointsarray-NoDirect UDP endpoints for hole-punching

All settings can be overridden with environment variables using the MANDIBLE__ prefix with double underscore separators:

MANDIBLE__SECTION__KEY=value

Examples:

SettingEnvironment Variable
server.portMANDIBLE__SERVER__PORT
database.urlDATABASE_URL
jwt.secretMANDIBLE__JWT__SECRET
cors.allowed_originsMANDIBLE__CORS__ALLOWED_ORIGINS (comma-separated)
auth.lens_base_urlMANDIBLE__AUTH__LENS_BASE_URL
grpc.orchestration_urlMANDIBLE__GRPC__ORCHESTRATION_URL

See Environment Variables for complete reference.

mandible.toml
[server]
host = "0.0.0.0"
port = 3000
request_timeout_secs = 30
[server.tls]
cert_path = "/etc/mantis/certs/server.crt"
key_path = "/etc/mantis/certs/server.key"
[database]
url = "postgres://mantis:secret@db.example.com:5432/mantis?sslmode=verify-full"
max_connections = 20
min_idle = 5
[jwt]
algorithm = "RS256"
private_key_path = "/etc/mantis/jwt/private.pem"
public_key_path = "/etc/mantis/jwt/public.pem"
access_token_expiry_secs = 28800
refresh_token_expiry_secs = 604800
issuer = "mandible"
[cors]
allowed_origins = ["https://lens.example.com"]
allow_credentials = true
max_age_secs = 3600
[cookie]
refresh_token_name = "mantis_refresh_token"
secure = true
same_site = "Lax"
domain = ".example.com"
[auth]
lens_base_url = "https://lens.example.com/login"
[grpc]
orchestration_url = "https://thorax.internal:50051"
connect_timeout_secs = 5
request_timeout_secs = 300
tls_ca_cert_path = "/etc/mantis/certs/ca.crt"
[internal_grpc]
enabled = true
host = "0.0.0.0"
port = 50052
tls_cert_path = "/etc/mantis/certs/internal.crt"
tls_key_path = "/etc/mantis/certs/internal.key"
tls_ca_cert_path = "/etc/mantis/certs/ca.crt"
[queue]
enabled = true
host = "rabbitmq.internal"
port = 5671
username = "mantis"
password = "secret"
vhost = "/"
ca_cert_path = "/etc/mantis/certs/rabbitmq-ca.crt"
[audit]
enabled = true
[oidc]
allowed_redirect_urls = ["https://lens.example.com"]
allow_localhost_redirect = false
allow_any_redirect = false