Mandible Configuration
Mandible Configuration
Section titled “Mandible Configuration”Configure the Mandible REST API server for your deployment.
Configuration File
Section titled “Configuration File”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.
Configuration Sections
Section titled “Configuration Sections”[server]
Section titled “[server]”HTTP server settings.
[server]host = "0.0.0.0"port = 3000request_timeout_secs = 30external_url = "https://api.mantis.example.com"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
host | string | "0.0.0.0" | No | IP address to bind |
port | integer | 3000 | No | HTTP port |
request_timeout_secs | integer | 30 | No | Request timeout in seconds |
external_url | string | - | No | External URL for OAuth2 discovery endpoints. If not set, derived from host:port |
[server.tls]
Section titled “[server.tls]”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"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
cert_path | string | - | Yes (if TLS enabled) | Path to TLS certificate PEM file |
key_path | string | - | Yes (if TLS enabled) | Path to TLS private key PEM file |
[database]
Section titled “[database]”PostgreSQL connection settings.
[database]url = "postgres://mantis:password@localhost:5432/mantis"max_connections = 10min_idle = 2connection_timeout_secs = 10| Field | Type | Default | Required | Description |
|---|---|---|---|---|
url | string | DATABASE_URL env var | Yes | PostgreSQL connection URL. Startup fails with a config error if not set |
max_connections | integer | 10 | No | Maximum connection pool size |
min_idle | integer | 2 | No | Minimum idle connections |
connection_timeout_secs | integer | 10 | No | Connection 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 = 3600refresh_token_expiry_secs = 2592000issuer = "mandible"audience = "lens"key_id = "k1"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
algorithm | string | "HS256" | No | Signing algorithm: HS256 or RS256 |
secret | string | "" | Yes (HS256) | HMAC secret key (min 32 characters). Set via MANDIBLE__JWT__SECRET |
private_key_path | string | - | Yes (RS256) | Path to RSA private key PEM file |
public_key_path | string | - | Yes (RS256) | Path to RSA public key PEM file |
key_id | string | "k1" | No | Key ID for the current signing key (for key rotation) |
previous_secret | string | - | No | Previous secret for graceful HS256 key rotation |
previous_public_key_path | string | - | No | Previous public key path for graceful RS256 key rotation |
previous_key_id | string | - | No | Key ID for the previous key |
issuer | string | "mandible" | No | JWT issuer claim |
audience | string | "lens" | No | JWT audience claim |
access_token_expiry_secs | integer | 3600 | No | Access token lifetime (1 hour) |
refresh_token_expiry_secs | integer | 2592000 | No | Refresh token lifetime (30 days) |
[cors]
Section titled “[cors]”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 = truemax_age_secs = 3600| Field | Type | Default | Required | Description |
|---|---|---|---|---|
allowed_origins | array | ["https://localhost:5173", "http://localhost:5173", "https://localhost:4173", "http://localhost:4173"] | No | Allowed origins |
allowed_methods | array | ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] | No | Allowed HTTP methods |
allowed_headers | array | ["Content-Type", "Authorization", "Accept", "X-Request-ID"] | No | Allowed headers |
allow_credentials | boolean | true | No | Whether to allow credentials |
max_age_secs | integer | 3600 | No | Preflight cache duration in seconds |
[cookie]
Section titled “[cookie]”Cookie settings for authentication refresh tokens.
[cookie]refresh_token_name = "mantis_refresh_token"secure = truesame_site = "Lax"path = "/"domain = ".example.com"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
refresh_token_name | string | "mantis_refresh_token" | No | Cookie name for the refresh token |
secure | boolean | true (release), false (debug) | No | HTTPS-only cookies |
same_site | string | "Lax" | No | SameSite policy: Strict, Lax, or None |
path | string | "/" | No | Cookie path scope |
domain | string | - | No | Cookie domain. If not set, defaults to the origin domain |
[auth]
Section titled “[auth]”Authentication redirect settings.
[auth]lens_base_url = "https://lens.example.com/login"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
lens_base_url | string | "https://localhost:5173/login" | No | Lens UI login URL for redirects. Must be a valid HTTP/HTTPS URL |
[grpc]
Section titled “[grpc]”gRPC client settings for connecting to Thorax.
[grpc]orchestration_url = "https://thorax.example.com:50051"connect_timeout_secs = 5request_timeout_secs = 300tls_ca_cert_path = "/etc/mantis/certs/ca.crt"tls_cert_path = "/etc/mantis/certs/client.crt"tls_key_path = "/etc/mantis/certs/client.key"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
orchestration_url | string | "https://localhost:50051" | No | Thorax gRPC URL. Env: MANDIBLE__GRPC__ORCHESTRATION_URL |
connect_timeout_secs | integer | 5 | No | Connection timeout |
request_timeout_secs | integer | 300 | No | Request timeout (5 minutes for long-running operations) |
tls_ca_cert_path | string | - | No | CA certificate for TLS verification. Env: MANDIBLE__GRPC__TLS_CA_CERT_PATH |
tls_cert_path | string | - | No | Client certificate for mTLS. Env: MANDIBLE__GRPC__TLS_CERT_PATH |
tls_key_path | string | - | No | Client private key for mTLS. Env: MANDIBLE__GRPC__TLS_KEY_PATH |
[grpc.retry]
Section titled “[grpc.retry]”Retry configuration for transient gRPC failures. Only read-only operations are retried.
| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | true | No | Enable retry for read-only operations |
max_retries | integer | 3 | No | Maximum retry attempts |
initial_delay_ms | integer | 100 | No | Initial delay before first retry (ms) |
max_delay_ms | integer | 5000 | No | Maximum delay between retries (ms) |
[grpc.circuit_breaker]
Section titled “[grpc.circuit_breaker]”Circuit breaker to prevent cascading failures.
| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | true | No | Enable circuit breaker |
failure_threshold | integer | 5 | No | Consecutive failures before circuit opens |
success_threshold | integer | 2 | No | Successes in half-open state before closing |
cooldown_secs | integer | 30 | No | How long circuit stays open (seconds) |
[internal_grpc]
Section titled “[internal_grpc]”Internal gRPC server for Thorax-to-Mandible communication. Uses mTLS for authentication.
[internal_grpc]enabled = truehost = "0.0.0.0"port = 50052tls_cert_path = "/etc/mantis/certs/internal.crt"tls_key_path = "/etc/mantis/certs/internal.key"tls_ca_cert_path = "/etc/mantis/certs/ca.crt"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | false | No | Enable the internal gRPC server. Also reads MANDIBLE__INTERNAL_GRPC__ENABLED |
host | string | "0.0.0.0" | No | Bind address. Also reads MANDIBLE__INTERNAL_GRPC__HOST |
port | integer | 50052 | No | Listen port. Also reads MANDIBLE__INTERNAL_GRPC__PORT |
tls_cert_path | string | - | Yes (if enabled) | Server TLS certificate. Also reads MANDIBLE__INTERNAL_GRPC__TLS_CERT_PATH |
tls_key_path | string | - | Yes (if enabled) | Server TLS private key. Also reads MANDIBLE__INTERNAL_GRPC__TLS_KEY_PATH |
tls_ca_cert_path | string | - | Yes (if enabled) | CA certificate for client verification. Also reads MANDIBLE__INTERNAL_GRPC__TLS_CA_CERT_PATH |
request_timeout_secs | integer | 300 | No | Request timeout (seconds) |
max_connections | integer | 100 | No | Maximum concurrent connections |
[rate_limit]
Section titled “[rate_limit]”API rate limiting settings.
[rate_limit]enabled = truerequests_per_second = 100burst_size = 200| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | true | No | Enable rate limiting |
requests_per_second | integer | 100 | No | Max requests per second per IP |
burst_size | integer | 200 | No | Burst size (max instant requests) |
[rate_limit.auth]
Section titled “[rate_limit.auth]”Authentication-specific rate limiting for brute force protection.
| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | true | No | Enable auth rate limiting |
login_attempts_per_minute | integer | 10 | No | Max failed login attempts per minute per IP |
lockout_duration_secs | integer | 900 | No | Lockout duration after exceeding limit (15 minutes) |
password_change_attempts_per_hour | integer | 10 | No | Max password-change attempts per hour per IP (not yet enforced — reserved) |
registration_attempts_per_hour | integer | 10 | No | Max registration attempts per hour per IP (not yet enforced — reserved) |
[rate_limit.trusted_proxies]
Section titled “[rate_limit.trusted_proxies]”Trusted reverse proxy configuration for X-Forwarded-For header processing.
| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | false | No | Trust X-Forwarded-For from configured proxies |
addresses | array | [] | No | Trusted proxy IP addresses or CIDR ranges |
[identity]
Section titled “[identity]”Server identity for the /server/info discovery endpoint.
[identity]server_name = "Mandible Server"server_cert_path = "/etc/mantis/certs/server.crt"registration_enabled = true| Field | Type | Default | Required | Description |
|---|---|---|---|---|
server_name | string | "Mandible Server" | No | Human-readable server name |
server_cert_path | string | - | No | Path to server TLS certificate for thumbprint calculation |
server_thumbprint | string | - | No | Pre-calculated server thumbprint (SHA256 hex) |
registration_enabled | boolean | true | No | Whether new client registration is enabled |
[console]
Section titled “[console]”Tokio-console settings for async runtime debugging. Only active when the tokio-console feature is enabled.
[console]enabled = trueaddress = "127.0.0.1"port = 6670retention_secs = 60publish_interval_ms = 1000| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | false | No | Enable the tokio-console server |
address | string | "127.0.0.1" | No | Bind address |
port | integer | 0 | No | Console 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_secs | integer | 60 | No | How long to retain completed task data |
publish_interval_ms | integer | 1000 | No | Update interval for connected clients (ms) |
recording_path | string | - | No | Path to record console data for offline analysis |
[audit]
Section titled “[audit]”Audit logging configuration with per-tenant cryptographic hash chains.
[audit]enabled = truebatch_size = 100flush_interval_secs = 1channel_buffer = 10000max_retries = 3| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | true | No | Enable audit logging |
batch_size | integer | 100 | No | Maximum batch size before forced flush |
flush_interval_secs | integer | 1 | No | Maximum time between flushes (seconds) |
channel_buffer | integer | 10000 | No | Async channel buffer size |
max_retries | integer | 3 | No | Maximum total attempts for database writes |
dead_letter_path | string | - | No | Path for dead-letter queue file (failed entries) |
Server-Sent Events session and token configuration.
[sse]token_ttl_secs = 60session_ttl_secs = 3600audience = "mantis-sse"redis_url = "redis://127.0.0.1:6379"redis_namespace = "default"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
token_ttl_secs | integer | 60 | No | SSE token time-to-live (single-use, short-lived) |
session_ttl_secs | integer | 3600 | No | SSE session time-to-live (1 hour) |
audience | string | "mantis-sse" | No | SSE token audience claim |
redis_url | string | "redis://127.0.0.1:6379" | No | Redis URL for SSE state. Also reads SSE_REDIS_URL env var |
redis_namespace | string | "default" | No | Redis key namespace |
[queue]
Section titled “[queue]”RabbitMQ queue settings for command dispatch. TLS is mandatory.
[queue]enabled = truehost = "rabbitmq.internal"port = 5671username = "mantis"password = "secret"vhost = "/"ca_cert_path = "/etc/mantis/certs/rabbitmq-ca.crt"prefetch_count = 10publisher_confirms = truefallback_on_failure = truehealth_check_interval_secs = 10| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | false | No | Enable RabbitMQ dispatch. Also reads MANDIBLE__QUEUE__ENABLED |
host | string | "localhost" | No | RabbitMQ host. Also reads MANDIBLE__QUEUE__HOST |
port | integer | 5671 | No | AMQPS port (TLS only). Also reads MANDIBLE__QUEUE__PORT |
username | string | "" | No | RabbitMQ username. Also reads MANDIBLE__QUEUE__USERNAME |
password | string | "" | No | RabbitMQ password. Also reads MANDIBLE__QUEUE__PASSWORD |
vhost | string | "/" | No | Virtual host. Also reads MANDIBLE__QUEUE__VHOST |
ca_cert_path | string | - | Yes (if enabled) | CA certificate for TLS. Also reads MANDIBLE__QUEUE__CA_CERT_PATH |
client_cert_path | string | - | No | Client certificate for mTLS |
client_key_path | string | - | No | Client private key for mTLS |
prefetch_count | integer | 10 | No | Consumer prefetch count |
publisher_confirms | boolean | true | No | Enable publisher confirms for guaranteed delivery |
fallback_on_failure | boolean | true | No | Fall back to polling when RabbitMQ is unavailable. Also reads MANDIBLE__QUEUE__FALLBACK_ON_FAILURE |
health_check_interval_secs | integer | 10 | No | Health check interval (seconds). Also reads MANDIBLE__QUEUE__HEALTH_CHECK_INTERVAL_SECS |
[oidc]
Section titled “[oidc]”OIDC/SSO settings for redirect URL validation.
[oidc]allowed_redirect_urls = ["https://app.example.com"]allowed_redirect_domains = ["*.example.com"]allow_localhost_redirect = falseallow_any_redirect = false| Field | Type | Default | Required | Description |
|---|---|---|---|---|
allowed_redirect_urls | array | [] | No | Explicit list of allowed redirect URLs |
allowed_redirect_domains | array | [] | No | Allowed domains (supports *.example.com wildcards) |
allow_localhost_redirect | boolean | true (debug), false (release) | No | Allow redirects to localhost |
allow_any_redirect | boolean | true (debug), false (release) | No | Allow any redirect when no allowlist configured |
[encryption]
Section titled “[encryption]”Encryption settings for credential protection at rest (AES-256-GCM).
[encryption]key = "base64-encoded-32-byte-key"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
key | string | - | Yes | Base64-encoded 32-byte encryption key. Also reads MANTIS_ENCRYPTION_KEY or MANDIBLE__ENCRYPTION__KEY env var. Generate with: openssl rand -base64 32 |
[file_cache]
Section titled “[file_cache]”File cache settings for S3/Git storage content caching.
[file_cache]enabled = truememory_max_size_bytes = 104857600| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | true | No | Enable file caching. Also reads MANDIBLE__FILE_CACHE__ENABLED |
memory_max_size_bytes | integer | 104857600 (100 MB) | No | Maximum memory cache size in bytes. Also reads MANDIBLE__FILE_CACHE__MEMORY_MAX_SIZE_BYTES |
[log_analyzer]
Section titled “[log_analyzer]”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 = 60check_interval_secs = 5batch_size = 10max_input_length = 8192temperature = 0.1top_p = 0.9max_tokens = 768| Field | Type | Default | Required | Description |
|---|---|---|---|---|
provider_type | string | "ollama" | No | LLM provider type: ollama or openai. Env: MANDIBLE__LOG_ANALYZER__PROVIDER_TYPE |
api_url | string | "http://ollama:11434" | No | LLM provider API URL. Also reads MANDIBLE__LOG_ANALYZER__API_URL |
model | string | "granite4" | No | Model name. Also reads MANDIBLE__LOG_ANALYZER__MODEL |
timeout_secs | integer | 60 | No | Request timeout. Also reads MANDIBLE__LOG_ANALYZER__TIMEOUT_SECS |
check_interval_secs | integer | 5 | No | Interval between processing batches. Also reads MANDIBLE__LOG_ANALYZER__CHECK_INTERVAL_SECS |
batch_size | integer | 10 | No | Max requests per batch. Also reads MANDIBLE__LOG_ANALYZER__BATCH_SIZE |
max_input_length | integer | 8192 | No | Max log text input length (chars). Also reads MANDIBLE__LOG_ANALYZER__MAX_INPUT_LENGTH |
temperature | float | 0.1 | No | LLM temperature. Also reads MANDIBLE__LOG_ANALYZER__TEMPERATURE |
top_p | float | 0.9 | No | Nucleus sampling threshold. Also reads MANDIBLE__LOG_ANALYZER__TOP_P |
max_tokens | integer | 768 | No | Max tokens to generate. Also reads MANDIBLE__LOG_ANALYZER__MAX_TOKENS |
tls_ca_cert_path | string | - | No | Path to custom CA certificate for TLS verification when connecting to LLM provider |
[wireguard]
Section titled “[wireguard]”Optional WireGuard transport configuration.
[wireguard]enabled = truerelay_url = "wss://relay.example.com"turn_shared_secret = "shared-secret"| Field | Type | Default | Required | Description |
|---|---|---|---|---|
enabled | boolean | false | No | Enable WireGuard transport |
turn_servers | array | - | No | TURN servers for NAT traversal |
turn_shared_secret | string | - | No | Shared secret for TURN credentials |
relay_url | string | - | No | WebSocket relay URL for fallback transport |
udp_endpoints | array | - | No | Direct UDP endpoints for hole-punching |
Environment Variables
Section titled “Environment Variables”All settings can be overridden with environment variables using the MANDIBLE__ prefix with double underscore separators:
MANDIBLE__SECTION__KEY=valueExamples:
| Setting | Environment Variable |
|---|---|
server.port | MANDIBLE__SERVER__PORT |
database.url | DATABASE_URL |
jwt.secret | MANDIBLE__JWT__SECRET |
cors.allowed_origins | MANDIBLE__CORS__ALLOWED_ORIGINS (comma-separated) |
auth.lens_base_url | MANDIBLE__AUTH__LENS_BASE_URL |
grpc.orchestration_url | MANDIBLE__GRPC__ORCHESTRATION_URL |
See Environment Variables for complete reference.
Complete Example
Section titled “Complete Example”Production Configuration
Section titled “Production Configuration”[server]host = "0.0.0.0"port = 3000request_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 = 20min_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 = 28800refresh_token_expiry_secs = 604800issuer = "mandible"
[cors]allowed_origins = ["https://lens.example.com"]allow_credentials = truemax_age_secs = 3600
[cookie]refresh_token_name = "mantis_refresh_token"secure = truesame_site = "Lax"domain = ".example.com"
[auth]lens_base_url = "https://lens.example.com/login"
[grpc]orchestration_url = "https://thorax.internal:50051"connect_timeout_secs = 5request_timeout_secs = 300tls_ca_cert_path = "/etc/mantis/certs/ca.crt"
[internal_grpc]enabled = truehost = "0.0.0.0"port = 50052tls_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 = truehost = "rabbitmq.internal"port = 5671username = "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 = falseallow_any_redirect = falseNext Steps
Section titled “Next Steps”- Thorax Configuration - Orchestration server
- Environment Variables - Variable reference
- Security Overview - Security settings
