Configuration Reference
Complete reference for all configuration directives, auto-generated from the Hexon Gateway source code. Each section corresponds to a TOML section in /etc/hexon/.
Precedence (highest to lowest): Environment variables (HEXON_*) > GitOps repository > TOML files > Built-in defaults.
Hot-reload: Most sections reload within 1 second of file changes — no restart needed.
Core Service
TOML: [service] · Env: HEXON_SERVICE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
hostname | string | — | Public hostname for the gateway Sets OIDC issuer URL, SAML metadata base URL, and ACME CA external URL. Changing post-deployment invalidates existing OIDC tokens and SAML SP registrations Required. |
port | int | 443 | HTTPS port to listen on Ports below 1024 require elevated privileges or CAP_NET_BIND_SERVICE Range: 1–65535. |
public_port | int | none | Public-facing port for URL generation when behind NAT/LB Set when behind a load balancer on a different port than service.port |
auto_tls | bool | false | Issue wildcard TLS cert from internal ACME CA Uses internal ACME CA; must not be used together with acme_client. Wildcard covers *.hostname Requires hostname. |
auto_tls_renewal | duration | 720h | AutoTLS renewal cycle Must be less than auto_tls_validity; overlap enforced at 20-80% of validity Requires auto_tls=true. |
auto_tls_validity | duration | 1440h | AutoTLS certificate validity Must be greater than auto_tls_renewal; default 1440h = 60 days Requires auto_tls=true. |
network_interface | string | eth0 | Network interface to bind to Default for cluster.cluster_interface, health.interface, vpn.network_interface, and bastion.network_interface when not set explicitly |
releases_url | string | https://downloads.hexon.io/releases | Base URL for release artifacts and version manifest |
enable_portal | bool (optional) | true | Enable unified portal SPA at /profile |
admin_socket | bool (optional) | true | Enable Unix socket for local admin CLI access Allows ‘hexon admin <command>’ on the server host without bastion |
admin_socket_path | string | /tmp/hexon-admin.sock | Unix socket path for admin CLI Override with HEXON_ADMIN_SOCK env var on the client side |
read_timeout | duration | 30s | HTTP read timeout WebSocket and streaming responses may require longer values |
write_timeout | duration | 30s | HTTP write timeout Applies to entire response delivery; set higher for large file downloads or streaming |
idle_timeout | duration | 120s | HTTP idle connection timeout |
max_header_bytes | string | 64KB | Maximum HTTP request header size |
graceful_shutdown_timeout | duration | 30s | Total time to wait for graceful shutdown Max: 10m. |
ikev2_shutdown_timeout | duration | 15s | Max time for IKEv2 client notification during shutdown Max: 10m. |
listener_drain_timeout | duration | 10s | Max time for listener connection draining during shutdown Max: 10m. |
background_task_timeout | duration | 5s | Max time for background goroutines to stop during shutdown Max: 10m. |
http2_enable | bool | true | Enable HTTP/2 support When false, JA4H fingerprinting and HTTP/2 server push are also disabled |
http2_maxstreams | int | 1000 | Max concurrent HTTP/2 streams per connection Max: 1000000. |
http2_maxframesize | int | 1048576 | Max HTTP/2 frame size in bytes Max: 16777216. |
http2_idletimeout | duration | 120s | HTTP/2 idle timeout |
http2_keepalive | bool | true | Enable HTTP/2 keepalive pings |
http2_keepalive_interval | duration | 30s | HTTP/2 keepalive ping interval |
http2_push_enabled | bool | true | Enable HTTP/2 server push Only effective when http2_enable is true |
http2_push_max_resources | int | 8 | Max resources to push per HTTP/2 request |
http2_push_timeout | duration | 100ms | HTTP/2 push operation timeout |
http2_push_cache_enabled | bool | true | Enable push cache to avoid redundant HTTP/2 pushes |
http2_push_cache_ttl | duration | 1h | HTTP/2 push cache TTL |
http2_push_only_secure | bool | true | Only push resources over secure connections |
http3_enable | bool | false | Enable HTTP/3 over QUIC alongside HTTP/2 Requires UDP port open on firewall. Activates QUIC affinity and 0-RTT replay tracking |
http3_idle_timeout | duration | 30s | QUIC idle timeout |
http3_max_streams | duration | 100 | Max bidirectional QUIC streams per connection Range: 0–1000000. |
http3_max_uni_streams | duration | 100 | Max unidirectional QUIC streams per connection Range: 0–1000000. |
http3_allow_0rtt | bool | true | Allow 0-RTT early data with replay protection |
http3_altsvc_max_age | duration | 24h | Alt-Svc header max-age |
http3_0rtt_token_ttl | duration | 2m | HTTP/3 0-RTT replay protection token TTL |
quic_affinity_enabled | bool | false | Enable QUIC affinity routing via UDP fingerprint Routes QUIC connections to the same cluster node based on connection ID |
quic_cid_mapping_limit | int | 100000 | Max tracked QUIC connection IDs |
quic_affinity_idle_timeout | duration | 5m | Idle timeout for QUIC CID mappings |
quic_migration_max_per_conn | int | 10 | Max QUIC migrations per connection before rejection Range: 0–100. |
quic_migration_cooldown | duration | 1s | Minimum time between QUIC migrations |
quic_migration_ttl | duration | 30m | Idle QUIC connection tracking timeout |
quic_migration_cleanup | duration | 5m | QUIC expired connection cleanup interval |
quic_0rtt_token_ttl | duration | 2m | QUIC 0-RTT token validity duration |
quic_0rtt_bind_to_ip | bool | true | Require IP match for QUIC 0-RTT token use |
quic_0rtt_max_tokens | int | 100000 | Maximum QUIC 0-RTT tokens to track per node Range: 0–10000000. |
quic_0rtt_cleanup | duration | 1m | QUIC 0-RTT token cleanup interval |
handshake_timeout | duration | 10s | TLS handshake timeout |
block_malformed_tls | bool | false | Block malformed TLS connections Rejects TLS connections with invalid ClientHello; may block legacy clients |
tls_min_version | string | 1.3 | Minimum TLS version for inbound connections Values: 1.2, 1.3. |
tls_max_version | string | — | Maximum TLS version for inbound connections Defaults to latest supported version if not set Values: 1.2, 1.3. |
tls_session_tickets | bool | false | Enable TLS session tickets Disabled by default for forward secrecy |
tls_renegotiation | bool | false | Allow TLS renegotiation Disabled by default for security |
tls_prefer_server_ciphers | bool | true | Server prefers its own cipher suite order |
tls_strict_cipher_suites | bool | true | Use only AEAD ciphers with forward secrecy |
outbound_tls_min_version | string | 1.3 | Minimum TLS version for outbound connections to backends Does not affect internal cluster (hexdcall) which always uses TLS 1.3 Values: 1.2, 1.3. |
pqc | bool (optional) | true | Enable hybrid post-quantum key exchange ML-KEM-768 + X25519 for service TLS RFC FIPS203. |
mtls_mode | string | none | Client certificate requirement level With proxy=true and mandatory mode, proxy_header_clientcert is required Values: none, optional, mandatory. |
x509_auto_auth | bool (optional) | true | Auto-authenticate clients presenting a valid TLS client certificate |
fingerprinting_enabled | bool | false | Enable composite client fingerprinting (TLS+HTTP/2+TCP) Enables JA4 TLS fingerprint extraction; used for affinity routing and security analytics |
fingerprint_max_entries | int | 10000 | Maximum fingerprint entries in cache |
fingerprint_ttl | duration | 5m | Base TTL for fingerprint cache entries |
fingerprint_cleanup | duration | 30s | Fingerprint cache cleanup interval |
quic_fingerprint_reassembly_max_packets | int | 10 | Max packets for QUIC ClientHello reassembly |
quic_fingerprint_reassembly_max_bytes | string | 15KB | Max bytes for QUIC reassembly buffer |
quic_fingerprint_reassembly_timeout | duration | 5s | QUIC reassembly state timeout |
ja4_format | string | composite | JA4 fingerprint format: composite (internal optimized) or canonical (FoxIO JA4 standard) canonical enables interop with Wireshark, Zeek, and threat intel feeds |
ja4_max_extensions | int | 200 | Max TLS extensions to parse for JA4 fingerprinting Typical clients send 10-30 extensions |
ja4_max_sigalgs | int | 100 | Max signature algorithms to parse for JA4 fingerprinting Typical clients send 10-20 signature algorithms |
http2_fingerprint_cache_size | int | 10000 | Max entries in HTTP/2 fingerprint cache |
http2_fingerprint_cache_evict_pct | int | 10 | Percentage of oldest entries to evict when HTTP/2 fingerprint cache is full |
fingerprint_max_entries_per_ip | int | 10 | Max fingerprint entries per client IP for anti-abuse |
quic_max_crypto_frame_offset | string | 64KB | Max QUIC CRYPTO frame offset for DoS protection |
proxy | bool | false | Enable proxy mode when behind a reverse proxy, load balancer, or CDN Requires proxy_header_clientip and proxy_cidr when enabled |
proxy_cidr | []string | — | Trusted proxy IP ranges for header trust Required when proxy=true; prevents header spoofing Requires proxy=true. |
hexon_edge_protocol | bool | false | Enable Hexon Edge Protocol for edge-to-gateway communication Set true when edge.enabled in Helm; parses HXEP header for real client IP |
hexon_edge_cidr | []string | — | Trusted CIDRs for Hexon Edge Protocol header parsing Defaults to trust-all (0.0.0.0/0, ::/0); set to pod network CIDR in production |
proxy_header_clientip | string | — | HTTP header containing real client IP from proxy Required when proxy=true Requires proxy=true. |
proxy_header_clientcert | string | — | HTTP header containing client certificate from proxy for mTLS passthrough |
proxy_header_clientfingerprint | string | — | HTTP header containing client fingerprint from proxy, replaces JA4 |
proxy_header_traceid | string | — | HTTP header containing trace ID from proxy for distributed tracing |
preserve_client_port | bool | true | Use client connection port in redirects for NAT/LB port mapping |
correlation_id_header | string | X-Hexon-ID | HTTP header name for request correlation ID |
disable_server_header | bool | false | Disable the Server response header |
security_headers_enabled | bool | true | Enable security response headers |
x_frame_options | string | DENY | X-Frame-Options header value Also supports ALLOW-FROM uri Values: DENY, SAMEORIGIN. |
x_content_type_options | string | nosniff | X-Content-Type-Options header value |
x_xss_protection | string | 1; mode=block | X-XSS-Protection header value Values: 0, 1, 1; mode=block. |
content_security_policy | string | — | Content-Security-Policy header value Empty means no CSP header; max 8192 characters |
e2oe | bool | false | Enable End-to-Origin Encryption (requires PoW) |
e2oe_strict | bool | false | No degradation — reject all requests without E2OE channel Requires e2oe=true. |
compression_enabled | bool | true | Enable response compression |
compression_level | string | balanced | Response compression level Values: none, fast, balanced, best. |
config_hot_reload_enabled | bool | true | Enable automatic config hot-reload on file changes |
config_file_watching_enabled | bool | true | Enable file system monitoring for config changes |
config_cache_enabled | bool | true | Enable config section caching for faster access |
config_cache_max_entries | int | 100 | Maximum config cache entries Range: 0–10000. |
config_callback_throttle_ms | int | 100 | Config change callback throttle window in milliseconds Range: 0–10000. |
config_poll_interval_ms | int | 1000 | Config file polling interval in milliseconds Range: 100–60000. |
config_diff_history_enabled | bool | true | Store config change history in a ring buffer |
config_diff_history_size | int | 10 | Maximum config diff entries to retain Range: 1–100. Requires config_diff_history_enabled=true. |
inline_assets | bool | true | Embed CSS/JS directly in HTML responses Set false for external asset serving via CDN |
hide_status | bool (optional) | true | Hide HTTP status codes in user-facing message pages |
default_language | string | en | Default UI language code |
detect_browser_language | bool (optional) | true | Auto-detect language from browser Accept-Language header |
disclaimer | string | By logging in, you agree to acceptable use policy and monitoring terms. | Footer disclaimer text for emails and forms |
cookie_notice | bool (optional) | true | Show informational cookie notice banner Informational only — all cookies are essential and exempt from consent |
privacy_policy_url | string | — | Privacy policy URL linked from cookie notice Shows ‘More info’ link when set |
cookie_name | string | hexon | Default cookie name for sessions |
cookie_domain | string | — | Cookie domain for cross-subdomain session sharing Empty means current hostname only |
cookie_ttl | duration | 12h | Default session cookie TTL |
session_ttl | duration | 24h | Authenticated user session TTL |
session_password_expired | duration | 15m | Password expired session TTL |
session_mfa_pending | duration | 5m | MFA pending session TTL |
max_concurrent_sessions | int | 1 | Maximum concurrent sessions per user Set to 0 for unlimited |
runtime_metrics | bool | true | Enable runtime package metrics collection |
runtime_metrics_ttl | duration | 24h | Retention window for runtime metrics |
runtime_metrics_queue | int | 10000 | Event queue size for runtime metrics Range: 0–1000000. |
runtime_metrics_exporter | bool | false | Enable Prometheus metrics exporter endpoint |
runtime_metrics_port | int | 9090 | Prometheus metrics exporter listen port Range: 1–65535. |
runtime_metrics_network_interface | string | eth0 | Network interface for metrics exporter listener |
runtime_metrics_allow_from | []string | — | CIDR ranges allowed to scrape Prometheus metrics Empty means no IP restrictions; restrict to Prometheus scraper CIDRs in production |
debug_mode | bool | false | Enable Server-Timing debug headers with request tracing Exposes internal timing and infrastructure details; use only for debugging |
geo_enabled | bool | false | Enable geo-IP access restrictions |
geo_database | string | none | Path to MaxMind GeoLite2-Country.mmdb database Required when geo_enabled=true. Download from MaxMind GeoLite2 |
geo_asn_database | string | none | Path to MaxMind GeoLite2-ASN.mmdb database Required only when geo_allow_asn or geo_deny_asn rules are configured |
geo_allow_countries | []string | none | ISO 3166-1 alpha-2 country codes to allow Empty means allow all countries |
geo_deny_countries | []string | none | ISO 3166-1 alpha-2 country codes to deny |
geo_allow_asn | []string | none | ASN numbers to allow |
geo_deny_asn | []string | none | ASN numbers to deny |
geo_bypass_cidr | []string | none | CIDRs that bypass geo-IP checks |
geo_deny_code | int | 403 | HTTP status code for geo-IP denial Range: 400–599. |
geo_deny_message | string | Access denied from your location. | Custom message shown on geo-IP denial |
geo_country_header | string | — | CDN header containing ISO country code, skips MaxMind lookup Requires proxy=true; common values: CF-IPCountry, CloudFront-Viewer-Country |
time_enabled | bool | false | Enable time-based access restrictions Global default inherited by proxy, VPN, bastion, forward_proxy, tcp_proxy, and webshell; each can override |
time_bypass_cidr | []string | none | CIDRs that bypass time-based checks Service-level bypass; per-service bypass CIDRs are merged with this list |
time_deny_code | int | 403 | HTTP status code for time-based denial Range: 400–599. |
time_deny_message | string | Access not permitted at this time. | Custom message shown on time-based denial |
time_default_timezone | string | UTC | Default IANA timezone for time-based restrictions |
time_default_allow_days | []string | — | Default allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
time_default_deny_days | []string | — | Default denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
time_default_allow_hours | string | — | Default allowed hours range in 24h format Format: HH:MM-HH:MM |
time_default_deny_hours | string | — | Default denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Cross-Origin Resource Sharing configuration for API endpoints
TOML: [service.cors] · Env: HEXON_SERVICE_CORS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable Cross-Origin Resource Sharing |
allowed_origins | []string | — | Allowed CORS origins Required when CORS is enabled; use * for all origins (not with credentials) Requires enabled=true. |
allow_credentials | bool | false | Allow cookies and credentials in CORS requests Cannot be true when allowed_origins contains * Requires enabled=true. |
allowed_methods | []string | — | Allowed HTTP methods for CORS Values: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS. Requires enabled=true. |
allowed_headers | []string | — | Allowed request headers for CORS Requires enabled=true. |
exposed_headers | []string | — | Response headers exposed to browser via CORS Requires enabled=true. |
max_age | int | 3600 | CORS preflight response cache duration in seconds Range: 0–86400. Requires enabled=true. |
UI theme configuration for colors and branding (hot-reloadable)
TOML: [service.theme] · Env: HEXON_SERVICE_THEME_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
mode | string | auto | Theme behavior mode Values: light, dark, auto. |
allow_user_override | bool (optional) | true | Allow browser to select dark/light based on OS preferences Only applies when mode is auto |
Color configuration for theme
TOML: [service.theme.colors] · Env: HEXON_SERVICE_THEME_COLORS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
success | string | 142 71% 45% | Success state color in HSL format |
warning | string | 38 92% 50% | Warning state color in HSL format |
info | string | 217 91% 60% | Info state color in HSL format |
radius | string | 0.5rem | Border radius as CSS length value |
Light mode color overrides
TOML: [service.theme.colors.light] · Env: HEXON_SERVICE_THEME_COLORS_LIGHT_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
background | string | — | Page background color in HSL format Light default: 60 9% 98%; Dark default: 60 3% 15% |
foreground | string | — | Primary text color in HSL format |
card | string | — | Card/panel background color in HSL format |
card_foreground | string | — | Card text color in HSL format |
primary | string | — | Primary action color in HSL format |
primary_hover | string | — | Primary hover state color in HSL format |
primary_foreground | string | — | Primary action text color in HSL format |
secondary | string | — | Secondary action color in HSL format |
secondary_hover | string | — | Secondary hover state color in HSL format |
destructive | string | — | Destructive action color in HSL format |
destructive_foreground | string | — | Destructive action text color in HSL format |
muted | string | — | Muted background color in HSL format |
muted_foreground | string | — | Muted text color in HSL format |
accent | string | — | Accent background color in HSL format |
accent_foreground | string | — | Accent text color in HSL format |
border | string | — | Border color in HSL format |
input | string | — | Input border color in HSL format |
Dark mode color overrides
TOML: [service.theme.colors.dark] · Env: HEXON_SERVICE_THEME_COLORS_DARK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
background | string | — | Page background color in HSL format Light default: 60 9% 98%; Dark default: 60 3% 15% |
foreground | string | — | Primary text color in HSL format |
card | string | — | Card/panel background color in HSL format |
card_foreground | string | — | Card text color in HSL format |
primary | string | — | Primary action color in HSL format |
primary_hover | string | — | Primary hover state color in HSL format |
primary_foreground | string | — | Primary action text color in HSL format |
secondary | string | — | Secondary action color in HSL format |
secondary_hover | string | — | Secondary hover state color in HSL format |
destructive | string | — | Destructive action color in HSL format |
destructive_foreground | string | — | Destructive action text color in HSL format |
muted | string | — | Muted background color in HSL format |
muted_foreground | string | — | Muted text color in HSL format |
accent | string | — | Accent background color in HSL format |
accent_foreground | string | — | Accent text color in HSL format |
border | string | — | Border color in HSL format |
input | string | — | Input border color in HSL format |
Branding assets configuration
TOML: [service.theme.branding] · Env: HEXON_SERVICE_THEME_BRANDING_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
logo | string | — | Default logo path or URL, used if mode-specific logos not set |
logo_light | string | — | Logo for light mode and emails |
logo_dark | string | — | Logo for dark mode |
favicon | string | — | Favicon path or URL |
allow_http_images | bool | false | Allow HTTP (non-HTTPS) URLs for branding images Enabling is a security risk; use HTTPS URLs instead |
assets_base_path | string | /opt/hexon/assets | Base directory for local branding asset files Must be an absolute path |
Sign-in authentication flow configuration
TOML: [service.signin] · Env: HEXON_SERVICE_SIGNIN_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
primary | string | — | Primary authentication method |
secondary | []string | — | Alternative authentication methods |
require_mfa | []string | — | Authentication methods that require MFA step |
mfa_methods | []string | — | Allowed MFA methods |
Magic link passwordless sign-in configuration
TOML: [service.signin.magiclink] · Env: HEXON_SERVICE_SIGNIN_MAGICLINK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable magic link passwordless sign-in Requires SMTP to be configured; auto-enables device code module |
code_length | int | 10 | Magic link token length (BASE-20 encoding) 10 chars = ~43 bits entropy; sufficient with short TTL and rate limiting Range: 6–40. Requires enabled=true. |
code_ttl | duration | 10m | Magic link validity duration Requires enabled=true. |
rate_limit | rate_limit | 5/1m | Rate limit for magic link requests per IP Requires enabled=true. |
rate_limit_email | rate_limit | 3/10m | Rate limit per email address Prevents inbox flooding for a single user Requires enabled=true. |
Sign-up registration flow configuration
TOML: [service.signup] · Env: HEXON_SERVICE_SIGNUP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
primary | string | — | Primary signup/registration method |
secondary | []string | — | Alternative signup methods |
signin | []string | — | Sign-in methods enabled after signup Inherits MFA requirements from signin config |
Time access windows by country or CIDR
TOML: [service.time_windows] · Env: HEXON_SERVICE_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Cluster
TOML: [cluster] · Env: HEXON_CLUSTER_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
cluster_mode | bool | false | Enable cluster mode for distributed multi-node operation |
cluster_peers | []string | — | Static list of cluster peer addresses including self (IPs or hostnames) Minimum 2 entries (includes self). When set, cluster_dns is ignored. Hostnames are resolved to IPs on each refresh cycle Min: 2. Requires cluster_mode=true. |
cluster_dns | string | — | DNS name used for peer discovery in cluster mode Used for DNS-based node discovery. Ignored when cluster_peers is set Requires cluster_mode=true. |
cluster_dnssec | bool (optional) | true | Enable DNSSEC validation for cluster DNS lookups Nil means not set (defaults to true for security); set explicitly to false to disable Requires cluster_mode=true. |
cluster_dns_resolvers | []string | — | Custom DNS resolvers for cluster peer discovery Port defaults to :53 if not specified; leave empty to use OS DNS resolvers Requires cluster_mode=true. |
cluster_port | int | 7946 | NATS messaging port for inter-node cluster communication Range: 1–65535. Requires cluster_mode=true. |
cluster_port_routing | int | none | NATS cluster routing port for route gossip protocol Defaults to cluster_port+1 at runtime Range: 1–65535. Requires cluster_mode=true. |
cluster_interface | string | — | Network interface for cluster communication Defaults to the value of [service].network_interface if not set Requires cluster_mode=true. |
cluster_path | string | — | Shared filesystem path for NATS JetStream persistence NFS mount shared across all cluster nodes. Without this, JetStream is memory-only and persistent state is lost on restart Requires cluster_mode=true. |
cluster_refresh | duration | 15s | Interval for refreshing peer list and affinity ring Range: 1s–24h. Requires cluster_mode=true. |
cluster_startup_delay | duration | 0s | Delay before starting cluster operations after boot Allows time for peers to become available before joining the cluster Range: 0s–5m. Requires cluster_mode=true. |
cluster_affinity | bool | false | Enable consistent hashing for affinity-based request routing Routes requests to the same node based on fingerprint for session stickiness Requires cluster_mode=true. |
max_concurrent_forwards | int | 1000 | Maximum number of concurrent connection forwards between cluster nodes Set to 0 for unlimited (not recommended); applied only when cluster_mode is enabled Range: 0–100000. Requires cluster_mode=true. |
cluster_min_nodes | int | 0 | Minimum number of nodes required before the server starts accepting traffic Use 0 to start immediately or 2+ for quorum; value of 1 is not allowed Range: 0–100. Requires cluster_mode=true. |
config_file_shared | bool | true | Whether the config file is shared across nodes via NFS When false, each node reads its own local config file; hot-reload propagates only locally |
persist_memory | bool | true | Persist memory module data to JetStream file storage Requires cluster_path; enables restart-resilient sessions, PATs, audit trail, etc. Requires cluster_path. |
memory_kv_max_write | int | 10 | Maximum concurrent KV write operations for memory persistence Controls how many entries are written to JetStream KV simultaneously; increase for large directories Range: 1–100. Requires persist_memory=true. |
threshold_required | bool | false | Require threshold signing for OIDC JWTs (fail-closed after bootstrap grace) When true, token issuance fails (503) if threshold signing unavailable after grace period Requires cluster_mode=true. |
threshold_bootstrap_grace | duration | 2m | Grace period for DKG completion before enforcing threshold requirement Fallback to deterministic key during this period; after expiry, fail-closed (503) Range: 30s–10m. Requires threshold_required=true. |
threshold_nodes | int | 0 | Minimum signers required (t value; t+1 nodes cooperate to sign) 0 = auto (majority quorum: n/2). For 3-node cluster, t=2 means any 2 of 3 can sign Range: 0–100. Requires cluster_mode=true. |
Operations
TOML: [operations] · Env: HEXON_OPERATIONS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
leader_election_interval | duration | 5s | How often to run leader election check |
health_check_interval | duration | 10s | How often to check NATS health |
nats_ready_timeout | duration | 30s | How long to wait for NATS to be ready at startup |
max_concurrent_ops | int | 2000 | Maximum concurrent operations Range: 0–100000. |
operation_timeout | duration | 5m | Timeout for operation execution |
max_payload_bytes | string | 8MB | Maximum NATS message payload size |
once_dedupe_ttl | duration | 5m | TTL for Once operation deduplication |
wait_timeout | duration | 2s | Timeout for Wait() on single operations |
fire_and_forget_timeout | duration | 25ms | Auto-cleanup timeout for fire-and-forget detection |
quorum_timeout | duration | 5s | Timeout for WaitBroadcast() with quorum |
cluster_timeout | duration | 10s | Timeout for WaitBroadcast() waiting for all nodes |
encryption_ready_timeout | duration | 10s | Timeout waiting for encryption key sync during startup |
cluster_operational_timeout | duration | 2m | Timeout for cluster operational readiness before accepting traffic |
metrics_retention_window | duration | 1h | How long to retain operations metrics |
shutdown_timeout | duration | 30s | Timeout for graceful shutdown of operations |
max_queued_once_ops | int | 1000 | Maximum queued Once operations during leadership gap Range: 0–1000000. |
max_dedupe_map_size | int | 10000 | Maximum deduplication map entries Range: 0–10000000. |
publish_max_retries | int | 3 | Maximum retries for NATS publish failures Range: 0–100. |
publish_retry_delay | duration | 10ms | Initial retry delay for NATS publish with exponential backoff |
publish_timeout | duration | 5s | Per-attempt timeout for NATS publish |
broadcast_dedupe_ttl | duration | none | TTL for Broadcast deduplication to prevent echo races Auto-calculated as publish_timeout * 3 (min 2s) if not set |
circuit_breaker_failure_threshold | int | 5 | Consecutive failures before tripping circuit breaker Range: 0–1000. |
circuit_breaker_open_duration | duration | 30s | How long circuit breaker stays open before half-open |
circuit_breaker_half_open_successes | int | 2 | Consecutive successes to close circuit from half-open Range: 0–100. |
mtls | bool | true | Enable mTLS for NATS cluster communication |
internal_ca_valid_since | string | 2025-01-01T00:00:00Z | Internal CA certificate valid-from date ISO 8601 format. Changing invalidates all previously issued internal mTLS certificates |
internal_ca_valid_for | duration | 17520h | Internal CA validity duration 17520h=2 years |
internal_cert_max_validity | duration | 8760h | Maximum validity for internal certificates and CA overlap period 8760h=1 year |
internal_ca_subject_cn | string | Hexon Internal CA Root Subsystem | Internal CA Subject Common Name |
acme_ca_valid_since | string | none | ACME CA certificate valid-from date ISO 8601; changing invalidates all previously issued ACME CA certificates |
acme_ca_valid_for | duration | 175200h | ACME CA validity duration 175200h=20 years |
acme_ca_subject_cn | string | Hexon ACME CA Root Subsystem | ACME CA Subject Common Name |
acme_ca_renewal | duration | 8760h | ACME CA rotation and refresh interval 8760h=1 year |
acme_cert_max_validity | duration | 8760h | Maximum validity for ACME-issued certificates and CA overlap period 8760h=1 year |
acme_ca_threshold | bool | false | Enable threshold ECDSA (P-256) for ACME CA private key Fail-closed: no ACME certs until DKG completes (~30s). CA key never exists on any single node. Requires cluster_mode=true. |
encrypt_payloads | bool | true | Enable HMAC-authenticated AES-256-GCM payload encryption Disabling removes application-layer encryption from hexdcall RPC; mTLS still protects transport. Only disable for debugging |
forward_secrecy | bool | true | Enable forward secrecy with X3DH key exchange Requires JetStream KV with persistent storage (cluster_path). On single-node without cluster_path, pre-keys are memory-only and lost on restart |
forward_secrecy_key_interval | duration | 1h | Forward secrecy key rotation interval |
forward_secrecy_grace_period | duration | 5s | Grace period for accepting old keys during rotation |
forward_secrecy_prekey_rotation | duration | 168h | Pre-key rotation interval 168h = 7 days |
forward_secrecy_prekey_batch_size | int | 100 | Number of pre-keys to generate per batch Range: 0–10000. |
forward_secrecy_prekey_low_watermark | int | 20 | Minimum pre-keys to maintain before replenishment Must be less than or equal to prekey_batch_size Min: 0. |
forward_secrecy_prekey_ttl | duration | 168h | Time-to-live for pre-keys 168h = 7 days |
cluster_pqc | bool (optional) | true | Enable hybrid post-quantum key exchange (ML-KEM-768 + X25519) for cluster TLS FIPS 203 compliant |
scheduler_max_workers | int | 8 | Maximum concurrent scheduler workers Range: 0–1000. |
scheduler_queue_size | int | 100 | Priority queue buffer size per priority level Range: 0–100000. |
scheduler_adaptive_enabled | bool | false | Enable adaptive worker scaling based on CPU load Automatically adjusts task scheduling based on cluster load |
scheduler_cpu_threshold | string | 80 | CPU utilization threshold for adaptive scaling Percentage value, with or without % suffix Range: 10–99. |
scheduler_load_check_interval | duration | 5s | Interval for checking system load for adaptive scaling |
persistent_max_value_bytes | string | 1MB | Maximum value size for persistent storage Range: 1KB to 8MB |
Telemetry & Logging
TOML: [telemetry] · Env: HEXON_TELEMETRY_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
service_name | string | none | Service name for telemetry identification Appears in OTLP trace spans and log entries |
service_version | string | none | Service version for telemetry metadata Appears in OTLP trace metadata |
environment | string | none | Deployment environment name Appears in OTLP trace metadata; common values: production, staging, development |
log_level | string | info | Global log level Recommended: info for production, debug for troubleshooting Values: trace, debug, info, warn, error, fatal. |
log_format | string | json | Log output format json for machine parsing; human for interactive debugging Values: json, human. |
output | string | stdout | Log output destination otlp requires otlp_endpoint; both sends to stdout and OTLP Values: stdout, otlp, both. |
otlp_endpoint | string | none | OTLP gRPC endpoint for telemetry export Required when output is otlp or both Requires output=otlp. |
log_buffer_size | int | 0 | Ring buffer entries for log queries 0 disables the ring buffer Range: 0–10000000. |
audit | bool (optional) | true | Enable audit log class (always displayed regardless of log level) Audit-class events (SFTP, bastion, admin CLI) bypass level filtering when enabled |
DNS
TOML: [dns] · Env: HEXON_DNS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
timeout | duration | 5s | DNS query timeout |
cache_ttl | duration | 5m | Cache TTL, used when server TTL is unavailable or cache_override is true |
cache_override | bool | false | Ignore DNS server TTL and always use cache_ttl value |
dnssec_strict | bool | false | Fail DNS queries if DNSSEC is requested but the zone is not signed |
dnssec_full_validation | bool | false | Perform full cryptographic RRSIG/DNSKEY/DS chain-of-trust verification Recommended with DoT/DoH for maximum security; disabling trusts the resolver AD bit |
dnssec_sha1_policy | string | warn | Controls how SHA-1 usage in DNSSEC is handled Rejecting SHA-1 may break zones still using NSEC3-SHA1 Values: allow, warn, deprecate, reject. |
resolvers | []string | — | DNS resolver addresses for the infrastructure DNS module Separate from cluster.cluster_dns_resolvers. Empty = use OS resolver. Port defaults to :53 |
dot_enabled | bool | false | Enable DNS-over-TLS for encrypted DNS queries RFC 7858. |
dot_port | int | 853 | DNS-over-TLS port RFC 7858 mandates port 853 for interoperability RFC 7858. |
dot_verify_server_cert | bool | true | Verify TLS server certificates for DoT connections Disabling is not recommended as it removes authentication of DNS servers RFC 7858. |
dot_connection_pool_enabled | bool | true | Enable TLS connection pooling for DoT resolvers Reduces TLS handshake overhead when querying same resolvers Requires dot_enabled=true. |
dot_connection_pool_max_size | int | 100 | Maximum pooled connections per resolver Maximum persistent TLS connections to DoT resolvers Requires dot_connection_pool_enabled=true. |
dot_connection_pool_idle_timeout | duration | 5m | Close idle pooled connections after this duration Requires dot_connection_pool_enabled=true. |
flatten_cname | bool | true | Follow CNAME chains to resolve final A/AAAA records RFC 1034. |
max_cname_depth | int | 16 | Maximum CNAME chain depth to prevent resolution loops RFC 1034 Section 3.6.2 recommends a limit of 16 Min: 1. RFC 1034. |
health_check_enabled | bool (optional) | true | Enable periodic health checks on DNS resolvers |
health_failure_threshold | int | 2 | Consecutive failures before marking a resolver unhealthy Min: 1. |
health_check_interval | duration | 30s | Health check interval |
health_check_query | string | google.com | Domain name used for resolver health check queries |
adaptive_selector_enabled | bool | true | Enable intelligent performance-based resolver selection Selects fastest resolver based on observed latency |
adaptive_exploration_rate | float | 0.10 | Fraction of queries sent to non-optimal resolvers for exploration Higher values discover faster resolvers sooner but reduce short-term performance Range: 0.0–1.0. |
adaptive_smoothing_factor | float | 0.3 | Exponential moving average smoothing factor for latency tracking Higher values weight recent measurements more heavily Range: 0.0–1.0. |
adaptive_min_sample_size | int | 100 | Minimum query count per resolver before adaptive selection activates Min: 1. |
adaptive_load_balance_enabled | bool | true | Distribute queries across resolvers weighted by performance Requires adaptive_selector_enabled=true. |
Health
TOML: [health] · Env: HEXON_HEALTH_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable health monitoring and endpoints |
interface | string | — | Network interface name for health server IP address is resolved automatically from the interface Requires enabled=true. |
port | int | none | Port for health endpoints (plain HTTP, no TLS) Required when health monitoring is enabled Range: 1–65535. Requires enabled=true. |
allowed_cidrs | []string | 0.0.0.0/0 | Allowed CIDR ranges for health endpoint access Requires enabled=true. |
check_interval | duration | 10s | Health check interval for component monitoring Range: 1s–1h. Requires enabled=true. |
self_healing_enabled | bool | false | Enable self-healing for listener restarts When enabled, automatically restarts failed listeners within configured limits Requires enabled=true. |
max_listener_restarts | int | 3 | Max listener restarts in window before giving up After this many restarts in restart_window, listener is left stopped Range: 0–1000. Requires self_healing_enabled=true. |
restart_window | duration | 5m | Time window for counting listener restarts Rolling window for counting restart attempts Min: 1s. Requires self_healing_enabled=true. |
restart_backoff_multiplier | float | 2.0 | Exponential backoff multiplier for restart delays Each restart delay = previous delay * multiplier; prevents rapid restart loops Range: 0–100. Requires self_healing_enabled=true. |
Memory
TOML: [memory] · Env: HEXON_MEMORY_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable the memory management module |
leak_detection_enabled | bool | true | Enable goroutine and memory leak detection Monitors goroutine count growth and memory allocation trends Requires enabled=true. |
resource_management_enabled | bool | true | Enable tracking and cleanup of idle resources Tracks idle HTTP connections, file handles, and temporary buffers Requires enabled=true. |
goroutine_check_interval | duration | 30s | How often to check for goroutine leaks More frequent checks detect leaks faster but add minor overhead Requires leak_detection_enabled=true. |
memory_check_interval | duration | 1m | How often to check memory usage against thresholds Compares heap usage against max_memory threshold Requires enabled=true. |
cleanup_interval | duration | 5m | How often to run idle resource cleanup Runs idle resource cleanup; lower values free resources faster Requires resource_management_enabled=true. |
max_memory | string | 1GB | Maximum memory usage before triggering alerts e.g. 1GB, 512MB Requires enabled=true. |
max_goroutines | int | 10000 | Maximum number of goroutines before triggering alerts Alert fires when goroutine count exceeds this; typical idle: 50-200 Range: 100–1000000. Requires leak_detection_enabled=true. |
max_http_connections | int | 5000 | Maximum number of HTTP connections before triggering alerts Alert fires when total HTTP connection count exceeds this Range: 100–100000. Requires enabled=true. |
alert_interval | duration | 5m | Minimum time between repeated memory/resource alerts Prevents alert flooding; one alert per interval per threshold Min: 1m. Requires enabled=true. |
resource_timeout | duration | 30m | Maximum idle time before a resource is eligible for cleanup Resources idle longer than this are eligible for cleanup Min: 5m. Requires resource_management_enabled=true. |
max_resource_age | duration | 2h | Maximum total age of a resource before forced cleanup regardless of activity Forces cleanup regardless of activity; prevents long-lived resource leaks Min: 30m. Requires resource_management_enabled=true. |
SMTP
TOML: [smtp] · Env: HEXON_SMTP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
host | string | — | SMTP server hostname Required by magic link, OTP email delivery, WebAuthn expiry reminders, X.509 renewal notifications, and VPN PSK reminders Required. |
port | int | 587 | SMTP server port 587 for STARTTLS, 465 for SSL, 25 for plain Range: 1–65535. Requires host. |
encryption | string | none | SMTP encryption mode Empty defaults to plaintext; always set ssl or starttls in production to protect credentials Values: ssl, starttls, none. Requires host. |
user | string | none | SMTP authentication username SMTP AUTH username; leave empty if server does not require authentication Requires host. |
from | string | none | Sender email address RFC 5322 sender address (e.g., noreply@example.com); required for email delivery Requires host. |
reply_to | string | none | Reply-To email address Reply-To address; defaults to From address if empty Requires host. |
name | string | none | Sender display name Display name shown in From header (e.g., Hexon Gateway) Requires host. |
skip_tls | bool | false | Skip TLS certificate verification Skips server certificate validation for SSL/STARTTLS; NOT recommended for production — use only when the SMTP server presents an untrusted or mismatched certificate Requires host. |
Notifications
TOML: [notify] · Env: HEXON_NOTIFY_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
digest_window | duration | 5m | Batch window for digest notifications Batches notifications within this window into a single digest |
Email notification settings (requires SMTP module)
TOML: [notify.email] · Env: HEXON_NOTIFY_EMAIL_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable email notifications via existing SMTP module |
Outgoing webhook endpoints for notifications
TOML: [notify.webhooks] · Env: HEXON_NOTIFY_WEBHOOKS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique webhook name (used in notify_webhook param) Required. |
format | string | generic | Builtin payload format Values: slack, teams, discord, pagerduty, generic. |
body_template | string | — | Custom Go text/template for JSON body (overrides format) Template variables: {{.Subject}}, {{.Body}}, {{.Severity}} (info/warning/critical), {{.Username}}, {{.Hostname}}, {{.Timestamp}} (RFC3339), {{.Metadata}} (map), {{.Items}} (digest list), {{.ItemCount}}. Helper: {{json .Field}} for JSON-safe escaping |
content_type | string | application/json | HTTP Content-Type header |
timeout | duration | 10s | HTTP request timeout |
ACME CA (Internal)
TOML: [acme] · Env: HEXON_ACME_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable ACME certificate authority server RFC 8555. |
allowed_cidrs | []string | — | Allowed CIDRs for ACME API access If empty, no IP restrictions apply Requires enabled=true. |
allowed_identifiers | []string | — | Allowed domain patterns for certificate issuance Supports wildcards; if empty, any domain allowed Requires enabled=true. |
challenges_enabled | []string | http-01 | Enabled ACME challenge types Values: http-01, dns-01, tls-alpn-01. RFC 8555. Requires enabled=true. |
challenge_validity | duration | 15m | Challenge validity period RFC 8555. Requires enabled=true. |
dns_deterministic | bool | false | Enable deterministic DNS challenges for internal domains Generates deterministic DNS challenge tokens from cluster_key HMAC Requires enabled=true. |
dns_deterministic_cidrs | []string | — | CIDRs where deterministic DNS is allowed Only domains resolving within these CIDRs can use deterministic DNS Requires dns_deterministic. |
nonce_validity | duration | 15m | Nonce validity period for anti-replay protection RFC 8555. Requires enabled=true. |
max_validity | duration | 2160h | Maximum certificate validity period 2160h=90 days, 8760h=1 year RFC 8555. Requires enabled=true. |
default_validity | duration | 2160h | Default certificate validity when client does not specify 720h=30 days, 2160h=90 days RFC 8555. Requires enabled=true. |
max_san_count | int | 100 | Maximum Subject Alternative Names per certificate Matches Let’s Encrypt limit Min: 0. Requires enabled=true. |
enable_ip_identifiers | bool (optional) | true | Allow IP address identifiers in certificates IP challenges use http-01 or tls-alpn-01 only RFC 8738. Requires enabled=true. |
caa_checking | bool | false | Enable CAA record checking before issuance Verifies DNS CAA records authorize this CA RFC 8659. Requires enabled=true. |
caa_identifiers | []string | — | CAA identifiers that authorize this CA Defaults to service hostname if empty RFC 8659. Requires caa_checking. |
rate_limit_orders_per_ip | int | 50 | Maximum new orders per IP per hour Min: 0. Requires enabled=true. |
rate_limit_certs_per_domain | int | 50 | Maximum certificates per domain per week Min: 0. Requires enabled=true. |
path_prefix | string | /acme | Path prefix for ACME endpoints Endpoints: {prefix}/directory, {prefix}/newNonce, etc. Requires enabled=true. |
external_url | string | — | External URL for ACME directory responses Must end with path_prefix value. When empty, derived as https://<service.hostname><path_prefix> Requires enabled=true. |
terms_of_service | string | none | Terms of Service text served at /acme/tos URL to CA terms of service; displayed to ACME clients Requires enabled=true. |
ocsp_enabled | bool (optional) | true | Enable OCSP responder endpoint Serves real-time certificate status at /acme/ocsp RFC 6960. Requires enabled=true. |
ocsp_cache_ttl | duration | 5m | OCSP response cache TTL RFC 6960. Requires ocsp_enabled. |
ocsp_cidrs | []string | 0.0.0.0/0,::/0 | Allowed CIDRs for OCSP endpoint RFC 6960. Requires ocsp_enabled. |
crl_enabled | bool (optional) | true | Enable CRL distribution endpoint Serves Certificate Revocation List at /acme/crl RFC 5280. Requires enabled=true. |
crl_cidrs | []string | 0.0.0.0/0,::/0 | Allowed CIDRs for CRL endpoint RFC 5280. Requires crl_enabled. |
crl_next_update | duration | 48h | CRL NextUpdate offset from ThisUpdate Determines client CRL cache lifetime RFC 5280. Requires crl_enabled. |
Advanced multi-dimensional rate limiting configuration
TOML: [acme.rate_limits] · Env: HEXON_ACME_RATE_LIMITS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable comprehensive rate limiting |
orders_per_account | int | 5000 | Maximum orders per account within window Let’s Encrypt: 300 Min: 0. Requires enabled=true. |
orders_per_account_window | duration | 3h | Sliding window for orders per account Requires enabled=true. |
certs_per_domain | int | 500 | Maximum certificates per registered domain (eTLD+1) within window Let’s Encrypt: 50; applies across all subdomains Min: 0. Requires enabled=true. |
certs_per_domain_window | duration | 168h | Sliding window for certificates per domain Requires enabled=true. |
certs_per_exact_set | int | 50 | Maximum certificates for exact same domain set within window Let’s Encrypt: 5; prevents duplicate issuance Min: 0. Requires enabled=true. |
certs_per_exact_set_window | duration | 168h | Sliding window for certificates per exact set Requires enabled=true. |
auth_failures_per_domain | int | 50 | Maximum authorization failures per domain within window Let’s Encrypt: 5; throttles misconfigured domains Min: 0. Requires enabled=true. |
auth_failures_window | duration | 1h | Sliding window for authorization failures Requires enabled=true. |
orders_per_ip | int | 1000 | Maximum orders per IP address within window Let’s Encrypt: ~50; IPv6 grouped by /64 prefix Min: 0. Requires enabled=true. |
orders_per_ip_window | duration | 1h | Sliding window for orders per IP Requires enabled=true. |
failed_finalizations_per_order | int | 10 | Maximum failed finalization attempts per order Prevents CSR spam on a single order Min: 0. Requires enabled=true. |
min_order_interval | duration | 100ms | Minimum interval between orders (global throttle) Prevents thundering herd scenarios Requires enabled=true. |
buffer_percent | int | 10 | Buffer percentage below limits to trigger warnings Warnings logged at (100-buffer)% capacity Range: 0–100. Requires enabled=true. |
max_issued_at_entries | int | 10000 | Maximum timestamps to track per rate limit entity Higher values use more memory but improve precision Min: 0. Requires enabled=true. |
ACME Client (External)
TOML: [acme_client] · Env: HEXON_ACMECLIENT_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable ACME client for automatic certificate management RFC 8555. |
directory_url | string | https://acme-v02.api.letsencrypt.org/directory | ACME directory URL RFC 8555. Requires enabled=true. |
email | string | — | Contact email for ACME account Requires enabled=true. Required. |
accept_tos | bool | — | Accept CA Terms of Service Requires enabled=true. Required. |
reset | bool | false | Delete all ACME data on startup and start fresh Removes account, certificates, and keys Requires enabled=true. |
renewal_threshold | duration | 720h | Renew when cert expires within this duration 720h=30 days, 2160h=90 days Requires enabled=true. |
renewal_check_interval | duration | 6h | How often to check for renewals Range: 1m–24h. Requires enabled=true. |
challenge_port | int | 80 | Port for HTTP-01 challenge server Range: 1–65535. RFC 8555. Requires enabled=true. |
additional_domains | []string | — | Additional domains beyond main service hostname Requires enabled=true. |
auto_proxy_domains | bool (optional) | true | Auto-include proxy mapping hosts in certificate Requires enabled=true. |
key_type | string | ecdsa256 | Certificate key type Values: ecdsa256, ecdsa384, rsa2048, rsa4096. Requires enabled=true. |
timeout | duration | 60s | Timeout for ACME operations Range: 10s–5m. Requires enabled=true. |
max_retries | int | 10 | Max issuance retries before marking domain as failed Range: 0–100. Requires enabled=true. |
network_retries | int | 3 | Max retries for ACME network requests Range: 0–10. Requires enabled=true. |
allow_bootstrap_fallback | bool (optional) | true | Allow self-signed bootstrap certificate on ACME failure Generates temporary cert so server can start Requires enabled=true. |
startup_timeout | duration | 60s | Max time to wait for ACME on startup before fallback Range: 10s–5m. Requires enabled=true. |
startup_retries | int | 3 | Retries within startup_timeout before fallback Range: 0–10. Requires enabled=true. |
ari_enabled | bool (optional) | true | Enable ARI for optimal renewal timing Enables rate-limit-exempt renewals via CA-provided windows RFC 8739. Requires enabled=true. |
ari_check_interval | duration | 6h | How often to refresh ARI data Range: 1m–24h. RFC 8739. Requires enabled=true. |
Client-side rate limit tracking to avoid hitting CA limits
TOML: [acme_client.rate_limits] · Env: HEXON_ACMECLIENT_RATE_LIMITS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable client-side rate limit tracking |
orders_per_account | int | 300 | Max orders per account per window Min: 0. Requires enabled=true. |
orders_window | duration | 3h | Orders window duration Time window for counting certificate orders Requires enabled=true. |
certs_per_domain | int | 50 | Max certs per registered domain per window Min: 0. Requires enabled=true. |
certs_per_domain_window | duration | 168h | Certs per domain window duration 168h = 7 days Requires enabled=true. |
certs_per_exact_set | int | 5 | Max certs per exact domain set per window Min: 0. Requires enabled=true. |
certs_per_exact_set_window | duration | 168h | Exact set window duration 168h = 7 days Requires enabled=true. |
auth_failures_per_domain | int | 5 | Max auth failures per domain per window Min: 0. Requires enabled=true. |
auth_failures_window | duration | 1h | Auth failures window duration Time window for counting authorization failures Requires enabled=true. |
buffer_percent | int | 10 | Percent of limit to reserve as safety margin Range: 0–90. Requires enabled=true. |
min_order_interval | duration | 1s | Min time between orders Minimum time between certificate order attempts Requires enabled=true. |
max_retry_after_wait | duration | 1h | Max wait time before scheduling retry Maximum time to honor Retry-After headers from ACME server Requires enabled=true. |
respect_retry_after | bool (optional) | true | Honor server Retry-After header Requires enabled=true. |
Authentication
TOML: [authentication] · Env: HEXON_AUTHENTICATION_<KEY>
One-Time Password (email OTP) configuration
TOML: [authentication.otp] · Env: HEXON_AUTHENTICATION_OTP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
length | int | 6 | OTP code length Range: 4–12. |
type | string | base20 | OTP encoding type Values: numeric, base20. |
valid | duration | 5m | OTP validity duration |
domains | []string | — | Allowed email domains for OTP delivery. Empty or [”*”] allows all domains Leave empty or set to * to allow any email domain |
avoid_replay | bool | true | Delete OTP after first use to prevent replay |
resend_time | duration | 60s | Minimum interval between OTP resend requests |
max_retries | int | 5 | Maximum failed validation attempts before OTP invalidation Range: 0–100. |
rate_limit_request | rate_limit | 10/1m | Rate limit for OTP requests |
rate_limit_verify | rate_limit | 20/1m | Rate limit for OTP verification |
mask_email | bool (optional) | true | Mask email address in MFA template When enabled, user@example.com shows as u***@example.com |
TOTP authenticator app configuration
TOML: [authentication.totp] · Env: HEXON_AUTHENTICATION_TOTP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable TOTP authenticator app |
issuer | string | HexonGateway | Issuer name shown in authenticator app (2-16 chars, no spaces) Range: 2–16. Requires enabled=true. |
algorithm | string | SHA1 | HMAC algorithm SHA1 required for Google Authenticator, Authy, and most apps. Changing after enrollment breaks existing codes Values: SHA1, SHA256, SHA512. Requires enabled=true. |
digits | int | 6 | TOTP code digits Values: 6, 8. Requires enabled=true. |
period | duration | 30s | TOTP time step duration Requires enabled=true. |
skew | int | 1 | Allowed time skew steps Range: 0–2. Requires enabled=true. |
recovery_codes | int | 10 | Number of recovery codes Range: 0–20. Requires enabled=true. |
recovery_code_length | int | 6 | Length of each recovery code Range: 4–16. Requires enabled=true. |
rate_limit_auth | rate_limit | 10/1m | TOTP verification rate limit Requires enabled=true. |
OpenID Connect Provider configuration
TOML: [authentication.oidc] · Env: HEXON_AUTHENTICATION_OIDC_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable OIDC provider Issuer URL derives from [service].hostname |
signing_algorithm | string | ES256 | ID token signing algorithm ES256/384/512 (ECDSA) are compatible with Kubernetes kube-apiserver; EdDSA (Ed25519) is faster but not supported by all OIDC consumers Values: ES256, ES384, ES512, EdDSA. Requires enabled=true. |
access_token_ttl | duration | 1h | Access token lifetime Shorter TTLs improve security but increase token refresh traffic Range: 1m–24h. RFC 6749. Requires enabled=true. |
refresh_token_ttl | duration | 720h | Refresh token lifetime RFC 6749. Requires enabled=true. |
id_token_ttl | duration | 1h | ID token lifetime RFC 7519. Requires enabled=true. |
auth_code_ttl | duration | 10m | Authorization code lifetime RFC 6749. Requires enabled=true. |
refresh_token_rotation | bool | true | Rotate refresh tokens on each use Prevents refresh token replay attacks; disabling allows unlimited reuse of refresh tokens Requires enabled=true. |
force_dpop | bool | false | Require DPoP proof-of-possession for all clients Binds tokens to the client’s key pair, preventing token theft RFC 9449. Requires enabled=true. |
dpop_strict_replay | bool | false | Wait for cluster quorum on DPoP JTI storage Eliminates replay window but adds latency due to quorum write RFC 9449. Requires force_dpop=true. |
dpop_proactive_nonce | bool (optional) | true | Send DPoP-Nonce in all token responses Encourages nonce-based replay protection per RFC 9449 Section 8 RFC 9449. Requires force_dpop=true. |
disable_wildcard_redirects | bool | false | Disable wildcard matching in redirect URIs Recommended for production to prevent open redirect attacks Requires enabled=true. |
enable_test_client | bool | false | Enable built-in OIDC test client Exposes /_hexon/oidc/test endpoint for authorization code flow testing; disable in production Requires enabled=true. |
groups_test_client | []string | — | Groups allowed to access the test client Empty means any authenticated user can access Requires enable_test_client=true. |
rate_limit_auth | rate_limit | 100/1m | Authorization endpoint rate limit Requires enabled=true. |
rate_limit_auth_code | rate_limit | — | Per-user-per-client auth code generation rate limit Empty means unlimited (not recommended); prevents auth code flooding per user per client Requires enabled=true. |
rate_limit_token | rate_limit | 60/1m | Token endpoint rate limit Requires enabled=true. |
rate_limit_introspect | rate_limit | 300/1m | Introspection endpoint rate limit RFC 7662. Requires enabled=true. |
device_code_ttl | duration | 10m | Device code expiration RFC 8628. Requires enabled=true. |
par_enabled | bool | true | Enable Pushed Authorization Request endpoint PAR improves security by keeping authorization parameters server-side RFC 9126. Requires enabled=true. |
par_required | bool | false | Require PAR for all authorization requests RFC 9126. Requires par_enabled=true. |
par_ttl | duration | 5m | PAR request_uri lifetime Range: 1m–10m. RFC 9126. Requires par_enabled=true. |
rate_limit_par | rate_limit | — | PAR endpoint rate limit Requires par_enabled=true. |
enable_dcr | bool | false | Enable Dynamic Client Registration (RFC 7591) Allows native OAuth clients to register dynamically via POST /oidc/register RFC 7591. Requires enabled=true. |
rate_limit_dcr | rate_limit | 10/1m | DCR endpoint rate limit RFC 7591. Requires enable_dcr=true. |
allow_dcr_from | []string | — | IP/CIDR allowlist for DCR endpoint Empty means allow from any IP. Restrict to trusted networks in production Requires enable_dcr=true. |
allow_dcr_redirect_domains | []string | — | Allowed redirect URI domains for DCR clients Loopback always allowed. Use * to allow any HTTPS domain. Supports exact match and wildcard subdomains (*.example.com). Non-loopback requires HTTPS Requires enable_dcr=true. |
disable_plain_pkce | bool (optional) | false | Reject plain PKCE method, requiring S256 OAuth 2.1 recommends S256 only. Enable this to reject plain PKCE code challenges Requires enabled=true. |
pat_enabled | bool (optional) | — | Enable Personal Access Tokens for CLI and automation When false (default), the PAT subsystem is completely disabled — no UI, no CLI, no API Requires enabled=true. |
pat_max_ttl | duration | 2160h | Maximum PAT lifetime Default 90 days (2160h), maximum 365 days (8760h). Supports Go duration format. Requires enabled=true,pat_enabled=true. |
pat_max_per_user | int | 10 | Maximum active PATs per user Range: 1–100. Requires enabled=true,pat_enabled=true. |
pat_required_groups | []string | — | Groups allowed to create PATs; empty allows any authenticated user User must have ANY of the listed groups to create or hold PATs Requires enabled=true,pat_enabled=true. |
OIDC client configurations
TOML: [authentication.oidc.clients] · Env: HEXON_AUTHENTICATION_OIDC_CLIENTS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique client identifier Required. |
require_pkce | bool | false | Require Proof Key for Code Exchange Must be true for public clients (no client_secret) RFC 7636. |
origin_urls | []string | — | Allowed CORS origins |
redirect_urls | []string | — | Allowed OAuth redirect URIs after authentication |
allow_auth_from | []string | * | Who can authenticate through this client Use * for any origin, or restrict to specific patterns |
allow_client_from | []string | 0.0.0.0/0 | IP/CIDR allowlist for token endpoint access Restricts /token endpoint access by client IP; tighten to backend IP ranges for confidential clients |
allowed_scopes | []string | — | Scopes this client can request Values: openid, profile, email, groups, ssh_keys, certificates, wireguard. |
skip_consent | bool (optional) | false | Skip consent screen for trusted first-party clients When true, authorization is granted silently for authenticated users. Not recommended for third-party clients |
allowed_grant_types | []string | authorization_code,refresh_token | Allowed OAuth grant types Values: authorization_code, refresh_token, client_credentials, jwt-bearer. RFC 6749. |
client_credentials_ttl | duration | — | Token TTL for machine-to-machine client credentials grant RFC 6749. Requires allowed_grant_types=client_credentials. |
public | bool | false | Public client (no secret required) For SPAs, native apps, and device code flow. Must enable require_pkce |
jwt_public_key | string | — | PEM-encoded public key for JWT bearer assertion verification RFC 7523. Requires allowed_grant_types=jwt-bearer. |
jwt_algorithm | string | ES256 | JWT signature algorithm Values: RS256, RS384, RS512, ES256, ES384, ES512, EdDSA. RFC 7523. Requires allowed_grant_types=jwt-bearer. |
jwt_issuer | string | — | Expected issuer claim in JWT assertion Recommended for security — prevents token reuse across clients Requires allowed_grant_types=jwt-bearer. |
jwt_subject | string | — | Expected subject claim in JWT assertion Requires allowed_grant_types=jwt-bearer. |
token_endpoint_auth_method | string | client_secret_basic | Client authentication method at token endpoint Values: client_secret_basic, private_key_jwt, tls_client_auth. RFC 8705. |
tls_client_auth_subject_dn | string | — | Expected Subject DN for mTLS client certificate Must match Go pkix.Name.String() format, e.g. CN=client,O=Org,C=US RFC 8705. Requires token_endpoint_auth_method=tls_client_auth. |
tls_client_auth_san_uri | string | — | Expected URI SAN in client certificate (spiffe:// or https://) RFC 8705. Requires token_endpoint_auth_method=tls_client_auth. |
tls_client_auth_san_dns | string | — | Expected DNS SAN in client certificate RFC 8705. Requires token_endpoint_auth_method=tls_client_auth. |
tls_client_auth_san_email | string | — | Expected Email SAN in client certificate RFC 8705. Requires token_endpoint_auth_method=tls_client_auth. |
certificate_bound_tokens | bool | false | Bind issued tokens to the client certificate thumbprint Prevents token use without the original certificate RFC 8705. Requires token_endpoint_auth_method=tls_client_auth. |
client_ca_pem | string | — | CA PEM to verify client certificate issuer Inline PEM or file path. Per-client CA trust for defense-in-depth Requires token_endpoint_auth_method=tls_client_auth. |
WebAuthn/Passkey authentication configuration
TOML: [authentication.webauthn] · Env: HEXON_AUTHENTICATION_WEBAUTHN_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable WebAuthn/Passkey authentication |
rpid | string | — | Relying Party ID (typically the domain) Requires enabled=true. Required. |
origin | string | — | Expected origin URL for WebAuthn ceremonies Typically https://[service].hostname; exact origin match required Requires enabled=true. Required. |
skip_port_check | bool (optional) | true | Skip port check in origin validation Useful for K8s/Docker where external port differs from internal Requires enabled=true. |
domain | string | — | Cookie domain for WebAuthn sessions Requires enabled=true. |
name | string | — | Relying Party display name shown to users Requires enabled=true. |
type | string | preferred | Authenticator attachment preference platform=built-in (TouchID/Windows Hello), cross-platform=USB keys, preferred=any Values: platform, cross-platform, preferred. Requires enabled=true. |
validity | duration | 2160h | Passkey validity duration 0 means no expiry. Users are reminded before expiry via email Requires enabled=true. |
rate_limit_register | rate_limit | 5/1h | Passkey registration rate limit Requires enabled=true. |
rate_limit_auth | rate_limit | 20/1m | Passkey authentication rate limit Requires enabled=true. |
renewal_reminder_enabled | bool (optional) | true | Enable passkey expiration reminder emails Requires [smtp] to be configured; silently no-ops if SMTP is not set up Requires enabled=true. |
renewal_reminder_interval | duration | 24h | How often to check for expiring passkeys Requires renewal_reminder_enabled. |
renewal_reminder_before | duration | 360h | How long before expiry to start sending reminders Requires renewal_reminder_enabled. |
renewal_reminder_timeout | duration | 5m | Timeout for each reminder check run Requires renewal_reminder_enabled. |
renewal_reminder_retries | int | 3 | Retry count on transient reminder failures Requires renewal_reminder_enabled. |
renewal_reminder_retry_delay | duration | 30s | Delay between reminder retries Requires renewal_reminder_enabled. |
Kerberos authentication configuration
TOML: [authentication.kerberos] · Env: HEXON_AUTHENTICATION_KERBEROS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
realm | string | — | Kerberos realm name Must be uppercase by convention |
kdc | string | — | Primary Key Distribution Center address |
kdc_fallback | []string | — | Fallback KDC addresses for HA Tried in order if primary KDC fails Requires kdc. |
ticket_ttl | duration | 8h | Kerberos ticket lifetime for sessions |
password_change | bool | false | Enable password change via kpasswd protocol Requires realm. |
kpasswd_path | string | — | Path to kpasswd binary Auto-detected in PATH if not specified Requires password_change=true. |
spnego_enabled | bool | false | Enable SPNEGO/Negotiate browser SSO for domain-joined workstations Requires realm. |
keytab_path | string | — | Path to service keytab file containing HTTP/<hostname>@REALM principal Requires spnego_enabled=true. |
keytab_base64 | string | — | Service keytab as base64 string (alternative to keytab_path, for K8s/containers) Requires spnego_enabled=true. |
service_principal | string | — | Service principal name override Defaults to HTTP/<service.hostname> if empty Requires spnego_enabled=true. |
spnego_auto_auth | bool | false | Transparent SPNEGO for proxy routes (like x509_auto_auth) Tries Negotiate challenge before OIDC redirect Requires spnego_enabled=true. |
spnego_exclude_nets | []string | — | CIDRs to exclude from auto-SPNEGO challenges External/non-domain networks Requires spnego_auto_auth=true. |
X.509 client certificate authentication
TOML: [authentication.x509] · Env: HEXON_AUTHENTICATION_X509_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable X.509 client certificate authentication |
ca_pem | string | — | Trusted CA certificate(s) in PEM format Can contain root + intermediate CAs. If omitted, only hexdcall ACME CA bundle is used Requires enabled=true. |
ocsp_enabled | bool | false | Enable OCSP revocation checking Requires enabled=true. |
ocsp_url | string | — | OCSP responder URL Requires ocsp_enabled=true. |
ocsp_url_fallback | []string | — | Fallback OCSP URLs for HA Tried in order if primary OCSP responder fails Requires ocsp_enabled=true. |
ocsp_cache | duration | 15m | OCSP response cache duration Requires ocsp_enabled=true. |
ocsp_timeout | duration | 5s | OCSP HTTP request timeout Range: 1s–60s. Requires ocsp_enabled=true. |
ocsp_soft_fail | bool (optional) | true | Allow auth if OCSP responder unreachable Revoked certs are always blocked regardless of this setting Requires ocsp_enabled=true. |
crl_enabled | bool | false | Enable CRL revocation checking Requires enabled=true. |
crl_url | string | — | CRL download URL Requires crl_enabled=true. |
crl_url_fallback | []string | — | Fallback CRL URLs for HA Tried in order if primary CRL URL fails Requires crl_enabled=true. |
crl_refresh | duration | 1h | CRL refresh interval Requires crl_enabled=true. |
crl_timeout | duration | 30s | CRL download HTTP timeout Requires crl_enabled=true. |
crl_max_size | string | 0 | Maximum CRL size 0 means unlimited Requires crl_enabled=true. |
enroll_enabled | bool | false | Enable self-service certificate enrollment Requires enabled=true. |
enroll_validity | duration | 2160h | Certificate validity duration Requires enroll_enabled=true. |
enroll_algorithm | string | ECDSA-P256 | Key algorithm for enrolled certificates Values: ECDSA-P256, RSA-2048. Requires enroll_enabled=true. |
enroll_pkcs12_profile | string | LegacyDES | PKCS#12 encryption profile LegacyDES uses 3DES (all macOS versions). Modern2023 uses AES-256 (requires macOS Ventura 13.0+ or Windows 10 v1607+) Values: LegacyDES, Modern2023. Requires enroll_enabled=true. |
enroll_organization | string | Hexon Authenticated Users | Organization name in certificate Subject Requires enroll_enabled=true. |
enroll_max_active_certs | int | 10 | Maximum active certificates per user Oldest certificate is auto-revoked when limit is reached Range: 1–50. Requires enroll_enabled=true. |
enroll_rate_limit | rate_limit | 3/1h | Enrollment rate limit per user Requires enroll_enabled=true. |
revoke_rate_limit | rate_limit | 5/1h | Revocation rate limit per user Requires enroll_enabled=true. |
enroll_p12_min_entropy | int | 60 | Minimum entropy bits for PKCS#12 password Higher values enforce stronger passwords for certificate export Requires enroll_enabled=true. |
enroll_auto_renew | bool (optional) | true | Enable automatic certificate renewal before expiry Renews silently; notification emails require [smtp] Requires enroll_enabled=true. |
enroll_auto_renew_days | int | 15 | Days before expiry to trigger auto-renewal Must be less than enroll_validity in days Requires enroll_enabled=true. |
enroll_auto_renew_interval | duration | 24h | How often to check for certificates needing renewal Min: 1h. Requires enroll_enabled=true. |
enroll_auto_renew_timeout | duration | 5m | Timeout for each renewal check run Requires enroll_enabled=true. |
enroll_auto_renew_retries | int | 3 | Retry count on transient renewal failures Requires enroll_enabled=true. |
enroll_auto_renew_retry_delay | duration | 30s | Delay between renewal retries Requires enroll_enabled=true. |
Device Authorization Grant (RFC 8628)
TOML: [authentication.devicecode] · Env: HEXON_AUTHENTICATION_DEVICECODE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable device authorization grant RFC 8628. |
device_code_ttl | duration | 10m | Device code validity duration RFC 8628. Requires enabled=true. |
user_code_length | int | 8 | User code length (BASE-20 encoding) 8 chars gives ~37 bits of entropy, sufficient for human-typed codes Range: 6–12. Requires enabled=true. |
polling_interval | duration | 5s | Minimum polling interval Clients polling faster receive slow_down error response (RFC 8628 §3.5) RFC 8628. Requires enabled=true. |
rate_limit_authorize | rate_limit | 10/1m | Device authorization endpoint rate limit Requires enabled=true. |
SAML 2.0 Identity Provider configuration
TOML: [authentication.saml] · Env: HEXON_AUTHENTICATION_SAML_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable SAML 2.0 Identity Provider |
assertion_ttl | duration | 5m | SAML assertion validity duration Requires enabled=true. |
session_ttl | duration | 8h | Session duration for Single Logout tracking Requires enabled=true. |
require_signed_requests | bool | false | Require Service Providers to sign AuthnRequests Requires enabled=true. |
sign_responses | bool (optional) | true | Sign full SAML Response XML Requires enabled=true. |
sign_assertions | bool (optional) | true | Sign SAML Assertion within Response Requires enabled=true. |
encrypt_assertions | bool | false | Encrypt assertions (requires SP certificate) SP must provide certificate_pem for encryption Requires enabled=true. |
name_id_format | string | persistent | Default NameID format for all SPs Values: persistent, transient, email, unspecified. Requires enabled=true. |
rate_limit_sso | rate_limit | — | SSO endpoint rate limit Requires enabled=true. |
rate_limit_slo | rate_limit | — | SLO endpoint rate limit Requires enabled=true. |
enable_test_client | bool | false | Enable built-in SAML test client Exposes /_hexon/saml/test endpoint for SP-initiated SSO testing; disable in production Requires enabled=true. |
groups_test_client | []string | — | Groups allowed to access test client Requires enable_test_client=true. |
Configured SAML Service Providers
TOML: [authentication.saml.service_providers] · Env: HEXON_AUTHENTICATION_SAML_SERVICE_PROVIDERS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Human-readable SP name Required. |
entity_id | string | — | SP entity ID (unique identifier) Required. |
acs_url | string | — | Assertion Consumer Service URL Required. |
slo_url | string | — | Single Logout URL |
certificate_pem | string | — | SP certificate in PEM format for signature verification and encryption |
name_id_format | string | — | Override default NameID format for this SP Values: persistent, transient, email, unspecified. |
allowed_groups | []string | — | Groups that can access this SP Empty means any authenticated user |
SCIM 2.0 server for identity provisioning
TOML: [authentication.scim] · Env: HEXON_AUTHENTICATION_SCIM_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable SCIM 2.0 server |
allow_from | []string | — | Default IP/CIDR allowlist for SCIM clients Requires enabled=true. |
rate_limit | rate_limit | 100/1m | Default rate limit for SCIM clients Requires enabled=true. |
max_results | int | 100 | Default max items per page Max: 1000. Requires enabled=true. |
default_results | int | 20 | Default items per page when not specified Must not exceed max_results Requires enabled=true. |
Per-client SCIM configurations
TOML: [authentication.scim.clients] · Env: HEXON_AUTHENTICATION_SCIM_CLIENTS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Client identifier Required. |
allow_from | []string | — | IP/CIDR allowlist (overrides global) Empty uses global allow_from default |
rate_limit | rate_limit | — | Rate limit (overrides global) Empty uses global rate_limit default |
max_results | int | — | Max items per page (overrides global) 0 uses global max_results default |
valid_from | string | — | Token valid from RFC3339 format. Empty means always valid |
valid_until | string | — | Token valid until RFC3339 format. Empty means never expires |
Identity
TOML: [identity] · Env: HEXON_IDENTITY_<KEY>
LDAP directory provider configuration
TOML: [identity.ldap] · Env: HEXON_IDENTITY_LDAP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
url | string | — | LDAP server URL |
url_fallback | []string | — | Fallback LDAP URLs for HA, tried in order if primary fails |
base_dn | string | — | LDAP base distinguished name |
user_attribute | string | — | Primary user identifier attribute |
user_base_dn | string | — | Base DN for user searches |
group_base_dn | string | — | Base DN for group searches |
user_filter | string | — | LDAP filter for user searches RFC 4515 LDAP filter syntax. Common: (objectClass=posixAccount), (&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) for AD active users |
delta_sync | duration | — | Delta sync interval Only active when sync_mode=delta; requires delta_field to be set Requires sync_mode=delta. |
delta_field | string | — | LDAP attribute used for delta sync timestamps LDAP attribute used as watermark; modifyTimestamp is the standard choice Requires sync_mode=delta. |
full_sync | duration | — | Full sync interval |
sync_mode | string | delta | Directory synchronization mode persistent=LDAP persistent search (real-time, requires server support). delta=poll using modifyTimestamp (delta_field). syncrepl=RFC 4533 sync replication (most efficient) Values: persistent, delta, syncrepl. |
max_persistent_failures | int | — | Switch to delta sync after this many persistent search failures 0 means never fall back; after switching to delta sync, restart required to re-enable persistent search Range: 0–1000. Requires sync_mode=persistent. |
nested_groups | bool | — | Enable transitive nested group resolution Resolves groups recursively; can increase LDAP query load with deep hierarchies |
page_size | int | 100 | LDAP paged search result size Range: 0–10000. |
ldap_connection_pool | int | 5 | Number of pooled LDAP connections Range: 0–1000. |
bind_dn | string | — | Bind DN for LDAP authentication |
ignore_group_prefixes | []string | — | Ignore groups whose names start with these prefixes |
ca_pem | string | — | Custom CA certificate in PEM format for LDAP TLS verification Inline PEM or file path. When empty, system CA pool is used |
search_timeout | duration | 30s | Timeout for LDAP search operations |
bind_timeout | duration | 10s | Timeout for LDAP bind operations |
connection_timeout | duration | 10s | Timeout for new LDAP connection establishment |
pool_wait_timeout | duration | 5s | Timeout waiting for an available pool connection |
LDAP attribute-to-user field mapping
TOML: [identity.ldap_attribute_map] · Env: HEXON_IDENTITY_LDAP_ATTRIBUTE_MAP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
username | string | none | LDAP attribute for user identifier |
full_name | string | none | LDAP attribute for user full name |
email | string | none | LDAP attribute for email address |
given_name | string | none | LDAP attribute for given/first name |
surname | string | none | LDAP attribute for surname/last name |
member_of | string | none | LDAP attribute for group membership |
cert_attribute | string | none | LDAP attribute for user X.509 certificate |
group_name_attr | string | none | RDN attribute to extract group name from group DNs Extracts ‘admins’ from ‘cn=admins,cn=groups,dc=example,dc=com’ |
account_lock | string | none | LDAP attribute indicating account lock status |
password_expiry | string | none | LDAP attribute for password expiration timestamp |
modify_timestamp | string | none | LDAP attribute for entry modification timestamp |
create_timestamp | string | none | LDAP attribute for entry creation timestamp |
krb_principal | string | none | LDAP attribute for Kerberos principal name |
krb_last_pwd | string | none | LDAP attribute for Kerberos last password change |
employee_id | string | none | LDAP attribute for employee ID |
title | string | none | LDAP attribute for job title |
phone | string | none | LDAP attribute for phone number |
X.509 certificate subject field mapping
TOML: [identity.cert_subject_map] · Env: HEXON_IDENTITY_CERT_SUBJECT_MAP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
username | string | — | X.509 subject field to use as username Common values: cn, uid, emailAddress |
External OIDC identity providers for federated login
TOML: [identity.oidc_providers] · Env: HEXON_IDENTITY_OIDC_PROVIDERS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Internal provider identifier Required. |
display_name | string | — | UI display name, falls back to name if empty |
icon | string | — | UI icon URL or identifier for the provider |
issuer | string | — | OIDC issuer URL, must use HTTPS Required. |
client_id | string | — | OAuth 2.0 client identifier Required. |
scopes | []string | openid,profile,email | OAuth 2.0 scopes to request, must include openid |
pkce_required | bool | true | Require Proof Key for Code Exchange Must be true for public clients (no client_secret) RFC 7636. |
dpop_enabled | bool | — | Enable Demonstrating Proof of Possession token binding RFC 9449. |
redirect_uris | []string | — | Allowed OAuth 2.0 callback URLs, exact match required Must use HTTPS except localhost for development RFC 6749. |
dev_mode | bool | false | Enable relaxed validation for development NEVER enable in production |
suppress_error_details | bool | true | Hide internal error details in responses Defaults to true in production (non-dev) mode |
clock_skew_tolerance | duration | 2m | Allowed clock skew for token validation Max: 5m. |
strict_key_expiry | bool | false | Reject tokens signed with expired JWKS keys Enable to reject tokens when JWKS signing key has expired |
required_amr | []string | — | Required Authentication Method Reference values Empty means no AMR requirement |
par_preferred | bool (optional) | true | Prefer Pushed Authorization Requests when provider supports it RFC 9126. |
timeout | duration | 30s | HTTP client timeout for provider requests Range: 1s–60s. |
discovery_ttl | duration | 24h | OIDC discovery document cache TTL Range: 1h–720h. |
External SCIM identity providers for directory sync
TOML: [identity.scim_providers] · Env: HEXON_IDENTITY_SCIM_PROVIDERS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Internal provider identifier, must be unique Required. |
display_name | string | — | UI display name, falls back to name if empty |
enabled | bool | — | Enable this SCIM provider |
priority | int | — | Merge priority for multi-provider conflicts, lower wins Lower value = higher priority Range: 0–1000. Requires enabled=true. |
base_url | string | — | SCIM server base URL, must use HTTPS in production Requires enabled=true. Required. |
auth_type | string | — | Authentication method for SCIM API Values: bearer, basic, oauth2. Requires enabled=true. Required. |
basic_username | string | — | Username for auth_type=basic Requires auth_type=basic. |
oauth2_token_url | string | — | Token endpoint URL for auth_type=oauth2 Requires auth_type=oauth2. |
oauth2_client_id | string | — | Client ID for auth_type=oauth2 Requires auth_type=oauth2. |
oauth2_scope | string | scim.read | OAuth2 scope for auth_type=oauth2 Requires auth_type=oauth2. |
sync_interval | duration | 5m | Background incremental sync interval Range: 1m–24h. Requires enabled=true. |
full_sync_interval | duration | 24h | Full directory sync interval Range: 1h–168h. Requires enabled=true. |
sync_mode | string | full | Synchronization strategy full=periodic full directory pull. incremental=poll for changes since last sync. push=webhook-driven from IdP. all=full+incremental+push combined Values: full, incremental, push, all. Requires enabled=true. |
sync_users | bool | true | Sync user resources from this provider Requires enabled=true. |
sync_groups | bool | true | Sync group resources from this provider Requires enabled=true. |
sync_group_members | bool | — | Include member lists when syncing groups Requires enabled=true. |
page_size | int | 100 | SCIM list pagination page size Range: 0–1000. Requires enabled=true. |
nested_groups | bool | — | Enable transitive nested group resolution Requires enabled=true. |
nested_groups_direction | string | up | Direction for nested group traversal up=resolve parent groups (user→team→dept). down=resolve child groups (dept→team→members). both=resolve in both directions Values: up, down, both. Requires nested_groups=true. |
max_nesting_depth | int | 10 | Maximum recursion depth for nested group resolution Range: 0–100. Requires nested_groups=true. |
ca_pem | string | — | Custom CA certificate in PEM format for TLS verification Requires enabled=true. |
insecure_skip_verify | bool | — | Skip TLS certificate verification NEVER enable in production Requires enabled=true. |
timeout | duration | 30s | HTTP client timeout for SCIM API requests Range: 1s–5m. Requires enabled=true. |
Map SCIM attributes to internal directory fields
TOML: [identity.scim_providers.attribute_map] · Env: HEXON_IDENTITY_SCIM_PROVIDERS_ATTRIBUTE_MAP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
username | string | userName | SCIM attribute for user identifier |
full_name | string | displayName | SCIM attribute for display name |
email | string | emails[primary eq true].value | SCIM path expression for primary email SCIM path syntax: dot notation for nested (name.givenName), bracket filter for arrays (emails[primary eq true].value), [] for all items (groups[].display) |
given_name | string | name.givenName | SCIM path expression for given name |
surname | string | name.familyName | SCIM path expression for family name |
groups | string | groups[].display | SCIM path expression for group membership |
active | string | active | SCIM attribute for account active status |
employee_id | string | employeeNumber | SCIM attribute for employee ID |
title | string | title | SCIM attribute for job title |
phone | string | phoneNumbers[primary eq true].value | SCIM path expression for primary phone number |
department | string | urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:department | SCIM attribute for department Uses SCIM enterprise extension schema |
Proxy
TOML: [proxy] · Env: HEXON_PROXY_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable the reverse proxy service |
hostname | string | none | Hostname for proxy landing page Hostname only, no scheme or port Requires enabled=true. |
header_user | string | X-Hexon-User | Header name for authenticated username Requires enabled=true. |
header_mail | string | X-Hexon-Mail | Header name for authenticated user email Requires enabled=true. |
header_name | string | X-Hexon-Name | Header name for authenticated user full name Requires enabled=true. |
header_groups | string | X-Hexon-Groups | Header name for authenticated user groups Requires enabled=true. |
gzip | bool | false | Enable gzip compression for proxied responses Compresses proxied responses; negotiated via Accept-Encoding header Requires enabled=true. |
brotli_support | bool (optional) | true | Enable Brotli decode/reencode for HTML rewriting Requires enabled=true. |
expose_circuit_state | bool (optional) | true | Include X-Circuit-State header in 503 responses when circuit is open Requires enabled=true. |
signing_enabled | bool | true | Enable HMAC-SHA256 signing of auth headers Shared rotating HMAC key used by per-mapping sign_request=true. Disabling breaks all sign_request verifications Requires enabled=true. |
signing_rotation | duration | 15m | HMAC signing key rotation interval Requires enabled=true. |
verify_max_body_size | string | 4KB | Max request body size for signature verify endpoint Requires enabled=true. |
verify_rate_limit | string | 100/1s | Rate limit for signature verify endpoint Requires enabled=true. |
max_idle_conns | int | 100 | Total idle connections across all backend hosts Requires enabled=true. |
max_idle_conns_per_host | int | 50 | Idle connections per backend host Requires enabled=true. |
max_conns_per_host | int | 100 | Max total connections per backend host Requires enabled=true. |
idle_conn_timeout | duration | 90s | Idle backend connection timeout Requires enabled=true. |
response_header_timeout | duration | 30s | Timeout waiting for backend response headers Requires enabled=true. |
expect_continue_timeout | duration | 1s | Timeout waiting for HTTP 100-Continue response Requires enabled=true. |
tls_handshake_timeout | duration | 10s | TLS handshake timeout with backends Requires enabled=true. |
force_attempt_http2 | bool | true | Enable HTTP/2 for backend connections Requires enabled=true. |
cache_enabled | bool | false | Enable in-memory response caching for static assets Requires enabled=true. |
cache_size | string | 100MB | Maximum response cache size Requires cache_enabled=true. |
cache_ttl | duration | 5m | Response cache time-to-live Requires cache_enabled=true. |
enable_http3 | bool | false | Enable HTTP/3 (QUIC) for backend connections Requires enabled=true. |
http3_fallback_enabled | bool | true | Fall back to HTTP/2 or HTTP/1.1 if HTTP/3 fails Requires enable_http3=true. |
default_0rtt | bool | true | Enable 0-RTT early data for backend HTTP/3 connections Requires enable_http3=true. |
quic_idle_timeout | duration | 30s | QUIC idle timeout for backend connections Requires enable_http3=true. |
quic_max_streams | int | 100 | Max concurrent streams per QUIC backend connection Requires enable_http3=true. |
maglev_table_size | int | 65537 | Maglev consistent hash lookup table size Must be prime number; ~256KB memory per load balancer Min: 10007. Requires enabled=true. |
proxy_protocol | bool (optional) | false | Enable HAProxy PROXY protocol for backend connections Requires enabled=true. |
proxy_protocol_version | string | v2 | PROXY protocol version v1=text format, v2=binary format (more efficient) Values: v1, v2. Requires proxy_protocol. |
disable_affinity_hosts | []string | none | Hostnames where cluster affinity forwarding is disabled Use for CDN, static content, stateless APIs Requires enabled=true. |
group_refresh_interval | duration | 15m | Interval for checking OIDC proxy session group membership changes Only applies to OIDC-authenticated proxy sessions. LDAP group changes reflected via directory sync. Set to 0 to disable Requires enabled=true. |
bearer_cache_ttl | duration | 5m | Cache TTL for verified JWT Bearer tokens Caches Ed25519 verification result. Set to 0 to disable. Per-mapping override available Requires enabled=true. |
Array of reverse proxy route mappings
TOML: [proxy.mapping] · Env: HEXON_PROXY_MAPPING_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
app | string | — | Application display name Required. |
host | string | — | Frontend hostname to match via SNI/Host header Required. |
path | string | — | Path regex pattern to match Go regexp syntax; anchored with ^…$ automatically. Use /api/.* not /api/. Literal dots need escaping: /api/v1.0/. Required. |
allowed_methods | []string | — | Allowed HTTP methods; empty allows all Empty allows all HTTP methods Values: GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH. |
priority | int | none | Route matching priority nil (omit)=auto-calculated from path specificity. 0-1000=auto range. >1000=manual override, higher wins. Most specific path should have highest priority |
service | []string | — | Backend service URLs Required. |
auth | bool | false | Require authentication for this mapping Requires [authentication] to be configured |
auth_flow | string | none | Named auth flow profile References [auth_flow.name]. Defaults to ‘default’ when omitted. Requires auth=true |
oidc_providers | []string | internal | OIDC providers for authentication Provider names from [authentication.oidc] clients. Requires auth=true Requires auth=true. |
mtls | bool | false | Require client certificate (mTLS) for this mapping Uses mapping cert/key if set, falls back to service certificate. Configure x509.ca_pem for client CA trust |
lb_strategy | string | adaptive | Load balancing algorithm for multiple backends Values: adaptive, round_robin, weighted, least_connections, hash, random, maglev. |
lb_hash_key | string | none | Hash key source for hash/maglev strategies Used with lb_strategy=hash or lb_strategy=maglev. Variables: header:<name>, cookie:<name>, query:<param>, ip, uri Requires lb_strategy=hash. |
lb_weights | []int | none | Backend weights for weighted strategy Must match service count; only valid with lb_strategy=weighted Min: 1. Requires lb_strategy=weighted. |
maglev_table_size | int | 65537 | Maglev lookup table size override Only valid with lb_strategy=maglev; must be prime Min: 10007. Requires lb_strategy=maglev. |
dns_discovery | bool | false | Enable STRICT_DNS service discovery mode Resolves single service hostname to multiple endpoints; requires exactly one service URL |
dns_refresh | duration | none | DNS refresh interval for service discovery Default respects TTL Min: 5s. Requires dns_discovery=true. |
groups | []string | none | Required group memberships for access Group names from [identity] directory. Requires auth=true |
allowed_subnets | []string | none | Restrict access to specific CIDR subnets Empty allows all client IPs |
add_auth_headers | bool | false | Add X-Hexon-User/Mail/Name/Groups headers to backend requests Injects X-Hexon-User/Mail/Name/Groups headers to backend |
add_bearer | bool | false | Inject signed JWT Bearer token into backend requests Backend must trust HexonGateway OIDC issuer. Verify via /oidc/cert JWKS endpoint |
forward_request_headers | bool | true | Forward original client request headers to backend Forward all original request headers to backend |
forward_response_headers | bool | true | Forward backend response headers to client Forward all backend response headers to client |
allow_upgrade | bool | false | Allow WebSocket and HTTP upgrade requests |
host_header | string | none | Override Host header sent to backend Overrides Host header sent to backend; empty uses original request host |
cookie_domain | string | none | Cookie domain for OIDC session Use leading dot for multi-subdomain; must have at least two labels |
tls_check | bool | false | Verify backend TLS certificates When false, skips TLS certificate verification for this backend |
rewrite_hosts | [][2]string | none | Host rewriting rules as [from, to] pairs Array of [from, to] pairs. Rewrites Location headers and HTML href/src attributes in responses |
folder | string | none | Folder for grouping mappings in the UI |
tags | []string | none | Tags for search and filtering in the UI UI metadata only; does not affect routing or access control |
display | bool (optional) | true | Show this mapping in the portal and access list Set to false to hide API-only or internal mappings from the user portal |
audience | string | none | Audience claim for header signing Defaults to service URL if not set |
disable_rate_limit | bool | false | Bypass global rate limiting for this mapping |
rate_limit | string | none | Custom rate limit override for this mapping Per-mapping rate limit; overrides global protection.rate_limit |
disable_size_limit | bool | false | Bypass global size limiting for this mapping |
max_bytes | string | none | Custom max request body size override Per-mapping body size limit; overrides global protection.max_bytes |
disable_cache | bool | false | Bypass response caching for this mapping |
disable_pow | bool | false | Bypass proof-of-work protection for this mapping |
dnssec | bool (optional) | none | Override DNSSEC validation for this mapping’s backend resolution Inherits from global proxy setting when not set |
dns_resolvers | []string | none | Override DNS resolvers for this mapping’s backend resolution |
rewrite_host | bool (optional) | true | Enable URL rewriting in HTML responses When false, HTML responses are streamed without rewriting href/src attributes — use for SSE or binary content |
inject_toolbar | bool (optional) | true | Inject logout toolbar into HTML responses Only effective when auth=true |
brotli_support | bool (optional) | none | Override global Brotli decode/reencode for this route Inherits from global proxy setting when not set |
cobrowse | bool | false | Enable co-browse capability for this mapping |
cobrowse_mask_inputs | bool (optional) | true | Mask all input field values in co-browse replay Requires cobrowse=true. |
cobrowse_block_selector | string | none | CSS selector to block from co-browse recording Requires cobrowse=true. |
max_idle_conns_per_host | int | none | Override idle connections per backend host Inherits from global setting when not set |
max_conns_per_host | int | none | Override max connections per backend host Inherits from global setting when not set |
idle_conn_timeout | duration | none | Override idle connection timeout |
response_header_timeout | duration | none | Override response header timeout |
expect_continue_timeout | duration | none | Override HTTP 100-Continue timeout |
tls_handshake_timeout | duration | none | Override TLS handshake timeout |
force_attempt_http2 | bool (optional) | none | Override HTTP/2 backend connection setting Inherits from global proxy setting when not set |
enable_http3 | bool (optional) | none | Override HTTP/3 (QUIC) for this backend Inherits from global proxy setting when not set |
force_http3 | bool | false | Force HTTP/3 only, fail if unavailable Requires enable_http3=true Requires enable_http3. |
enable_0rtt | bool (optional) | none | Override 0-RTT early data for this backend Inherits from global proxy setting when not set Requires enable_http3. |
protocol_preference | string | auto | HTTP protocol version preference Values: prefer_http3, prefer_http2, force_http3, auto. |
proxy_protocol | bool (optional) | none | Override HAProxy PROXY protocol for this backend Inherits from global proxy setting when not set |
sign_request | bool | false | Enable HMAC request signing for backend verification |
sign_request_max_body | string | 10MB | Max body size to include in request signature Use 0 to skip body hashing |
bearer_cache_ttl | duration | none | Override Bearer token cache TTL for this mapping Inherits from global proxy setting when not set. Set to 0 to disable caching |
grpc | bool | false | Enable gRPC mode with streaming, trailer extraction, and gRPC-aware circuit breaker |
site | string | none | Connector site ID for remote proxying When set, requests route through the named connector tunnel instead of direct backend connection. Site must be defined in [connector.sites] |
expose_circuit_state | bool (optional) | none | Override X-Circuit-State header exposure for this mapping Inherits from global proxy setting when not set |
geo_enabled | bool (optional) | none | Override service-level geo-IP access check Inherits from global proxy setting when not set |
geo_allow_countries | []string | none | Override allowed countries (replaces global list) ISO 3166-1 alpha-2 codes |
geo_deny_countries | []string | none | Override denied countries (replaces global list) ISO 3166-1 alpha-2 codes |
geo_allow_asn | []string | none | Override allowed ASNs for this mapping |
geo_deny_asn | []string | none | Override denied ASNs for this mapping |
geo_bypass_cidr | []string | none | Additional geo bypass CIDRs (merged with service level) |
geo_deny_code | int | none | Override HTTP status code for geo denial Inherits from global setting when not set Range: 400–599. |
geo_deny_message | string | none | Override denial message for geo-blocked requests Inherits from global setting when not set |
time_enabled | bool (optional) | none | Override service-level time-based access check Inherits from global proxy setting when not set |
time_bypass_cidr | []string | none | Additional time-check bypass CIDRs (merged with service level) |
time_deny_code | int | none | Override HTTP status code for time-based denial Inherits from global setting when not set Range: 400–599. |
time_deny_message | string | none | Override denial message for time-blocked requests Inherits from global setting when not set |
time_default_timezone | string | none | Override default timezone for time checks Inherits from global setting when not set |
time_default_allow_days | []string | — | Override default allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
time_default_deny_days | []string | — | Override default denied days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
time_default_allow_hours | string | none | Override default allowed hours range Format: HH:MM-HH:MM |
time_default_deny_hours | string | none | Override default denied hours range Format: HH:MM-HH:MM |
permissions_policy | string | none | Permissions-Policy response header override Empty=inherit from backend, dash=strip, value=override |
referrer_policy | string | none | Referrer-Policy response header override Empty=inherit from backend, dash=strip, value=override |
Just-In-Time 2FA configuration
TOML: [proxy.mapping.jit2fa] · Env: HEXON_PROXY_MAPPING_JIT2FA_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable JIT-2FA for this mapping |
inject_credentials | bool (optional) | true | Encrypt and replay credentials to backend after OTP When false, backend must trust auth headers (requires add_auth_headers=true) Requires enabled=true. |
login_url | string | — | Redirect URL when user is not authenticated Requires enabled=true. Required. |
login_path_regex | string | — | Regex to match login POST requests Requires enabled=true. Required. |
logout_path_regex | string | — | Regex to match logout requests Requires enabled=true. |
username_field | string | username | Form field name for username Requires enabled=true. |
password_field | string | password | Form field name for password Requires enabled=true. |
error_no_email | string | none | Error message when webhook returns no email Empty uses built-in default message Requires enabled=true. |
error_credentials | string | none | Error message for invalid credentials Empty uses built-in default message Requires enabled=true. |
error_otp_expired | string | none | Error message when OTP code expires Empty uses built-in default message Requires enabled=true. |
error_otp_invalid | string | none | Error message for invalid OTP code Empty uses built-in default message Requires enabled=true. |
error_max_retries | string | none | Error message when max OTP retries exceeded Empty uses built-in default message Requires enabled=true. |
cookie_name | string | jit2fa_key | Cookie name for session key storage Requires enabled=true. |
cookie_path | string | / | Cookie path Requires enabled=true. |
cookie_domain | string | — | Cookie domain (empty = current domain) Requires enabled=true. |
session_ttl | duration | 8h | Authenticated session time-to-live Requires enabled=true. |
Webhook configuration for credential validation
TOML: [proxy.mapping.jit2fa.webhook] · Env: HEXON_PROXY_MAPPING_JIT2FA_WEBHOOK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
url | string | — | Webhook URL for credential validation Required. |
method | string | POST | HTTP method for webhook request Values: GET, POST, PUT. |
request_format | string | json | Request body encoding format query format requires method=GET Values: json, query, form. |
username_param | string | username | Parameter name for username in query/form formats Requires request_format=query. |
password_param | string | password | Parameter name for password in query/form formats Requires request_format=query. |
body_template | string | — | Custom request body template for POST/PUT Supports {{username}} and {{password}} placeholders Requires request_format=json. |
timeout | duration | 5s | Webhook request timeout Range: 1s–60s. |
success_field | string | — | JSONPath to success field in response JSONPath syntax: $.field, $.nested.field, $.array[0].field. Either success_field or success_regex is required |
success_value | string | — | Expected value for success field Exact string match against the JSONPath result. Required when using success_field |
extract_email | string | — | JSONPath to email field in response JSONPath syntax: $.field, $.nested.field. Either extract_email or email_regex is required |
success_regex | string | — | Regex pattern to detect successful authentication Fallback for non-JSON responses; either this or success_field required |
email_regex | string | — | Regex with capture group to extract email from response Must have at least one capture group |
tls_skip_verify | bool (optional) | false | Skip TLS certificate verification for webhook |
tls_cert | string | — | Client certificate for mTLS to webhook (PEM) Must be specified together with tls_key |
tls_ca | string | — | Custom CA certificate for webhook TLS verification (PEM) |
max_idle_conns | int | 50 | Total idle connections in pool Range: 0–1000. |
max_idle_conns_per_host | int | 20 | Idle connections per host Range: 0–200. |
force_attempt_http2 | bool (optional) | true | Force HTTP/2 connection attempts |
disable_compression | bool (optional) | true | Disable transport compression Auth payloads are too small to benefit from compression |
write_buffer_size | string | 32KB | HTTP transport write buffer size |
read_buffer_size | string | 32KB | HTTP transport read buffer size |
dial_timeout | duration | 30s | TCP dial timeout for webhook connections Range: 1s–120s. |
keep_alive | duration | 30s | TCP keepalive interval for webhook connections Range: 0s–300s. |
OTP generation and validation settings
TOML: [proxy.mapping.jit2fa.otp] · Env: HEXON_PROXY_MAPPING_JIT2FA_OTP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
length | int | 6 | OTP code length Range: 4–12. |
type | string | — | OTP code type Empty = use global OTP type config Values: numeric, base20. |
valid | duration | 5m | OTP validity duration Range: 1m–30m. |
max_retries | int | 3 | Maximum OTP entry attempts before lockout Range: 1–10. |
resend_time | duration | 30s | Interval before OTP resend is allowed Range: 10s–5m. |
rate_limit | rate_limit | 10/1m | Rate limit for OTP verification attempts |
Envoy-style outlier detection for endpoint ejection
TOML: [proxy.mapping.outlier_detection] · Env: HEXON_PROXY_MAPPING_OUTLIER_DETECTION_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable outlier detection for endpoint ejection Auto-enabled when multiple backends are configured |
consecutive_5xx | int | 5 | Eject endpoint after N consecutive 5xx responses Min: 1. Requires enabled=true. |
consecutive_gateway_failure | int | 3 | Eject endpoint after N consecutive 502/503/504 responses Min: 1. Requires enabled=true. |
consecutive_local_origin_failure | int | 5 | Eject endpoint after N consecutive connection failures Min: 1. Requires enabled=true. |
interval | duration | 10s | Outlier detection evaluation interval Min: 1s. Requires enabled=true. |
base_ejection_time | duration | 30s | Initial ejection duration before re-evaluation Min: 1s. Requires enabled=true. |
max_ejection_time | duration | 5m | Maximum ejection duration cap Min: 1s. Requires enabled=true. |
max_ejection_percent | int | 50 | Max percentage of endpoints that can be ejected simultaneously Range: 0–100. Requires enabled=true. |
success_rate_minimum_hosts | int | 3 | Min healthy hosts required for success rate calculation Min: 1. Requires enabled=true. |
success_rate_request_volume | int | 100 | Min requests per host required for success rate calculation Min: 1. Requires enabled=true. |
success_rate_stdev_factor | int | 1900 | Standard deviation factor x1000 for success rate ejection 1900 means 1.9 standard deviations Min: 0. Requires enabled=true. |
failure_percentage_threshold | int | 50 | Eject endpoint if failure percentage exceeds this value Range: 0–100. Requires enabled=true. |
failure_percentage_minimum_hosts | int | 3 | Min hosts required for failure percentage calculation Min: 1. Requires enabled=true. |
failure_percentage_request_volume | int | 50 | Min requests required for failure percentage calculation Min: 1. Requires enabled=true. |
Active health check configuration for backend probing
TOML: [proxy.mapping.health_check] · Env: HEXON_PROXY_MAPPING_HEALTH_CHECK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable active health checking for backends Probes backends on a schedule to detect failures before traffic is affected |
type | string | http | Health check protocol Values: tcp, http, http3, grpc. |
path | string | /health | HTTP path for health check requests Requires type=http,type=http3. |
method | string | GET | HTTP method for health check requests Values: GET, HEAD. Requires type=http,type=http3. |
expected_status | []int | none | Expected HTTP status codes from healthy backends. Empty means any non-5xx response is healthy. Range: 100–599. Requires type=http,type=http3. |
grpc_service | string | none | gRPC service name for grpc.health.v1.Health/Check Empty checks the overall server health Requires type=grpc. |
interval | duration | 10s | Interval between health check probes Min: 1s. |
timeout | duration | 5s | Timeout per health check probe Min: 100ms. |
unhealthy_threshold | int | 3 | Consecutive failures before marking backend unhealthy Min: 1. |
healthy_threshold | int | 2 | Consecutive successes before marking backend healthy Min: 1. |
tls_skip_verify | bool (optional) | none | Skip TLS certificate verification for health checks Inherits from mapping tls_check when not set |
Override circuit breaker settings for this mapping
TOML: [proxy.mapping.circuit_breaker] · Env: HEXON_PROXY_MAPPING_CIRCUIT_BREAKER_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable circuit breaker for backend health tracking |
error_ratio_threshold | float | 0.25 | Trip circuit if 5xx error ratio exceeds this threshold Range: 0.0–1.0. Requires enabled=true. |
error_ratio_window | duration | 10s | Rolling window for error ratio calculation Requires enabled=true. |
latency_p95_threshold | duration | 1s | Trip circuit if P95 latency exceeds this duration Requires enabled=true. |
latency_p99_threshold | duration | none | Trip circuit if P99 latency exceeds this duration Requires enabled=true. |
network_error_threshold | float | 0.15 | Trip circuit if network error ratio exceeds this threshold Range: 0.0–1.0. Requires enabled=true. |
fallback_duration | duration | 30s | Duration the circuit stays open before entering half-open Requires enabled=true. |
recovery_duration | duration | 10s | Duration in half-open state before deciding to close or re-open Requires enabled=true. |
success_threshold | int | 2 | Successful requests needed in half-open state to close circuit Min: 1. Requires enabled=true. |
response_code | int | 503 | HTTP status code returned when circuit is open Range: 400–599. Requires enabled=true. |
fallback_mode | string | error | How to handle requests when circuit is open Values: error, service. Requires enabled=true. |
fallback_service | []string | none | Backend URLs for fallback when mode is service Required when fallback_mode=service Requires fallback_mode=service. |
fallback_site | string | none | Connector site ID for fallback backend routing When set, fallback requests route through the named connector tunnel. Site must be defined in [connector.sites] Requires fallback_mode=service. |
fallback_timeout | duration | 5s | Timeout for fallback service requests Requires fallback_mode=service. |
include_fallback_header | bool (optional) | true | Include X-Circuit-Breaker and Retry-After headers in responses Requires enabled=true. |
combine_mode | string | or | How to combine trigger conditions or=any condition trips, and=all must trip Values: or, and. Requires enabled=true. |
trip_expression | string | none | Custom boolean expression for circuit trip evaluation expr-lang boolean expression. Variables: error_rate, success_rate, latency_p50/p95/p99/avg (seconds), network_error_rate, timeout_rate, status_5xx_rate, status_4xx_rate, requests_total, requests_per_second. gRPC: grpc_error_rate, grpc_success_rate, grpc_unavailable_rate, grpc_internal_rate, grpc_timeout_rate, grpc_requests_total. Overrides threshold-based evaluation when set Requires enabled=true. |
grpc_health_check | bool (optional) | false | Enable active gRPC health checks using grpc.health.v1 protocol Requires enabled=true. |
grpc_health_check_interval | duration | 10s | Interval between gRPC health check probes Min: 1s. Requires grpc_health_check. |
grpc_health_check_timeout | duration | 5s | Timeout per gRPC health check probe Min: 100ms. Requires grpc_health_check. |
Override time windows with country/CIDR-specific schedules
TOML: [proxy.mapping.time_windows] · Env: HEXON_PROXY_MAPPING_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Shadow/mirror targets for request duplication
TOML: [proxy.mapping.shadow] · Env: HEXON_PROXY_MAPPING_SHADOW_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique identifier for this shadow target Required. |
service | string | — | Shadow target URL Required. |
host_header | string | none | Override Host header sent to shadow target |
timeout | duration | none | Override request timeout for this shadow |
max_body_size | string | none | Override max body size for this shadow |
add_headers | bool (optional) | none | Override X-Hexon-Shadow-* header injection Inherits from global proxy setting when not set |
site | string | none | Connector site ID for remote shadow target When set, shadow requests route through the named connector tunnel. Site must be defined in [connector.sites] |
Sampling rate for shadow requests
TOML: [proxy.mapping.shadow.runtime_fraction] · Env: HEXON_PROXY_MAPPING_SHADOW_RUNTIME_FRACTION_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
percent | int | none | Sampling percentage of requests to mirror Range: 0–100. |
numerator | int | none | Fractional sampling numerator Use with denominator for precise low rates, e.g. 1/1000 = 0.1% Min: 0. |
denominator | int | none | Fractional sampling denominator Must be >= numerator Min: 1. |
Default health check applied to all mappings without explicit health_check config. Active by default even without this section.
TOML: [proxy.default_health_check] · Env: HEXON_PROXY_DEFAULT_HEALTH_CHECK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable active health checking for backends Probes backends on a schedule to detect failures before traffic is affected |
type | string | http | Health check protocol Values: tcp, http, http3, grpc. |
path | string | /health | HTTP path for health check requests Requires type=http,type=http3. |
method | string | GET | HTTP method for health check requests Values: GET, HEAD. Requires type=http,type=http3. |
expected_status | []int | none | Expected HTTP status codes from healthy backends. Empty means any non-5xx response is healthy. Range: 100–599. Requires type=http,type=http3. |
grpc_service | string | none | gRPC service name for grpc.health.v1.Health/Check Empty checks the overall server health Requires type=grpc. |
interval | duration | 10s | Interval between health check probes Min: 1s. |
timeout | duration | 5s | Timeout per health check probe Min: 100ms. |
unhealthy_threshold | int | 3 | Consecutive failures before marking backend unhealthy Min: 1. |
healthy_threshold | int | 2 | Consecutive successes before marking backend healthy Min: 1. |
tls_skip_verify | bool (optional) | none | Skip TLS certificate verification for health checks Inherits from mapping tls_check when not set |
Default circuit breaker settings for all routes
TOML: [proxy.circuit_breaker] · Env: HEXON_PROXY_CIRCUIT_BREAKER_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable circuit breaker for backend health tracking |
error_ratio_threshold | float | 0.25 | Trip circuit if 5xx error ratio exceeds this threshold Range: 0.0–1.0. Requires enabled=true. |
error_ratio_window | duration | 10s | Rolling window for error ratio calculation Requires enabled=true. |
latency_p95_threshold | duration | 1s | Trip circuit if P95 latency exceeds this duration Requires enabled=true. |
latency_p99_threshold | duration | none | Trip circuit if P99 latency exceeds this duration Requires enabled=true. |
network_error_threshold | float | 0.15 | Trip circuit if network error ratio exceeds this threshold Range: 0.0–1.0. Requires enabled=true. |
fallback_duration | duration | 30s | Duration the circuit stays open before entering half-open Requires enabled=true. |
recovery_duration | duration | 10s | Duration in half-open state before deciding to close or re-open Requires enabled=true. |
success_threshold | int | 2 | Successful requests needed in half-open state to close circuit Min: 1. Requires enabled=true. |
response_code | int | 503 | HTTP status code returned when circuit is open Range: 400–599. Requires enabled=true. |
fallback_mode | string | error | How to handle requests when circuit is open Values: error, service. Requires enabled=true. |
fallback_service | []string | none | Backend URLs for fallback when mode is service Required when fallback_mode=service Requires fallback_mode=service. |
fallback_site | string | none | Connector site ID for fallback backend routing When set, fallback requests route through the named connector tunnel. Site must be defined in [connector.sites] Requires fallback_mode=service. |
fallback_timeout | duration | 5s | Timeout for fallback service requests Requires fallback_mode=service. |
include_fallback_header | bool (optional) | true | Include X-Circuit-Breaker and Retry-After headers in responses Requires enabled=true. |
combine_mode | string | or | How to combine trigger conditions or=any condition trips, and=all must trip Values: or, and. Requires enabled=true. |
trip_expression | string | none | Custom boolean expression for circuit trip evaluation expr-lang boolean expression. Variables: error_rate, success_rate, latency_p50/p95/p99/avg (seconds), network_error_rate, timeout_rate, status_5xx_rate, status_4xx_rate, requests_total, requests_per_second. gRPC: grpc_error_rate, grpc_success_rate, grpc_unavailable_rate, grpc_internal_rate, grpc_timeout_rate, grpc_requests_total. Overrides threshold-based evaluation when set Requires enabled=true. |
grpc_health_check | bool (optional) | false | Enable active gRPC health checks using grpc.health.v1 protocol Requires enabled=true. |
grpc_health_check_interval | duration | 10s | Interval between gRPC health check probes Min: 1s. Requires grpc_health_check. |
grpc_health_check_timeout | duration | 5s | Timeout per gRPC health check probe Min: 100ms. Requires grpc_health_check. |
DNS module usage settings for backend resolution
TOML: [proxy.dns] · Env: HEXON_PROXY_DNS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
use_cluster | bool | false | Use DNS module instead of system DNS for backend resolution |
dnssec | bool (optional) | none | Override cluster DNSSEC setting for proxy backends Only effective when use_cluster=true Requires use_cluster=true. |
resolvers | []string | none | Override cluster DNS resolvers for proxy backends Only effective when use_cluster=true Requires use_cluster=true. |
Global shadow/mirror defaults for request duplication
TOML: [proxy.shadow] · Env: HEXON_PROXY_SHADOW_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Global enable/disable shadow mirroring |
timeout | duration | 5s | Request timeout for shadow requests Requires enabled=true. |
max_body_size | string | 10MB | Max request body size to buffer for shadow Requires enabled=true. |
add_headers | bool (optional) | true | Add X-Hexon-Shadow-* headers to shadow requests Requires enabled=true. |
max_idle_conns | int | 50 | Total idle connections in shadow transport pool Min: 0. Requires enabled=true. |
max_idle_conns_per_host | int | 10 | Idle connections per shadow backend host Min: 0. Requires enabled=true. |
max_conns_per_host | int | 100 | Max total connections per shadow backend host Min: 0. Requires enabled=true. |
idle_conn_timeout | duration | 90s | Idle shadow connection timeout Requires enabled=true. |
tls_handshake_timeout | duration | 10s | TLS handshake timeout for shadow backends Requires enabled=true. |
tls_verify | bool (optional) | true | Verify TLS certificates of shadow backends Requires enabled=true. |
Connection Pool
TOML: [connection_pool] · Env: HEXON_CONNECTIONPOOL_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable optimized connection pools |
max_pools_per_type | int | 10 | Maximum pools per type (HTTP/SQL/LDAP) Min: 1. Requires enabled=true. |
metrics_collection_interval | duration | 30s | How often to collect pool metrics Requires enabled=true. |
global_health_check_interval | duration | 60s | Global health check interval across all pools Requires enabled=true. |
default_connection_timeout | duration | 30s | Default connection timeout for new pools Requires enabled=true. |
default_idle_timeout | duration | 5m | Default idle timeout before connection is reclaimed Requires enabled=true. |
enable_adaptive_scaling | bool | true | Enable adaptive pool scaling based on utilization Requires enabled=true. |
enable_circuit_breaker | bool | true | Enable circuit breaker for backend failure protection Requires enabled=true. |
log_level | string | info | Logging level for connection pool subsystem Values: debug, info, warn, error. Requires enabled=true. |
HTTP-specific pool settings
TOML: [connection_pool.http] · Env: HEXON_CONNECTIONPOOL_HTTP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
max_connections | int | 100 | Maximum connections per pool Hard cap on total connections; increase for high-traffic backends Min: 1. |
min_connections | int | 10 | Minimum connections per pool Must be less than or equal to max_connections Min: 1. |
connection_timeout | duration | 30s | Timeout for establishing a new connection Includes DNS resolution and TCP handshake; increase for high-latency backends |
idle_timeout | duration | 5m | Idle time before a connection is closed Close idle connections after this duration to free resources |
health_check_interval | duration | 1m | Interval between pool health checks Lower values detect backend failures faster but increase probe traffic |
scale_up_threshold | float | 0.8 | Utilization threshold to trigger pool scale-up Pool grows when usage exceeds this fraction of max_connections Range: 0–1. |
scale_down_threshold | float | 0.3 | Utilization threshold to trigger pool scale-down Must be less than scale_up_threshold Range: 0–1. |
max_scale_per_minute | int | 3 | Maximum scaling operations allowed per minute Prevents rapid pool resizing oscillation under fluctuating load Min: 1. |
failure_threshold | int | 5 | Consecutive failures before opening circuit breaker Lower values trip faster but may cause false positives under transient errors Min: 1. |
failure_window | duration | 1m | Time window for counting failures Failures outside this window are not counted toward the threshold |
recovery_timeout | duration | 30s | Time to wait before attempting half-open state After this delay, one probe request is sent to test backend recovery |
success_threshold | int | 3 | Consecutive successes to close circuit from half-open Higher values ensure backend stability before fully resuming traffic Min: 1. |
max_idle_conns | int | 200 | Total maximum idle connections across all hosts Global idle connection limit; excess idle connections are closed immediately Min: 1. |
max_idle_conns_per_host | int | 50 | Maximum idle connections per host Per-host idle connection limit; higher values improve throughput to frequently accessed backends Min: 1. |
max_conns_per_host | int | 100 | Maximum total connections per host Caps active plus idle connections; prevents a single backend from consuming all pool capacity Min: 1. |
idle_conn_timeout | duration | 90s | Idle connection timeout before closure Close idle connections after this duration to free resources |
tls_handshake_timeout | duration | 10s | Timeout for TLS handshake completion Increase for backends with slow certificate chain validation or OCSP stapling |
response_header_timeout | duration | 30s | Timeout waiting for response headers from backend Time from request sent to first response header received; does not limit body transfer |
expect_continue_timeout | duration | 1s | Timeout waiting for 100-Continue response Only applies to requests with Expect: 100-continue header |
force_attempt_http2 | bool | true | Force HTTP/2 connection attempts Uses HTTP/2 even with custom TLS config; disable if backends do not support HTTP/2 |
insecure_skip_verify | bool | false | Skip TLS certificate verification for backends Not recommended for production use |
write_buffer_size | string | 32KB | Write buffer size Tuned for high-throughput proxy |
read_buffer_size | string | 32KB | Read buffer size Tuned for high-throughput proxy |
disable_compression | bool | true | Disable HTTP transport compression Recommended true for proxy to avoid double compression |
enable_metrics | bool | true | Enable connection pool metrics collection Feeds pool utilization data to adaptive scaling and Prometheus exporter |
metrics_interval | duration | 30s | Interval between metrics collection cycles Lower values give finer-grained data but increase collection overhead |
Subrequest
TOML: [subrequest] · Env: HEXON_SUBREQUEST_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable subrequest authentication endpoint Used by nginx auth_request or similar reverse proxy authentication |
path | string | /authrequest | Path for subrequest endpoint |
group_param | string | group | Query parameter name for required group |
allowed_origins | []string | — | Allowed origins for CORS-like protection Empty list allows all origins |
header_user | string | X-Hexon-User | Response header name for username |
header_email | string | X-Hexon-Email | Response header name for email |
header_name | string | X-Hexon-Name | Response header name for full name |
header_groups | string | X-Hexon-Groups | Response header name for groups (comma-separated) |
Forward Proxy
TOML: [forward_proxy] · Env: HEXON_FORWARDPROXY_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable QUIC forward proxy Provides browser-native VPN-like access using MASQUE (RFC 9298) |
hostname | string | — | Hostname for forward proxy connections Use when running behind a CDN that doesn’t support HTTP CONNECT; defaults to service hostname Requires enabled=true. |
port | int | 8443 | Dedicated port for forward proxy listener Must differ from service.port. Must be reachable by browsers (open firewall for this port) Range: 1–65535. Requires enabled=true. Required. |
network_interface | string | — | Network interface to bind to Defaults to service.network_interface if not set Requires enabled=true. |
public_port | int | — | Public-facing port for PAC URL generation Use when behind NAT/load balancer; defaults to port value Range: 0–65535. Requires enabled=true. |
preserve_client_port | bool (optional) | true | Use client connection port in Alt-Svc header When false, Alt-Svc advertises public_port instead Requires enabled=true. |
cert | string | — | TLS certificate for forward proxy hostname File path or inline PEM; falls back to service certificate if not set Requires enabled=true. |
auth_mode | string | session_fingerprint | Authentication mode for forward proxy ‘none’ disables all authentication — the forward proxy becomes an open proxy; use only in controlled environments Values: session_fingerprint, none. Requires enabled=true. |
session_cookie | string | hexon_session | Session cookie name Requires enabled=true. |
fingerprint_binding | bool | true | Enable JA4Q fingerprint binding for session security Requires enabled=true. |
fingerprint_binding_ttl | duration | 8h | Fingerprint binding TTL Requires fingerprint_binding=true. |
enable_tcp | bool | true | Enable HTTP/3 CONNECT (RFC 9114) for TCP proxying Requires enabled=true. |
enable_udp | bool | true | Enable CONNECT-UDP (RFC 9298) for UDP proxying Requires enabled=true. |
connect_timeout | duration | 10s | Backend connection timeout Requires enabled=true. |
idle_timeout | duration | 5m | Idle connection timeout Requires enabled=true. |
max_connection_duration | duration | 24h | Maximum connection lifetime Requires enabled=true. |
rate_limit_per_user | int | 1000 | Requests per second per user 0 means unlimited Min: 0. Requires enabled=true. |
rate_limit_per_destination | int | 100 | Requests per second per destination 0 means unlimited Min: 0. Requires enabled=true. |
bandwidth_limit_per_user | string | 100mbps | Bandwidth limit per user Supports mbps, gbps, kbps, mb/s, gb/s, kb/s Requires enabled=true. |
buffer_size | string | 32KB | TCP relay buffer size Requires enabled=true. |
udp_buffer_size | string | 1500B | UDP buffer size Requires enabled=true. |
max_http_response_size | string | 512MB | Maximum response body size for plain HTTP proxy requests Limits response body for non-CONNECT HTTP forwarding; 0 means unlimited Requires enabled=true. |
proxy_protocol | bool | false | Enable PROXY protocol for backend connections Disabled by default; most internet servers do not support PROXY protocol Requires enabled=true. |
proxy_protocol_version | string | v2 | PROXY protocol version v1 is text format, v2 is binary format (more efficient) Values: v1, v2. Requires proxy_protocol=true. |
udp_proxy_path | string | /masque | URL path for CONNECT-UDP requests Requires enabled=true. |
token_ttl | duration | 5m | Extension token validity duration Min: 30s. Requires enabled=true. |
token_refresh_interval | duration | 60s | Extension token refresh interval Min: 5s. Requires enabled=true. |
geo_enabled | bool | — | Enable geo-IP restrictions for forward proxy Overrides service-level geo settings when set Requires enabled=true. |
geo_allow_countries | []string | — | ISO 3166-1 alpha-2 country codes to allow Requires geo_enabled=true. |
geo_deny_countries | []string | — | Country codes to deny Takes precedence over allow list Requires geo_enabled=true. |
geo_allow_asn | []string | — | ASN numbers to allow Requires geo_enabled=true. |
geo_deny_asn | []string | — | ASN numbers to deny Takes precedence over allow list Requires geo_enabled=true. |
geo_bypass_cidr | []string | none | CIDRs that bypass geo checks Requires geo_enabled=true. |
geo_deny_code | int | 403 | HTTP status code for geo denials Requires geo_enabled=true. |
geo_deny_message | string | — | Custom denial message for geo-blocked requests Requires geo_enabled=true. |
time_enabled | bool | — | Enable time-based restrictions for forward proxy Overrides service-level time settings when set Requires enabled=true. |
time_timezone | string | — | Default timezone for time restrictions IANA timezone format Requires time_enabled=true. |
time_allow_days | []string | — | Allowed days of the week Requires time_enabled=true. |
time_deny_days | []string | — | Denied days of the week Takes precedence over allow list Requires time_enabled=true. |
time_allow_hours | string | — | Allowed hours range Format: HH:MM-HH:MM Requires time_enabled=true. |
time_deny_hours | string | — | Denied hours range Takes precedence over allow hours; format: HH:MM-HH:MM Requires time_enabled=true. |
time_bypass_cidr | []string | none | CIDRs that bypass time checks Requires time_enabled=true. |
time_deny_code | int | 403 | HTTP status code for time denials Requires time_enabled=true. |
time_deny_message | string | — | Custom denial message for time-blocked requests Requires time_enabled=true. |
PAC (Proxy Auto-Configuration) file settings
TOML: [forward_proxy.pac] · Env: HEXON_FORWARDPROXY_PAC_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable PAC file endpoint Serves auto-generated PAC files for browser proxy configuration |
path | string | /proxy.pac | URL path for PAC file Requires enabled=true. |
cache_ttl | duration | 15m | Browser cache TTL for PAC file Min: 1m. Requires enabled=true. |
use_firewall_targets | bool | true | Use firewall rules to determine proxy targets PAC file includes targets from firewall rules for the authenticated user Requires enabled=true. |
group | string | — | Group required to access PAC file If empty, any authenticated user can access; if set, only members of this group Requires enabled=true. |
Per-country or per-CIDR time windows
TOML: [forward_proxy.time_windows] · Env: HEXON_FORWARDPROXY_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Connector
TOML: [connector] · Env: HEXON_CONNECTOR_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable QUIC connector listener for remote site access |
hostname | string | — | Hostname for connector listener Use when running behind a CDN; defaults to service hostname Requires enabled=true. |
port | int | — | Dedicated QUIC port for connector connections Must differ from service.port and forward_proxy.port Range: 1–65535. Requires enabled=true. Required. |
network_interface | string | — | Network interface to bind connector listener Defaults to service.network_interface if not set Requires enabled=true. |
cert | string | — | TLS certificate for connector hostname File path or inline PEM; falls back to service certificate if not set Requires enabled=true. |
handshake_timeout | duration | 10s | Maximum time for connector handshake Requires enabled=true. |
heartbeat_interval | duration | 30s | Interval between heartbeat messages Requires enabled=true. |
adaptive_min_sample_size | int | 10 | Round-robin until N samples per instance Range: 1–1000. Requires enabled=true. |
adaptive_exploration_rate | float | 0.1 | Exploration rate (0.0-1.0) Range: 0.0–1.0. Requires enabled=true. |
adaptive_smoothing_factor | float | 0.3 | EMA smoothing factor for latency (0.0-1.0) Range: 0.0–1.0. Requires enabled=true. |
Remote site definitions
TOML: [connector.sites] · Env: HEXON_CONNECTOR_SITES_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
id | string | — | Unique site identifier Required. |
name | string | — | Human-readable site name Required. |
cidrs | []string | — | Restrict connector source IPs to these CIDR ranges Empty means any source IP is allowed |
max_instances | int | 0 | Maximum concurrent connector instances 0 means unlimited Min: 0. |
rebalance | bool (optional) | true | Enable cluster-wide connector load balancing Soft-rejects excess connectors so they redistribute across nodes |
rebalance_retries | int | 5 | Max soft-reject attempts before accepting Range: 1–10. Requires rebalance=true. |
client_ip_header | string | X-Forwarded-For | Header for client IP forwarding |
SSH Bastion
TOML: [bastion] · Env: HEXON_BASTION_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable SSH bastion server |
port | int | — | SSH listen port Range: 1–65535. Requires enabled=true. Required. |
enable_admin | bool | — | Enable admin CLI shell for privileged users Requires enabled=true. |
use_llm | bool | — | Enable AI assistant in bastion shell Requires [llm] section to be enabled and configured Requires llm.enabled. |
admin_groups | []string | — | Groups allowed to access the admin CLI Groups from [identity] directory. Required when enable_admin=true Requires enable_admin=true. |
network_interface | string | eth0 | Network interface to bind SSH listener to Requires enabled=true. |
ca_user_comment | string | hexon-user-ca@hexon.io | Comment identifier for the User CA key Requires enabled=true. |
ca_host_comment | string | hexon-host-ca@hexon.io | Comment identifier for the Host CA key Requires enabled=true. |
ca_threshold | bool | false | Enable threshold Ed25519 (FROST) for SSH User CA signing Fail-closed: no SSH user certs until FROST DKG completes (~3s). User CA key never exists on any single node. Requires cluster.cluster_mode=true,enabled=true. |
allow_internal_cert_auth | bool | true | Allow certificate authentication from localhost for web shell connections Requires enabled=true. |
internal_cert_ttl | duration | 5m | TTL for internal service certificates used by web shell Requires enabled=true. |
required_groups | []string | — | Groups required for bastion access; empty allows any authenticated user Groups from [identity] directory Requires enabled=true. |
device_code_timeout | duration | 5m | Timeout for device code authorization flow Requires enabled=true. |
idle_timeout | duration | 30m | Session idle timeout before automatic disconnect Requires enabled=true. |
max_session_duration | duration | 24h | Maximum allowed session duration Requires enabled=true. |
refresh_access_token | duration | 45m | Interval to refresh OAuth access token during active sessions Requires enabled=true. |
refresh_user_info | duration | 5m | Interval to refresh user info from IdP during active sessions Requires enabled=true. |
enable_syntax_highlighting | bool | true | Enable command syntax highlighting in the shell Requires enabled=true. |
cursor_style | string | default | Terminal cursor appearance style Values: default, blinking_block, steady_block, blinking_underline, steady_underline, blinking_bar, steady_bar. Requires enabled=true. |
banner | string | — | Message displayed after login before the greeting Supports multiline text Requires enabled=true. |
enable_autosuggestions | bool | — | Enable fish-style auto-suggestions in the shell Requires enabled=true. |
anomaly_watch | bool | — | Enable background anomaly alerts from log intelligence Requires enabled=true. |
anomaly_watch_interval | duration | 30s | Anomaly polling interval Requires anomaly_watch=true. |
enable_status_bar | bool (optional) | true | Enable persistent status bar at bottom of terminal by default Requires enabled=true. |
enable_suggestions | bool | — | Show contextual follow-up suggestions after commands Requires enabled=true. |
client_alive_interval | duration | 30s | Interval between SSH keepalive requests to prevent idle connection drops Set to 0 to disable; prevents firewalls/NAT from dropping idle SSH connections Requires enabled=true. |
ssh_connection_timeout | duration | 30s | Timeout for outbound SSH dial connections Requires enabled=true. |
port_forward_timeout | duration | 10s | Timeout for port forwarding TCP connections Requires enabled=true. |
sql_connection_timeout | duration | 10s | Timeout for SQL database connections Requires enabled=true. |
session_cleanup_interval | duration | 5m | Interval between session cleanup sweeps Requires enabled=true. |
blocked_cidrs | []string | — | CIDR ranges blocked for SSH and port forwarding (SSRF protection) Empty allows all; use for DMZ bastions to block private networks Requires enabled=true. |
admin_max_history_size | int | 100 | Maximum commands stored in admin shell history per session Range: 10–10000. Requires enable_admin=true. |
persist_history | bool | true | Persist command history across sessions (requires hexon backend) Requires enabled=true. |
history_persist_max | int | 100 | Maximum commands to persist across sessions Range: 10–10000. Requires persist_history=true. |
history_enabled | bool | true | Enable command history Requires enabled=true. |
history_case_insensitive | bool | — | Enable case-insensitive history search Requires enabled=true. |
history_ignore_dups | bool | true | Ignore consecutive duplicate commands in history Requires enabled=true. |
history_ignore_space | bool | — | Ignore commands starting with a space from history Requires enabled=true. |
history_bang_expansion | bool | true | Enable bang (!) history expansion Requires enabled=true. |
geo_enabled | bool | — | Enable geo-IP restrictions for bastion Overrides [service] geo settings when set Requires enabled=true. |
geo_allow_countries | []string | — | ISO 3166-1 alpha-2 country codes to allow Requires geo_enabled=true. |
geo_deny_countries | []string | — | Country codes to deny (takes precedence over allow) Requires geo_enabled=true. |
geo_allow_asn | []string | — | ASN numbers to allow Requires geo_enabled=true. |
geo_deny_asn | []string | — | ASN numbers to deny Requires geo_enabled=true. |
geo_bypass_cidr | []string | — | CIDRs that bypass geo-IP checks Requires geo_enabled=true. |
time_enabled | bool | — | Enable time-based access restrictions for bastion Overrides [service] time settings when set Requires enabled=true. |
time_timezone | string | — | Default timezone for time-based restrictions IANA timezone format Requires time_enabled=true. |
time_allow_days | []string | — | Allowed days of the week Requires time_enabled=true. |
time_deny_days | []string | — | Denied days of the week (takes precedence over allow) Requires time_enabled=true. |
time_allow_hours | string | — | Allowed hours range in 24h format Requires time_enabled=true. |
time_deny_hours | string | — | Denied hours range (takes precedence over allow) Requires time_enabled=true. |
time_bypass_cidr | []string | — | CIDRs that bypass time-based restrictions Requires time_enabled=true. |
time_deny_message | string | — | Custom message shown when access is denied by time restrictions Requires time_enabled=true. |
Session recording configuration in asciinema v2 format
TOML: [bastion.recording] · Env: HEXON_BASTION_RECORDING_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable session recording in asciinema v2 format |
path | string | — | Base directory for recording storage Recordings stored in hierarchical structure: {path}/YYYY/MM/DD/ Requires enabled=true. |
record_input | bool | true | Record user input keystrokes WARNING: captures passwords and sensitive data typed by users Requires enabled=true. |
record_output | bool | true | Record terminal output Requires enabled=true. |
compress | bool | true | Gzip compress recordings after session closes (.cast.gz) Requires enabled=true. |
max_file_size | string | 500MB | Maximum recording file size Requires enabled=true. |
max_file_disconnect | bool | true | Disconnect user when max recording file size is reached If false, recording stops but session continues Requires enabled=true. |
replay_allowed | bool | true | Allow users to replay their own session recordings Requires enabled=true. |
replay_admin_groups | []string | — | Groups with access to replay any user’s session recordings Empty means no admin replay access Requires enabled=true. |
SFTP subsystem relay configuration
TOML: [bastion.sftp] · Env: HEXON_BASTION_SFTP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | false | Enable SFTP subsystem relay |
required_groups | []string | — | Groups required for SFTP access; empty allows any bastion user Groups from [identity] directory Requires enabled=true. |
idle_timeout | duration | 10m | Idle timeout for SFTP sessions Requires enabled=true. |
Port forwarding access control configuration
TOML: [bastion.port_forwarding_acl] · Env: HEXON_BASTION_PORT_FORWARDING_ACL_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable port forwarding through the bastion |
required_groups | []string | — | Groups required for port forwarding access Requires enabled=true. |
allowed_destinations | []string | — | Static whitelist of allowed forwarding destinations Format: host:port, host:*, or *:port Requires enabled=true. |
dynamic_acl | bool | — | Enable per-user dynamic ACL from directory service Requires enabled=true. |
default_allow | bool | — | Allow all destinations when no ACL rules match Dangerous - use only for testing Requires enabled=true. |
max_forwards_per_session | int | — | Maximum concurrent port forwards per session Min: 0. Requires enabled=true. |
idle_timeout | duration | — | Idle timeout for port forward connections Requires enabled=true. |
Per-group/destination port forwarding access rules
TOML: [bastion.port_forwarding_acl.rules] · Env: HEXON_BASTION_PORT_FORWARDING_ACL_RULES_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Optional identifier for this forwarding rule |
groups | []string | — | Groups this rule applies to; empty means all groups |
destinations | []string | — | Destinations this rule applies to Supports hostnames, globs (*.example.com), CIDRs (10.0.0.0/8) |
allowed_ports | []string | — | Allowed destination ports Supports single ports, ranges (3306-3307), wildcard (*) |
allowed_types | []string | — | Allowed forwarding types; empty means all local (-L), remote (-R), dynamic (-D) Values: local, remote, dynamic. |
source_cidrs | []string | — | Client IP ranges allowed to use this rule Empty means no restriction |
max_forwards_per_session | int | — | Maximum concurrent forwards per session override for this rule Min: 0. |
DoS protection configuration for SSH bastion
TOML: [bastion.dos_protection] · Env: HEXON_BASTION_DOS_PROTECTION_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
max_global_connections | int | 0 | Maximum total concurrent SSH connections 0 means unlimited Min: 0. |
max_connections_per_ip | int | 0 | Maximum concurrent connections per source IP 0 means unlimited Min: 0. |
connection_rate_limit | rate_limit | none | New connection rate limit per IP Empty disables; format: count/duration |
auth_rate_limit | rate_limit | none | Authentication attempt rate limit per IP Empty disables; limits auth attempts per IP |
auth_failure_threshold | int | 0 | Failed auth attempts before IP ban 0 disables lockout Min: 0. |
auth_failure_ban_duration | duration | — | Ban duration after auth failure threshold exceeded |
max_sessions_per_user | int | 0 | Maximum concurrent sessions per username 0 means unlimited Min: 0. |
max_sessions_per_ip | int | 0 | Maximum concurrent sessions per source IP 0 means unlimited Min: 0. |
max_total_sessions | int | 0 | Global maximum active bastion sessions 0 means unlimited Min: 0. |
session_creation_rate | rate_limit | none | Session creation rate limit per IP Empty disables; limits new sessions per user |
command_rate_limit | rate_limit | none | Command execution rate limit per session Empty disables; limits commands per session |
command_timeout | duration | none | Maximum execution time per command Empty disables; maximum execution time per command |
max_command_length | string | 4KB | Maximum command length |
max_history_size | int | 1000 | Maximum commands stored in session history Min: 0. |
qr_generation_rate | rate_limit | none | QR code generation rate limit per IP Empty disables; limits QR code generation per user |
SSH user certificate generation configuration
TOML: [bastion.ssh_cert] · Env: HEXON_BASTION_SSH_CERT_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable SSH user certificate generation Disabling prevents all SSH certificate-based outbound connections via bastion |
cert_ttl | duration | 1m | Certificate validity duration Requires enabled=true. |
source_cidrs | []string | — | Restrict certificate usage to specific source IP ranges Empty means no restriction Requires enabled=true. |
force_command | string | — | Restrict certificate to execute only this command Empty means no restriction Requires enabled=true. |
permit_pty | bool | true | Allow PTY allocation in certificate Requires enabled=true. |
permit_port_forwarding | bool | — | Allow port forwarding in certificate Requires enabled=true. |
permit_agent_forwarding | bool | — | Allow SSH agent forwarding in certificate Requires enabled=true. |
permit_x11_forwarding | bool | — | Allow X11 forwarding in certificate Requires enabled=true. |
permit_user_rc | bool | — | Allow user rc script execution in certificate Requires enabled=true. |
Per-group/destination certificate rules; most-privileged-wins on match
TOML: [bastion.ssh_cert.rules] · Env: HEXON_BASTION_SSH_CERT_RULES_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Optional identifier for this certificate rule |
groups | []string | — | Groups this rule applies to; empty means all groups |
destinations | []string | — | Destinations this rule applies to Supports hostnames, globs (*.example.com), CIDRs (10.0.0.0/8) |
site | string | none | Connector site ID for remote SSH access When set, SSH connections route through connector tunnel |
principals | []string | — | Usernames allowed in the certificate Multiple principals allow user selection |
cert_ttl | duration | — | Certificate TTL override for this rule |
source_cidrs | []string | — | Source CIDR restriction override for this rule |
force_command | string | — | Forced command override for this rule |
permit_pty | bool (optional) | — | Allow PTY allocation override for this rule |
permit_port_forwarding | bool (optional) | — | Allow port forwarding override for this rule |
permit_agent_forwarding | bool (optional) | — | Allow agent forwarding override for this rule |
permit_x11_forwarding | bool (optional) | — | Allow X11 forwarding override for this rule |
permit_user_rc | bool (optional) | — | Allow user rc execution override for this rule |
SSH CA auto-setup endpoint for target host enrollment
TOML: [bastion.sshca_setup] · Env: HEXON_BASTION_SSHCA_SETUP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool (optional) | true | Enable SSH CA auto-setup endpoint for target host enrollment |
allowed_cidrs | []string | — | Source CIDRs allowed to access enrollment endpoints Empty allows all source IPs |
cert_validity | duration | 90d | Host certificate validity duration |
Per-country or per-CIDR time access windows
TOML: [bastion.time_windows] · Env: HEXON_BASTION_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
SQL Bastion
TOML: [sql_bastion] · Env: HEXON_SQLBASTION_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable SQL bastion for interactive database access |
Available SQL database site configurations
TOML: [sql_bastion.sites] · Env: HEXON_SQLBASTION_SITES_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique identifier for this database site Required. |
type | string | — | Database engine type Values: mysql, postgres. Required. |
host | string | — | Database server hostname or IP address Required. |
port | int | 3306 | Database server port TOML default is 3306; explicitly set to 5432 for PostgreSQL Range: 1–65535. |
site | string | none | Connector site ID for remote database access When set, database connections route through connector tunnel |
user | string | — | Database connection username Required. |
database | string | — | Default database/schema to connect to |
ssl | bool | — | Enable SSL/TLS for this database connection |
skip_tls | bool | — | Skip server certificate verification (TLS on, no cert check) For self-signed certs; MySQL: tls=skip-verify, PostgreSQL: sslmode=require Requires ssl=true. |
ssl_mode | string | — | PostgreSQL SSL mode Ignored for MySQL Values: disable, require, verify-ca, verify-full. Requires type=postgres. |
ssl_cert | string | — | Path to client certificate for mutual TLS Requires ssl=true. |
ssl_ca | string | — | Path to CA certificate for server verification Requires ssl=true. |
connect_timeout | duration | 10s | Connection timeout |
tls_min_version | string | 1.2 | Minimum TLS version Values: 1.2, 1.3. |
Access control rules for this site; least restrictive match wins
TOML: [sql_bastion.sites.acls] · Env: HEXON_SQLBASTION_SITES_ACLS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
acl | string | — | Group name required for this ACL; user must be a member Required. |
readonly | bool | — | Restrict to read-only queries (SELECT, SHOW, DESCRIBE, EXPLAIN) |
query_timeout | duration | — | Maximum query execution time |
query_must_contain | []string | — | Required patterns in query (all must match, case-insensitive) |
query_must_not_contain | []string | — | Forbidden patterns in query (none may match, case-insensitive) |
query_max_limit | int | — | Maximum LIMIT value enforced on queries Queries exceeding this are rewritten; queries without LIMIT get this added Min: 0. |
allowed_tables | []string | — | Table whitelist; * for all, supports wildcards (app.) PostgreSQL: use schema-qualified names (public., analytics.*) |
forbidden_tables | []string | — | Table blacklist (takes precedence over allowed_tables) |
case_sensitive_tables | bool | — | Enable case-sensitive table name matching MySQL is case-insensitive by default on most systems |
masked_columns | []string | — | Column name patterns to mask in results (glob: credit_card_*, *_email) |
mask_strategy | string | partial | Masking display strategy Values: full, partial, hash, optional. |
Query rate limiting configuration
TOML: [sql_bastion.sites.acls.rate_limit] · Env: HEXON_SQLBASTION_SITES_ACLS_RATE_LIMIT_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
queries_per_minute | int | — | Maximum queries allowed per window Multi-statement queries count as multiple Min: 0. |
burst_allowed | int | — | Extra queries allowed beyond rate limit (burst capacity) Total allowed = queries_per_minute + burst_allowed Min: 0. |
window_size | duration | — | Rate limit sliding window duration |
Database server-side resource limit configuration
TOML: [sql_bastion.sites.acls.query_limits] · Env: HEXON_SQLBASTION_SITES_ACLS_QUERY_LIMITS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
max_complexity_score | int | — | Maximum allowed query complexity score Base:10, JOIN:+20, subquery:+30, LIKE:+15, GROUP BY:+25, ORDER BY:+15, HAVING:+20, aggregate:+10, UNION:+25 Min: 0. |
max_execution_time | duration | — | Database-enforced query execution time limit MySQL: max_execution_time; PostgreSQL: statement_timeout |
max_rows | int | — | Maximum rows returned per query MySQL: sql_select_limit; PostgreSQL: not supported (use LIMIT) Min: 0. |
max_memory | string | — | Memory limit for sorting and aggregate operations MySQL: max_sort_length; PostgreSQL: work_mem |
Web Shell
TOML: [webshell] · Env: HEXON_WEBSHELL_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable the web shell terminal service |
required_groups | []string | — | Groups required for web shell access User must be a member of at least one group; empty inherits from bastion.required_groups Requires enabled=true. |
max_sessions_per_user | int | 3 | Max concurrent web shell sessions per user Min: 1. Requires enabled=true. |
session_timeout | duration | 30m | Inactive session timeout duration Requires enabled=true. |
geo_enabled | bool | false | Enable geo-IP restrictions for web shell Overrides [service] geo settings when set Requires enabled=true. |
geo_allow_countries | []string | — | ISO 3166-1 alpha-2 country codes to allow Requires geo_enabled=true. |
geo_deny_countries | []string | — | Country codes to deny (takes precedence over allow) Requires geo_enabled=true. |
geo_allow_asn | []string | — | ASN numbers to allow Requires geo_enabled=true. |
geo_deny_asn | []string | — | ASN numbers to deny Requires geo_enabled=true. |
geo_bypass_cidr | []string | — | CIDRs that bypass geo-IP checks Requires geo_enabled=true. |
time_enabled | bool | — | Enable time-based restrictions for web shell Overrides [service] time settings when set Requires enabled=true. |
time_timezone | string | — | Default timezone in IANA format IANA timezone format (e.g., America/New_York) Requires time_enabled=true. |
time_allow_days | []string | — | Allowed days of the week Requires time_enabled=true. |
time_deny_days | []string | — | Denied days of the week (takes precedence over allow) Requires time_enabled=true. |
time_allow_hours | string | — | Allowed hours range Requires time_enabled=true. |
time_deny_hours | string | — | Denied hours range (takes precedence over allow) Requires time_enabled=true. |
time_bypass_cidr | []string | — | CIDRs that bypass time-based checks Requires time_enabled=true. |
time_deny_message | string | — | Custom message shown when access is denied by time restriction Requires time_enabled=true. |
Per-country or per-CIDR time windows
TOML: [webshell.time_windows] · Env: HEXON_WEBSHELL_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
TCP Proxy
TOML: [tcp_proxy] · Env: HEXON_TCPPROXY_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable mTLS-authenticated TCP/TLS proxy |
cert | string | — | Path to service TLS certificate for mTLS listener Requires enabled=true. |
buffer_size | string | 32KB | TCP relay buffer size Requires enabled=true. |
connect_timeout | duration | 10s | Backend connection timeout Requires enabled=true. |
idle_timeout | duration | 5m | Idle connection timeout Requires enabled=true. |
max_connection_duration | duration | 24h | Maximum connection lifetime Requires enabled=true. |
max_connections_per_user | int | 0 | Maximum concurrent connections per user (0 = unlimited) Range: 0–10000. Requires enabled=true. |
TCP proxy port mappings (listener to backend pool)
TOML: [tcp_proxy.mapping] · Env: HEXON_TCPPROXY_MAPPING_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique identifier for this mapping Alphanumeric, hyphens, underscores; max 64 chars Required. |
listen_port | int | — | TCP port to listen on for connections Range: 1–65535. Required. |
auth | bool (optional) | true | Enable mTLS authentication When false, acts as pure TCP passthrough without TLS termination |
cert | string | — | Path to TLS certificate for this mapping listener Falls back to global tcp_proxy.cert if not set |
protocol_hint | string | — | Protocol-specific optimizations for health checks and logging Optional protocol identifier for logging and metrics Values: mysql, postgresql, redis, mongodb, memcached, custom. |
backends | []string | — | Backend addresses in host:port format Required. |
lb_strategy | string | round_robin | Load balancing strategy Values: round_robin, weighted, least_connections, hash, random, maglev. |
lb_hash_key | string | cert_serial | Key for hash-based load balancing Only used when lb_strategy=hash Values: cert_serial, cn, ip. |
lb_weights | []int | — | Weights for weighted round-robin (must match backends count) Only used when lb_strategy=weighted; defaults to equal weights Min: 1. |
health_check_enabled | bool | true | Enable backend health checks |
health_check_interval | duration | 10s | Interval between health checks Requires health_check_enabled=true. |
health_check_timeout | duration | 5s | Timeout for each health check Must be less than health_check_interval Requires health_check_enabled=true. |
health_check_type | string | tcp | Health check type Values: tcp, mysql, postgresql, redis. Requires health_check_enabled=true. |
allowed_groups | []string | none | Groups allowed to connect (OR logic, empty = all) Empty allows all authenticated users |
denied_groups | []string | none | Groups denied from connecting (takes precedence over allow) Takes precedence over allowed_groups |
allowed_subnets | []string | none | Allowed client CIDRs (empty = all) Empty allows all client IPs |
geo_enabled | bool | false | Enable geo-IP restrictions for this mapping |
geo_allow_countries | []string | — | Allowed country codes (ISO 3166-1 alpha-2) Requires geo_enabled=true. |
geo_deny_countries | []string | — | Denied country codes (takes precedence over allow) Requires geo_enabled=true. |
geo_allow_asn | []string | — | Allowed Autonomous System Numbers Requires geo_enabled=true. |
geo_deny_asn | []string | — | Denied Autonomous System Numbers (takes precedence over allow) Requires geo_enabled=true. |
geo_bypass_cidr | []string | — | CIDRs that bypass geo-IP checks Requires geo_enabled=true. |
time_enabled | bool | false | Enable time-based access restrictions |
time_timezone | string | — | Default timezone for time restrictions IANA timezone format Requires time_enabled=true. |
time_allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. Requires time_enabled=true. |
time_deny_days | []string | — | Denied days of the week (takes precedence over allow) Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. Requires time_enabled=true. |
time_allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM Requires time_enabled=true. |
time_deny_hours | string | — | Denied hours range (takes precedence over allow) Format: HH:MM-HH:MM Requires time_enabled=true. |
time_bypass_cidr | []string | — | CIDRs that bypass time-based checks Requires time_enabled=true. |
rate_limit | rate_limit | none | Rate limit per user Per-mapping rate limit; empty means no limit |
max_connections | int | 0 | Max concurrent connections for this mapping (0 = unlimited) Min: 0. |
backend_tls | bool | false | Enable TLS for backend connections |
backend_tls_verify | bool | false | Verify backend TLS certificate Requires backend_tls=true. |
backend_tls_sni | string | — | SNI hostname for backend TLS Requires backend_tls=true. |
backend_tls_ca | string | — | CA certificate for backend verification (file path or inline PEM) Inline PEM or file path for backend TLS verification Requires backend_tls=true. |
backend_tls_cert | string | — | Client certificate for mTLS to backend (file path or inline PEM) Inline PEM or file path for mTLS to backend Requires backend_tls=true. |
backend_tls_min_version | string | 1.3 | Minimum TLS version for backend connections Values: 1.2, 1.3. Requires backend_tls=true. |
circuit_breaker_enabled | bool | false | Enable circuit breaker for backend failures |
circuit_breaker_error_threshold | float | 0.5 | Error ratio threshold to trip circuit breaker Range: 0–1. Requires circuit_breaker_enabled=true. |
circuit_breaker_window | duration | 10s | Time window for error rate tracking Requires circuit_breaker_enabled=true. |
circuit_breaker_fallback_time | duration | 30s | Duration circuit stays open before half-open retry Requires circuit_breaker_enabled=true. |
outlier_detection_enabled | bool | false | Enable outlier detection for backend ejection |
outlier_detection_interval | duration | 10s | Interval between outlier analysis runs Requires outlier_detection_enabled=true. |
outlier_detection_failure_rate | int | 50 | Failure percentage threshold to eject a backend Range: 1–100. Requires outlier_detection_enabled=true. |
outlier_detection_min_requests | int | 10 | Minimum requests before outlier analysis applies Requires outlier_detection_enabled=true. |
outlier_detection_ejection_time | duration | 30s | Base ejection duration for outlier backends Requires outlier_detection_enabled=true. |
outlier_detection_max_ejection | int | 50 | Maximum percentage of backends that can be ejected Range: 1–100. Requires outlier_detection_enabled=true. |
buffer_size | string | — | TCP relay buffer size override Overrides global buffer_size; empty = use global default |
connect_timeout | duration | — | Backend connection timeout override Overrides global connect_timeout; empty = use global default |
idle_timeout | duration | — | Idle connection timeout override Overrides global idle_timeout; empty = use global default |
max_connection_duration | duration | — | Maximum connection lifetime override Overrides global max_connection_duration; empty = use global default |
Time windows for specific countries or CIDRs
TOML: [tcp_proxy.mapping.time_windows] · Env: HEXON_TCPPROXY_MAPPING_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
VPN
TOML: [vpn] · Env: HEXON_VPN_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable IKEv2 VPN server RFC 7296. |
debug | bool | false | Enable verbose debug logging with packet-level traces Generates high-volume output; use only for troubleshooting Requires enabled=true. |
network_interface | string | — | Network interface for VPN traffic Must match external IP reachable by VPN clients. Defaults to service.network_interface if not set Requires enabled=true. |
ikev2_port | int | 500 | IKEv2 protocol port (UDP) Range: 1–65535. RFC 7296. Requires enabled=true. |
esp_port | int | 4500 | ESP/NAT-T port (UDP) Range: 1–65535. RFC 3948. Requires enabled=true. |
single_port | bool | false | All IKEv2 on port 4500 only (L4 LB compatible) Requires enabled=true. |
hostname | string | — | VPN server hostname for profiles and emails Defaults to service.hostname if not set; useful when VPN is behind a separate load balancer Max: 255. Requires enabled=true. |
max_goroutines | int | none | Max concurrent IKE/ESP processing goroutines Range: 100–100000. Requires enabled=true. |
max_pending_auth | int | none | Max pending auth contexts before IKE_AUTH completes Range: 100–50000. Requires enabled=true. |
dns_queries_per_minute | int | 500 | DNS rate limit per VPN client (rolling window) Prevents DNS amplification attacks while allowing normal browsing Requires enabled=true. |
geo_enabled | bool | — | Enable VPN-specific geo restrictions Overrides [service] geo config when set Requires enabled=true. |
geo_allow_countries | []string | — | Allowed country codes (ISO 3166-1 alpha-2) Requires geo_enabled=true. |
geo_deny_countries | []string | — | Denied country codes (ISO 3166-1 alpha-2) Requires geo_enabled=true. |
geo_allow_asn | []string | — | Allowed ASN numbers Requires geo_enabled=true. |
geo_deny_asn | []string | — | Denied ASN numbers Requires geo_enabled=true. |
geo_bypass_cidr | []string | — | CIDRs that bypass geo checks Requires geo_enabled=true. |
time_enabled | bool | — | Enable VPN-specific time restrictions Overrides [service] time config when set Requires enabled=true. |
time_timezone | string | — | Default timezone for time restrictions IANA timezone format Requires time_enabled=true. |
time_allow_days | []string | — | Allowed days of week Requires time_enabled=true. |
time_deny_days | []string | — | Denied days of week Requires time_enabled=true. |
time_allow_hours | string | — | Allowed hours range Requires time_enabled=true. |
time_deny_hours | string | — | Denied hours range Requires time_enabled=true. |
time_bypass_cidr | []string | — | CIDRs that bypass time checks Requires time_enabled=true. |
time_deny_message | string | — | Custom denial message for time-based restrictions Requires time_enabled=true. |
VPN network configuration
TOML: [vpn.network] · Env: HEXON_VPN_NETWORK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
subnet | string | — | VPN client IP subnet IPv4 only; first usable IP is gateway. Changing requires revoking all VPN profiles Required. |
gateway | string | — | VPN gateway IP address Must be an IPv4 address within the VPN subnet Required. |
dns_domains | []string | — | DNS domains for split DNS Clients use VPN DNS for queries matching these domains RFC 8598. |
dns_cache_size | int | 10000 | DNS cache size in number of entries Omit to use system default Range: 1–1000000. |
dns_cache_ttl | duration | none | DNS cache TTL Range: 1s–24h. |
dns_hijack | bool | — | Intercept all port 53 DNS traffic When false, only intercepts DNS to gateway IP |
mtu | int | 1400 | MTU for VPN tunnel 1400 accounts for IKEv2/ESP overhead on most networks Range: 576–9000. |
internal_interface | string | hexon0 | Internal dummy interface name for route-based VPN |
enable_nat_keepalive | bool | true | Enable NAT-T keepalive packets RFC 3948. |
nat_keepalive_interval | duration | 20s | Interval between NAT keepalive packets RFC 3948. |
ipv6_enabled | bool (optional) | true | Enable IPv6 dual-stack support Derived from IPv4 using fd7a:ec0a::/48 ULA prefix. Disable if clients don’t support dual-stack |
wildcard_max_hosts_per_domain | int | 100 | Max hostnames tracked per wildcard domain Prevents unbounded memory growth from wildcard DNS rules |
wildcard_max_hosts_total | int | 1000 | Max total hostnames across all wildcard domains |
VPN authentication configuration
TOML: [vpn.auth] · Env: HEXON_VPN_AUTH_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
ldap_bind_timeout | duration | none | LDAP bind timeout Range: 100ms–1m. |
max_auth_attempts | int | none | Maximum authentication attempts before lockout Range: 1–10. |
auth_timeout | duration | none | IKE_AUTH phase timeout Range: 1s–5m. RFC 7296. |
group | string | none | Required LDAP group for VPN access Group from [identity] directory. Empty means no group restriction |
lease_valid | duration | none | Profile/lease validity duration Use hours; e.g. 1080h for 45 days Range: 24h–8760h. |
dpd_timeout | duration | 90s | Dead Peer Detection timeout Range: 30s–10m. RFC 7296. |
dpd_interval | duration | 30s | DPD liveness probe interval Range: 10s–5m. RFC 7296. |
dpd_retries | int | 3 | Consecutive DPD probe failures before declaring peer dead Range: 1–10. RFC 7296. |
authorization_required | bool | — | Require post-authentication authorization via signin service Users must complete authorization before gaining full network access |
authorization_timeout | duration | 10m | Time limit for completing authorization Range: 1m–1h. Requires authorization_required=true. |
captive_portal | bool (optional) | — | Enable captive portal detection for unauthorized sessions Defaults to authorization_required value. Captive portal redirect uses device code flow Requires authorization_required=true. |
captive_portal_domains | []string | — | Domains used for captive portal detection Defaults to major OS/browser detection domains if not set Requires authorization_required=true. |
psk_reminder_enabled | bool (optional) | true | Enable PSK expiration reminder emails |
psk_reminder_interval | duration | 24h | How often to check for expiring PSKs Requires psk_reminder_enabled. |
psk_reminder_days | int | 15 | Days before expiry to start sending reminders Requires psk_reminder_enabled. |
psk_reminder_timeout | duration | 5m | Timeout for each reminder check run Requires psk_reminder_enabled. |
psk_reminder_retries | int | 3 | Number of retries on transient failures Requires psk_reminder_enabled. |
psk_reminder_retry_delay | duration | 30s | Delay between retries Requires psk_reminder_enabled. |
group_refresh_interval | duration | 15m | Group membership change monitoring interval Backup for event-driven callbacks Range: 1m–1h. |
Device code authorization flow settings
TOML: [vpn.auth.device_code] · Env: HEXON_VPN_AUTH_DEVICE_CODE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable device code flow for VPN authorization When enabled, VPN clients display QR code/user code for authorization via secondary device RFC 8628. |
email_notification | bool (optional) | true | Send email with authorization code and link RFC 8628. Requires enabled=true. |
ttl | duration | 5m | Time-to-live for device authorization codes Range: 1m–30m. RFC 8628. Requires enabled=true. |
polling_interval | duration | 5s | Interval between authorization status checks Range: 1s–60s. RFC 8628. Requires enabled=true. |
IKEv2 cryptographic proposals
TOML: [vpn.crypto] · Env: HEXON_VPN_CRYPTO_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
ike_proposals | []string | — | IKE Phase 1 cryptographic proposals RFC 7296. Required. |
esp_proposals | []string | — | ESP Phase 2 cryptographic proposals RFC 7296. Required. |
dh_groups | []int | — | Diffie-Hellman key exchange groups Groups 14+ (2048-bit+) recommended; groups 1, 2, 5 are weak (Logjam attack) Values: 1, 2, 5, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 30, 31. RFC 7296. Required. |
rekey_interval | duration | 24h | Child SA rekey interval for ESP key rotation Set to 0 to disable rekeying Range: 1m–24h. RFC 7296. |
ike_sa_lifetime | duration | 168h | IKE SA lifetime (max session duration) Sessions auto-reconnect after this duration Range: 24h–720h. RFC 7296. |
sha1_policy | string | warn | SHA-1 security policy for IKEv2 algorithms Rejecting SHA-1 may break legacy IKEv2 clients Values: allow, warn, deprecate, reject. |
gVisor netstack configuration
TOML: [vpn.netstack] · Env: HEXON_VPN_NETSTACK_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
tcp_buffer_size | string | 4MB | TCP buffer size Range: 1MB-100MB |
udp_buffer_size | string | 1MB | UDP buffer size Range: 64KB-10MB |
max_connections | int | none | Maximum concurrent netstack connections Range: 1–100000. |
tcp_keepalive | duration | none | TCP keepalive interval Range: 10s–1h. |
tcp_timeout | duration | none | TCP connection timeout Range: 1m–24h. |
VPN routing configuration
TOML: [vpn.routing] · Env: HEXON_VPN_ROUTING_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
cidrs | []string | 0.0.0.0/0 | CIDRs to route via VPN tunnel VPN subnet is always included automatically; NAT/MASQUERADE is always enabled Required. |
Inter-node VPN transit via WireGuard mesh
TOML: [vpn.internode] · Env: HEXON_VPN_INTERNODE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable inter-node VPN transit via WireGuard mesh Linux only — excluded from non-Linux builds. Requires cluster_mode=true and WireGuard kernel module |
interface | string | wg-hx-transit | WireGuard mesh interface name Linux limit: 15 characters max Max: 15. Requires enabled=true. |
port | int | 51820 | WireGuard mesh port (UDP) Range: 1–65535. Requires enabled=true. |
mtu | int | 1380 | MTU for WireGuard mesh interface Accounts for double encapsulation: VPN client > ESP > WireGuard mesh Range: 1280–1500. Requires enabled=true. |
sync_interval | duration | 5s | Peer list refresh interval Range: 1s–1m. Requires enabled=true. |
stale_timeout | duration | 180s | Remove peers not seen for this duration Must be greater than sync_interval Requires enabled=true. |
keepalive | duration | 25s | WireGuard persistent keepalive interval Range: 10s–5m. Requires enabled=true. |
debug | bool | — | Enable debug logging for internode operations Requires enabled=true. |
Per-country/CIDR time windows
TOML: [vpn.time_windows] · Env: HEXON_VPN_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Firewall
TOML: [firewall] · Env: HEXON_FIREWALL_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable firewall ACL system for VPN access control |
blocked_networks | []string | — | Networks to block globally for all VPN users Networks blocked for [vpn] users. Defaults to RFC1918, link-local, loopback, multicast if empty Requires enabled=true. |
dns_refresh_enabled | bool | true | Enable automatic DNS refresh for ACL hostnames Requires enabled=true. |
dns_refresh_min_interval | duration | 1m | Minimum DNS refresh interval Requires dns_refresh_enabled=true. |
dns_refresh_max_interval | duration | 1h | Maximum DNS refresh interval Must be >= dns_refresh_min_interval Requires dns_refresh_enabled=true. |
dns_refresh_jitter | int | 10 | DNS refresh jitter percentage Range: 0–100. Requires dns_refresh_enabled=true. |
dns_refresh_init_timeout | duration | 10s | DNS resolution timeout at startup Requires dns_refresh_enabled=true. |
nft_pool_size | int | 5 | nftables connection pool size Range: 1–100. Requires enabled=true. |
max_rules_per_chain | int | 1000 | Maximum nftables rules per peer chain Set to 0 for unlimited Requires enabled=true. |
Reusable host and port alias definitions for ACL rules
TOML: [firewall.aliases] · Env: HEXON_FIREWALL_ALIASES_<KEY>
Named sets of destination hosts for ACL rules
TOML: [firewall.aliases.hosts] · Env: HEXON_FIREWALL_ALIASES_HOSTS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique alias name Required. |
hosts | []string | — | Destination IPs, CIDRs, or hostnames Supports IPs, CIDRs, hostnames, and wildcard domains (*.example.com) Required. |
site | string | none | Connector site ID for remote access When set, destinations resolve on the remote site via connector tunnel |
Named sets of protocol/port combinations for ACL rules
TOML: [firewall.aliases.ports] · Env: HEXON_FIREWALL_ALIASES_PORTS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique alias name Required. |
Protocol and port combinations
TOML: [firewall.aliases.ports.entries] · Env: HEXON_FIREWALL_ALIASES_PORTS_ENTRIES_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
proto | string | — | Network protocol Values: tcp, udp, icmp, esp, any. Required. |
ports | []int | — | Port numbers; leave empty for icmp/esp/any Range: 1–65535. |
Group-based firewall access control rules
TOML: [firewall.rules] · Env: HEXON_FIREWALL_RULES_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
rule | string | — | Unique rule identifier Required. |
src | []string | — | Source LDAP groups; users in any group match (OR logic) LDAP groups from [identity] directory Required. |
dst | []string | — | Destination host alias names from aliases.hosts Required. |
ports | []string | — | Port alias names from aliases.ports; use ‘any’ for all Required. |
Protection
TOML: [protection] · Env: HEXON_PROTECTION_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
pow | bool | — | Enable Proof-of-Work challenge for bot protection |
pow_difficulty | int | 4 | PoW hash difficulty level Range: 1–32. Requires pow=true. |
pow_difficulty_time | duration | 5m | TTL for PoW tokens Requires pow=true. |
pow_session_ttl | duration | 30m | How long a PoW session remains valid after successful challenge Requires pow=true. |
pow_cookie_name | string | hexon_pow | Cookie name for PoW sessions Must differ from session cookie name Requires pow=true. |
pow_random_fields | bool | true | Use random form field names to deter bots Requires pow=true. |
pow_decoy_fields | int | 5 | Number of honeypot decoy fields in PoW form Range: 0–100. Requires pow=true. |
pow_min_render_time | duration | 200ms | Minimum time before form submission is accepted Requires pow=true. |
pow_body_ttl | duration | 5m | TTL for stored POST bodies during PoW challenge Requires pow=true. |
pow_body_max_size | string | 1MB | Maximum POST body size to preserve during PoW Requires pow=true. |
rate_limit | rate_limit | none | Request rate limit Empty disables global rate limiting; format: count/duration (e.g., 100/1m) |
rate_limit_type | string | fingerprint | Client identification method for rate limiting fingerprint uses TLS+HTTP/2+TCP composite Values: fingerprint, ip. |
rate_limit_bantime | duration | — | Duration to ban client after rate limit exceeded Empty disables banning; client is rate-limited momentarily but not blocked long-term |
rate_limit_max_clients | int | 100000 | Maximum number of clients to track for rate limiting Prevents memory exhaustion Range: 0–10000000. |
max_bytes | string | none | Default maximum request body size Empty disables body size limiting; applies to all request bodies |
password_min_length | int | 12 | Minimum password length Range: 0–128. |
password_min_score | int | 3 | Minimum zxcvbn password strength score Range: 0–4. |
password_min_entropy | float | 40.0 | Minimum password entropy in bits Range: 0–256. |
password_require_upper | bool | false | Require at least one uppercase letter |
password_require_lower | bool | false | Require at least one lowercase letter |
password_require_digit | bool | false | Require at least one digit |
password_require_special | bool | false | Require at least one special character |
Per-host/path exceptions for request body size limits
TOML: [protection.max_bytes_exceptions] · Env: HEXON_PROTECTION_MAX_BYTES_EXCEPTIONS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
host | string | — | Hostname to match; empty matches all hosts |
path | string | — | Path pattern (exact, wildcard, or regex) Exact: /upload/large. Wildcard: /upload/* (shell glob). Regex: /upload/[0-9]+ (set regex=true) |
bytes | string | — | Size limit for matching requests Required. |
regex | bool | false | Treat path as regular expression |
IKEv2 Intrusion Detection System configuration
TOML: [protection.ikev2ids] · Env: HEXON_PROTECTION_IKEV2IDS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable IKEv2 Intrusion Detection System Automatically enabled when vpn.enabled=true unless explicitly set to false |
block_malicious | bool | true | Block detected threats instead of log-only mode Requires enabled=true. |
log_level | string | info | IDS logging verbosity level Values: trace, debug, info, warn, error. Requires enabled=true. |
dos_threshold | int | 100 | Maximum connections per minute per IP before DoS detection Range: 0–100000. Requires enabled=true. |
anomaly_sensitivity | float | 0.95 | Statistical anomaly detection threshold Higher values = less sensitive Range: 0.0–1.0. Requires enabled=true. |
trusted_networks | []string | — | CIDRs to skip IP-based checks; signatures still apply Requires enabled=true. |
WAF
TOML: [waf] · Env: HEXON_WAF_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable WAF protection |
paranoia | int | 1 | OWASP CRS paranoia level 1=low (few false positives), 2=medium, 3=high, 4=paranoid (many false positives) Values: 1, 2, 3, 4. Range: 1–4. Requires enabled=true. |
detection_only | bool | false | Log-only mode without blocking requests Useful for rule calibration; monitor logs for false positives before enforcing Requires enabled=true. |
self_contained | bool | false | Use self-contained blocking instead of anomaly scoring Self-contained: each rule blocks immediately. Anomaly scoring (default): accumulates scores and blocks if threshold exceeded Requires enabled=true. |
max_body_size | string | none | Maximum request body size to inspect Accepts units: B, KB, MB, GB, TB Requires enabled=true. |
inspect_body | bool | false | Inspect request bodies for attacks Enables request body inspection for injection attacks; requires max_body_size Requires enabled=true. |
inspect_response | bool | — | Inspect response bodies for data leakage Enabling this has a performance impact on every proxied response Requires enabled=true. |
disabled_rules | []int | — | OWASP CRS rule IDs to disable Use to suppress specific false positives by rule ID Requires enabled=true. |
disabled_tags | []string | — | OWASP CRS rule tags to disable Disables all rules with the given tag (e.g., attack-sqli, attack-xss) Requires enabled=true. |
Operator-defined custom WAF rules loaded alongside OWASP CRS
TOML: [waf.custom_rule] · Env: HEXON_WAF_CUSTOM_RULE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
id | int | — | Unique rule ID Use 10000+ to avoid conflicts with OWASP CRS rule IDs Min: 10000. Required. |
name | string | — | Descriptive rule name Required. |
severity | string | — | Rule severity level Determines alert level in WAF logs; empty inherits from OWASP CRS defaults Values: CRITICAL, ERROR, WARNING, NOTICE. |
phase | int | — | Request processing phase 1=request headers, 2=request body, 3=response headers, 4=response body Values: 1, 2, 3, 4. Range: 1–4. Required. |
variable | string | — | Target variable to inspect Valid: ARGS, ARGS_NAMES, REQUEST_URI, REQUEST_HEADERS, REQUEST_BODY, REQUEST_COOKIES, RESPONSE_HEADERS, RESPONSE_BODY, REMOTE_ADDR, REQUEST_METHOD, REQUEST_FILENAME, FILES, FILES_NAMES Required. |
operator | string | — | Match operator type Valid: rx (regex), eq (equals), contains, beginsWith, endsWith, within, pm (phrase match), ge/gt/le/lt (numeric), streq (string equals), validateByteRange, validateUrlEncoding, validateUtf8Encoding Required. |
pattern | string | — | Pattern to match against the variable For rx operator, uses regex syntax; validated for ReDoS safety |
transform | []string | — | Transformations to apply before matching Valid: lowercase, uppercase, removeWhitespace, compressWhitespace, removeNulls, urlDecode, urlDecodeUni, htmlEntityDecode, jsDecode, cssDecode, base64Decode, hexDecode, length, normalizePath, trim, none |
action | string | pass | Action to take when rule matches deny=block with status code, pass=log only, drop=silent close, allow=skip remaining rules Values: deny, allow, pass, drop, redirect. |
status | int | 403 | HTTP status code for deny action Range: 100–599. Requires action=deny. |
message | string | none | Log message recorded when rule matches Recorded in WAF logs when rule matches; useful for identifying custom rules |
tags | []string | none | Tags for rule categorization and filtering Used for bulk rule management via disabled_tags |
SPIFFE
TOML: [spiffe] · Env: HEXON_SPIFFE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable SPIFFE workload identity service Serves a separate ACME directory for workload certificate issuance |
default_ttl | duration | 24h | Default certificate TTL for workloads Short-lived certificates are preferred for zero-trust Min: 1m. Requires enabled=true. |
max_ttl | duration | 168h | Maximum certificate TTL Overrides per-workload TTL if exceeded; must be >= default_ttl Min: 1m. Requires enabled=true. |
order_timeout | duration | 1h | ACME order expiration timeout Orders not finalized within this duration are automatically expired Min: 1s. Requires enabled=true. |
path_prefix | string | /acme/spiffe | ACME path prefix for SPIFFE directory Directory served at https://<hostname><path_prefix>/directory Requires enabled=true. |
allowed_cidrs | []string | — | Global allowed CIDRs for SPIFFE ACME endpoints Per-workload allowed_cidrs further restricts via intersection Requires enabled=true. |
rate_limit_per_workload | int | 100 | Rate limit per workload in certificates per hour Prevents a compromised workload from exhausting CA resources Range: 0–10000. Requires enabled=true. |
allowed_key_algorithms | []string | EC-P256,EC-P384,RSA-2048,RSA-3072,RSA-4096 | Allowed key algorithms for account and CSR keys Values: EC-P256, EC-P384, RSA-2048, RSA-3072, RSA-4096. Requires enabled=true. |
Workload identity definitions
TOML: [spiffe.workloads] · Env: HEXON_SPIFFE_WORKLOADS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
identity | string | — | Workload identity name Becomes SPIFFE path /workload/<identity>; lowercase alphanumeric with hyphens, 2-63 chars Required. |
account_public_key | string | — | Account public key in PEM format PEM-encoded public key; workload holds private key in K8s Secret (never in Git) Required. |
sans | []string | — | Allowed DNS SANs for this workload’s certificates Empty means client-authentication-only certificate |
allowed_peers | []string | — | Allowed peer workload identities for mTLS Embedded in AllowedPeers OID extension; empty list means no peer mTLS allowed |
ttl | duration | — | Certificate TTL override for this workload Falls back to spiffe.default_ttl if not set; cannot exceed spiffe.max_ttl Min: 1m. |
allowed_cidrs | []string | — | Per-workload CIDR restriction Intersected with global allowed_cidrs; both must allow |
MCP
TOML: [mcp] · Env: HEXON_MCP_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable the MCP server endpoint Exposes admin CLI commands as tools for AI assistants. For OAuth-based MCP clients, also enable DCR in [authentication.oidc] |
path | string | /_hexon/mcp | URL path where the MCP endpoint is mounted Requires enabled=true. |
read_only | bool | true | Read-only mode blocks mutation subcommands When false, write operations still require two-phase confirmation code. When true, revoke/disconnect/reset/uneject are blocked Requires enabled=true. |
allowed_groups | []string | — | Groups allowed to use the MCP server MCP will not start if this is empty Requires enabled=true. Required. |
allowed_cidrs | []string | — | Allowed CIDR ranges for MCP access If empty, no IP restrictions apply Requires enabled=true. |
stateless | bool (optional) | true | Disable in-memory session tracking for stateless operation When false, enables SSE-based stateful sessions. When true (default), uses stateless HTTP polling Requires enabled=true. |
Named workflow playbooks exposed as MCP prompts
TOML: [mcp.playbooks] · Env: HEXON_MCP_PLAYBOOKS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique playbook name (lowercase alphanumeric + hyphens) Required. |
title | string | — | Display title for this playbook |
description | string | — | Short description of the playbook’s purpose |
category | string | — | Category for organizing playbooks Values: troubleshooting, deployment, maintenance, audit, security. |
steps | string | — | Markdown workflow steps the AI follows Plain markdown; reference arguments by name and the AI will substitute values Required. |
Named input arguments for this playbook
TOML: [mcp.playbooks.arguments] · Env: HEXON_MCP_PLAYBOOKS_ARGUMENTS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Argument name Required. |
description | string | — | Description shown to the user |
required | bool | false | Whether this argument must be provided |
LLM Assistant
TOML: [llm] · Env: HEXON_LLM_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable the LLM module for AI-powered admin interaction |
api_url | string | — | LLM provider API endpoint URL Requires enabled=true. Required. |
model | string | — | Model identifier to use for completions Check provider docs for current model IDs. Anthropic: claude-opus-4-6, claude-sonnet-4-5-20250929 Requires enabled=true. Required. |
provider | string | auto | API provider type; auto-detected from api_url when set to auto Values: auto, openai, anthropic, azure, ollama, gemini. Requires enabled=true. |
temperature | float | 0.3 | Sampling temperature for response generation Range: 0–2. Requires enabled=true. |
max_tokens | int | 4096 | Maximum tokens in LLM response Range: 256–32768. Requires enabled=true. |
timeout | duration | 60s | Maximum time to wait for an LLM API response Requires enabled=true. |
rate_limit | rate_limit | 10/1m | Per-user query rate limit Requires enabled=true. |
auto_execute_readonly | bool (optional) | true | Execute read-only commands without operator confirmation Requires enabled=true. |
allowed_commands | []string | none | Commands the LLM can execute; empty allows all MCP-visible commands Empty allows all MCP-visible commands Requires enabled=true. |
approval_required | []string | none | Commands that always require operator confirmation before execution Empty means only write operations require approval Requires enabled=true. |
approval_timeout | duration | 60s | Max time to wait for operator approval of write operations Requires enabled=true. |
max_write_ops_per_query | int | 3 | Max write operations requiring approval per AI query Range: 1–20. Requires enabled=true. |
max_tool_rounds | int | 15 | Max tool-calling rounds per AI query Range: 1–50. Requires enabled=true. |
required_groups | []string | — | Groups allowed to use LLM features LLM will not start if this is empty Requires enabled=true. Required. |
redact_sensitive | bool (optional) | true | Redact secrets and sensitive data from LLM context Requires enabled=true. |
max_history | int | 25 | Maximum conversation exchanges to retain per session for context continuity Range: 0–100. Requires enabled=true. |
custom_instructions | string | — | Custom persona and behavioral instructions for the AI assistant Empty uses built-in SRE persona. Supports multi-line TOML strings. Requires enabled=true. |
max_context_entries | int | 10 | Maximum session context entries per operator Range: 1–50. Requires enabled=true. |
max_context_length | int | 500 | Maximum character length per session context entry Range: 50–2000. Requires enabled=true. |
max_memory_entries | int | 50 | Maximum number of memory entries (insights + rules combined) Range: 0–500. Requires enabled=true. |
max_memory_length | int | 500 | Maximum character length per memory entry Range: 50–2000. Requires enabled=true. |
memory_ttl | duration | 8760h | Time-to-live for memory entries in cluster storage Default 1 year (8760h). Set to 0 for no expiry Requires enabled=true. |
prompt_caching_ttl | duration | — | Anthropic prompt caching TTL; empty=disabled, 5m=default, 1h=extended (2x write cost) Only applies to Anthropic provider. 5m is recommended. Requires enabled=true. |
token_tracking_weeks | int | 18 | Weeks of per-user token consumption history to retain; 0 disables tracking Range: 0–104. Requires enabled=true. |
ai_disclaimer | string | — | Disclaimer shown once per session when entering AI mode Empty uses default. Set to a single space to disable. Requires enabled=true. |
max_sleep_duration | duration | 5m | Max duration per sleep call in monitoring loops Requires enabled=true. |
max_sleeps_per_query | int | 60 | Max sleep iterations per AI query for monitoring loops Range: 1–500. Requires enabled=true. |
Log Intelligence
TOML: [log_intelligence] · Env: HEXON_LOGINTELLIGENCE_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | — | Enable log pattern analysis and anomaly detection |
window | duration | 60s | Analysis window size Sliding window for pattern frequency analysis Range: 10s–1h. Requires enabled=true. |
max_patterns | int | 1000 | Maximum unique patterns to track Memory-bound; higher values detect more unique log patterns Range: 100–10000. Requires enabled=true. |
anomaly_buffer_size | int | 100 | Maximum anomalies to retain Circular buffer; oldest anomalies evicted when full Range: 10–1000. Requires enabled=true. |
co_occurrence_window | duration | 5s | Co-occurrence proximity window Patterns occurring within this window are tracked as correlated Range: 1s–60s. Requires enabled=true. |
trace_max_age | duration | 5m | Maximum trace tracking age Traces older than this are evicted from tracking Range: 30s–1h. Requires enabled=true. |
trace_max_entries | int | 5000 | Maximum concurrent traces to track Memory-bound; limits concurrent trace correlation tracking Range: 100–50000. Requires enabled=true. |
RADIUS
TOML: [radius] · Env: HEXON_RADIUS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable RADIUS authentication service |
radsec_only | bool (optional) | true | RADSEC-only mode (TCP+TLS). When false, also accepts plain UDP RADIUS Requires enabled=true. |
network_interface | string | — | Network interface to bind RADIUS listeners to Defaults to service.network_interface if not set Requires enabled=true. |
radsec_port | int | 2083 | RADSEC TCP+TLS listener port (RFC 6614) Range: 1–65535. Requires enabled=true. |
plain_port | int | 1812 | Plain UDP RADIUS listener port (RFC 2865, only when radsec_only=false) Ignored when radsec_only=true Range: 1–65535. Requires enabled=true. |
accounting_port | int | 2083 | Accounting port (reserved for future) Range: 1–65535. Requires enabled=true. |
auth_methods | []string | — | Authentication methods evaluated in order x509 validates RADSEC peer certificate via authentication.x509 module. password uses LDAP bind. Values: x509, password. Requires enabled=true. |
ca_pem | string | — | External CA certificates for x509 client validation Requires enabled=true. |
idle_timeout | duration | 30s | RADSEC connection idle timeout Requires enabled=true. |
session_ttl | duration | 1h | How long RADIUS auth events are visible in session list Range: 1m-24h. Stateless protocol — sessions represent authorization events. Requires enabled=true. |
tls_min_version | string | 1.2 | Minimum TLS version for RADSEC connections 1.2 recommended, 1.1 only for legacy NAS devices Values: 1.1, 1.2, 1.3. Requires enabled=true. |
tls_cert | string | — | Server TLS certificate (file path or inline PEM) Requires enabled=true. |
auto_tls | bool | false | Issue TLS cert from internal ACME CA Requires enabled=true. |
geo_enabled | bool | — | Enable geo-IP restrictions for RADIUS Overrides [service] geo settings when set Requires enabled=true. |
geo_allow_countries | []string | — | ISO 3166-1 alpha-2 country codes to allow Requires geo_enabled=true. |
geo_deny_countries | []string | — | Country codes to deny (takes precedence over allow) Requires geo_enabled=true. |
geo_allow_asn | []string | — | ASN numbers to allow Requires geo_enabled=true. |
geo_deny_asn | []string | — | ASN numbers to deny Requires geo_enabled=true. |
geo_bypass_cidr | []string | — | CIDRs that bypass geo-IP checks Requires geo_enabled=true. |
time_enabled | bool | — | Enable time-based access restrictions for RADIUS Overrides [service] time settings when set Requires enabled=true. |
time_timezone | string | — | Default timezone for time-based restrictions IANA timezone format Requires time_enabled=true. |
time_allow_days | []string | — | Allowed days of the week Requires time_enabled=true. |
time_deny_days | []string | — | Denied days of the week (takes precedence over allow) Requires time_enabled=true. |
time_allow_hours | string | — | Allowed hours range in 24h format Requires time_enabled=true. |
time_deny_hours | string | — | Denied hours range (takes precedence over allow) Requires time_enabled=true. |
time_bypass_cidr | []string | — | CIDRs that bypass time-based restrictions Requires time_enabled=true. |
time_deny_message | string | — | Custom deny message for time restrictions Requires time_enabled=true. |
Per-country or per-CIDR time access windows
TOML: [radius.time_windows] · Env: HEXON_RADIUS_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Multi-factor authentication (Access-Challenge or append mode)
TOML: [radius.mfa] · Env: HEXON_RADIUS_MFA_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable MFA for RADIUS password authentication |
mode | string | challenge | MFA mode ‘challenge’ uses Access-Challenge (RFC 2865). ‘append’ concatenates password+code. Values: challenge, append. Requires enabled=true. |
methods | []string | totp | MFA methods in priority order ‘totp’ checks enrollment first. ‘otp’ sends email OTP (requires challenge mode). Values: totp, otp. Requires enabled=true. |
separator | string | : | Separator between password and code in append mode Split at last occurrence to handle passwords containing the separator. Requires enabled=true. |
challenge_timeout | duration | 60s | Time allowed for user to respond to Access-Challenge Range: 10s-300s Requires enabled=true. |
required_groups | []string | — | Only require MFA for users in these groups (empty = all users) Requires enabled=true. |
skip_if_unavailable | bool | false | Allow auth without MFA if no method available When false, users without TOTP enrollment are rejected. Requires enabled=true. |
otp_ttl | duration | 5m | Email OTP validity period Range: 1m-10m Requires enabled=true. |
otp_code_length | int | 6 | Email OTP code length Range: 4–8. Requires enabled=true. |
Rate limiting and DoS protection
TOML: [radius.rate_limit] · Env: HEXON_RADIUS_RATE_LIMIT_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
max_requests_per_second_per_nas | int | 100 | Per-NAS request rate limit Range: 1–100000. |
max_auth_attempts_per_user | int | 5 | Failed attempts before lockout Range: 1–100. |
auth_lockout_duration | duration | 5m | Lockout period after max failures |
max_concurrent_authentications | int | 1000 | Global concurrent auth limit Range: 1–100000. |
NAS (Network Access Server) client definitions
TOML: [radius.client] · Env: HEXON_RADIUS_CLIENT_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Unique client identifier Required. |
description | string | — | Optional description for audit logs |
cidr | string | — | IP range of the NAS (defaults to 0.0.0.0/0 if empty) |
mfa_override | string | — | Override MFA mode for this client Empty inherits global [radius.mfa]. ‘off’ disables MFA for this client. Values: “, off, challenge, append. |
geo_enabled | bool (optional) | — | Override geo-IP restriction for this client nil=inherit, false=disable, true=use client settings |
geo_allow_countries | []string | — | Override allowed countries for this client |
geo_deny_countries | []string | — | Override denied countries for this client |
geo_allow_asn | []string | — | Override allowed ASNs for this client |
geo_deny_asn | []string | — | Override denied ASNs for this client |
geo_bypass_cidr | []string | — | Override bypass CIDRs for this client |
time_enabled | bool (optional) | — | Override time restriction for this client nil=inherit, false=disable, true=use client settings |
time_timezone | string | — | Override timezone for this client |
time_allow_days | []string | — | Override allowed days for this client |
time_deny_days | []string | — | Override denied days for this client |
time_allow_hours | string | — | Override allowed hours for this client |
time_deny_hours | string | — | Override denied hours for this client |
time_bypass_cidr | []string | — | Override bypass CIDRs for this client |
time_deny_message | string | — | Override deny message for this client |
tls_cert | string | — | Server cert override for this NAS (file path or inline PEM) |
client_ca_pem | string | — | CA to verify this NAS device’s client certificate (mTLS) |
Override time windows for this client
TOML: [radius.client.time_windows] · Env: HEXON_RADIUS_CLIENT_TIME_WINDOWS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
countries | []string | — | ISO 3166-1 alpha-2 country codes for this time window |
cidr | []string | — | IP ranges for this time window Takes precedence over country matching |
timezone | string | — | IANA timezone for this time window |
allow_days | []string | — | Allowed days of the week Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
deny_days | []string | — | Denied days of the week Deny takes precedence over allow Values: Mon, Tue, Wed, Thu, Fri, Sat, Sun. |
allow_hours | string | — | Allowed hours range in 24h format Format: HH:MM-HH:MM |
deny_hours | string | — | Denied hours range in 24h format Deny takes precedence over allow; format: HH:MM-HH:MM |
Group-based authorization mappings
TOML: [radius.mapping] · Env: HEXON_RADIUS_MAPPING_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
name | string | — | Display name for logging/metrics Required. |
groups | []string | — | Required groups (ANY match, empty = catch-all) |
priority | int | 0 | Evaluation order (higher = first) |
Client Access
TOML: [client_access] · Env: HEXON_CLIENTACCESS_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Enable QUIC client access listener for transparent L3 network access |
hostname | string | — | Hostname for client access listener Use when running behind a CDN; defaults to service hostname Requires enabled=true. |
port | int | — | Dedicated QUIC port for client access connections Must differ from service.port, forward_proxy.port, and connector.port Range: 1–65535. Requires enabled=true. Required. |
network_interface | string | — | Network interface to bind client access listener Defaults to service.network_interface if not set Requires enabled=true. |
cert | string | — | TLS certificate for client access hostname File path or inline PEM; falls back to service certificate if not set Requires enabled=true. |
subnet | string | 100.64.208.0/22 | Virtual IP pool subnet for client access CGN space; separate from IKEv2 VPN subnet to avoid conflicts Requires enabled=true. |
gateway_ip | string | 100.64.208.1 | Gateway virtual IP within the subnet Requires enabled=true. |
dns_upstream | []string | — | Internal DNS servers for split DNS resolution Requires enabled=true. |
dns_domains | []string | — | Split DNS domains pushed to clients Requires enabled=true. |
cidrs | []string | — | Additional CIDR routes pushed to all clients Merged with per-user routes from firewall rules; use when firewall aliases only have hostname wildcards Requires enabled=true. |
heartbeat_interval | duration | 30s | Heartbeat interval Requires enabled=true. |
token_refresh_interval | duration | 45m | Token refresh interval Requires enabled=true. |
max_idle_timeout | duration | 5m | Disconnect after idle period with no streams Requires enabled=true. |
max_clients | int | 1000 | Maximum concurrent client connections 0 means unlimited Min: 0. Requires enabled=true. |
max_streams_per_client | int | 100 | Maximum concurrent streams per client Min: 1. Requires enabled=true. |
required_groups | []string | — | Groups required for client access; empty allows any authenticated user Groups from [identity] directory. User must have ANY of the listed groups Requires enabled=true. |
dns_rate_limit | int | 100 | Maximum DNS queries per second per client Min: 1. Requires enabled=true. |
vip_reservation_ttl | duration | 5m | How long to reserve VIP after disconnect for reconnecting clients Set to 0 to disable; reconnecting clients get the same VIP within this window Requires enabled=true. |
Admin
TOML: [admin] · Env: HEXON_ADMIN_<KEY>
| Key | Type | Default | Description |
|---|---|---|---|
audit_trail | bool (optional) | true | Enable command audit trail Records all admin CLI commands cluster-wide for operational visibility |
audit_ttl | duration | 24h | Audit entry retention duration |
audit_max_entries | int | 10000 | Maximum audit entries to retain (0 = TTL-only) Min: 0. |