Skip to content

Tarsus Configuration

Configure the Tarsus client agent.

TARSUS_CONFIG names the config file outright: when it is set, that file is the only one read, and Tarsus fails to start if it is missing.

Otherwise Tarsus layers whichever of these exist, each overriding the one before:

  1. tarsus.toml in the current directory
  2. ~/.config/mantis/tarsus.toml (platform-dependent config directory)
  3. /etc/mantis/tarsus.toml

These are layers, not a first-match search: a key set in /etc/mantis/tarsus.toml wins over the same key in the user config directory or the current directory, so a file an unprivileged user can write cannot change what the deployed service does. If no file is found, defaults are used.

Environment variables are applied on top of the file. Every setting is reachable that way — the key is TARSUS__ followed by the section and field names in upper case, joined by double underscores (TARSUS__POLL__INTERVAL_SECS for [poll] interval_secs) — so the table below is the common subset, not the limit. Any TARSUS__* key that is not a setting is a hard startup error, not a silent override. Two further limits apply — the [security] section can never be set from the environment, and when minimum_transport_level = "wireguard" the WireGuard floor is checked after env vars, so TARSUS__TRANSPORT__ENABLED=false (or enabled = false in the file) makes Tarsus refuse to start rather than run below the mandated level.

name = "web-server-01"
mode = "listen"
data_dir = "/var/lib/tarsus"
log_level = "info"
FieldTypeDefaultRequiredDescription
namestringhostnameNoClient name for registration. Env: TARSUS__NAME
modestring"listen"NoOperating mode: listen (server connects to client) or poll (client polls server). Env: TARSUS__MODE
data_dirstringplatform data dir + /tarsusNoData directory for certificates and state. Env: TARSUS__DATA_DIR
log_levelstring"info"NoLog level: trace, debug, info, warn, error. Env: TARSUS__LOG_LEVEL

TLS configuration. TLS is always enabled and cannot be disabled.

[tls]
cert_path = "/etc/mantis/certs/client.crt"
key_path = "/etc/mantis/certs/client.key"
ca_cert_path = "/etc/mantis/certs/ca.crt"
server_name = "thorax.example.com"
FieldTypeDefaultRequiredDescription
cert_pathstring-NoClient certificate PEM file. If not set, auto-generated. Env: MANTIS_TLS_CERT_PATH
key_pathstring-NoClient private key PEM file. Must be set with cert_path. Env: MANTIS_TLS_KEY_PATH
ca_cert_pathstring-YesCA certificate for server verification. Env: MANTIS_TLS_CA_CERT_PATH
enrollment_addressstring-ConditionalThe assigned Thorax’s CSR-enrollment address as host:port. Required when a registration token is set: nothing derives it, and without it Tarsus warns, skips enrollment and falls back to a self-signed thumbprint-mode certificate. Env: TARSUS__TLS__ENROLLMENT_ADDRESS
server_namestring-NoServer name for SNI validation

Mandible connection settings (registration + heartbeat). Tarsus registers with Mandible’s internal gRPC endpoint; Mandible’s response assigns the Thorax instance responsible for command execution. In poll mode Tarsus then connects outbound to that Thorax to fetch commands; in listen mode (the default) Tarsus exposes a gRPC server and the assigned Thorax connects inbound.

[mandible]
endpoint = "mandible.example.com:50052"
connect_timeout_secs = 30
request_timeout_secs = 360
FieldTypeDefaultRequiredDescription
endpointstring"localhost:50052"NoMandible internal gRPC endpoint for registration (hostname:port) — this is the gRPC server port (50052), not the REST API port (3000). Env: TARSUS__MANDIBLE__ENDPOINT
connect_timeout_secsinteger30NoConnection timeout in seconds
request_timeout_secsinteger360NoRequest timeout in seconds. Must exceed Thorax’s command timeout (300s); default is 300s + 60s buffer.

Listen mode configuration (when mode = "listen").

[listen]
address = "0.0.0.0"
port = 9342
FieldTypeDefaultRequiredDescription
addressstring"0.0.0.0"NoBind address. Env: TARSUS__LISTEN__ADDRESS
portinteger9342NoListen port. Env: TARSUS__LISTEN__PORT

Poll mode configuration (when mode = "poll").

[poll]
interval_secs = 30
max_commands = 10
command_timeout_secs = 3600
FieldTypeDefaultRequiredDescription
interval_secsinteger30NoPolling interval in seconds. Env: TARSUS__POLL__INTERVAL_SECS
max_commandsinteger10NoMaximum commands to fetch per poll
command_timeout_secsinteger3600NoTimeout for a command dispatched without one of its own, when the server sends no configuration

Registration and heartbeat configuration.

[registration]
enabled = true
heartbeat_interval_secs = 30
token = "your-registration-token"
[registration.tags]
role = "web-server"
region = "us-east-1"
[registration.labels]
team = "platform"
FieldTypeDefaultRequiredDescription
enabledbooleantrueNoEnable registration with server
heartbeat_interval_secsinteger30NoHeartbeat interval. Env: TARSUS__REGISTRATION__HEARTBEAT_INTERVAL_SECS
tagsmap{}NoKey-value tags for deployment filtering
labelsmap{}NoCustom metadata labels
tokenstring-NoRegistration token for automated approval (Octopus-style). Env: TARSUS__REGISTRATION__TOKEN

RegistrationConfig is #[serde(deny_unknown_fields)], so those five keys are the whole section — any other key makes the agent fail to parse its config and refuse to start. Registration retries are not configured here: they use the shared [retry] section below (max_retries, initial_delay_ms, max_delay_ms, backoff_multiplier, retry_indefinitely, failure_threshold).

Connection retry configuration.

[retry]
max_retries = 3
initial_delay_ms = 1000
max_delay_ms = 60000
backoff_multiplier = 2.0
retry_indefinitely = true
failure_threshold = 5
FieldTypeDefaultRequiredDescription
max_retriesinteger3NoMax retries before resetting backoff
initial_delay_msinteger1000NoInitial delay before first retry (ms)
max_delay_msinteger60000NoMaximum delay between retries (ms)
backoff_multiplierfloat2.0NoExponential backoff multiplier
retry_indefinitelybooleantrueNoKeep retrying after max_retries (with max_delay). Set false only for testing
failure_thresholdinteger5NoConsecutive failures before opening circuit

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

[console]
enabled = true
address = "127.0.0.1"
port = 6671
retention_secs = 60
publish_interval_ms = 1000
FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoEnable the tokio-console server. false whether or not a config file loads, and whether or not it carries a [console] table: the debug listener is opt-in and needs this set explicitly. Env: TARSUS__CONSOLE__ENABLED
addressstring"127.0.0.1"NoBind address. Env: TARSUS__CONSOLE__ADDRESS
portinteger6671NoConsole port. 6671 with no config file and with a file that omits [console]; the sentinel 0 applies only when the table is present and port alone is omitted. Env: TARSUS__CONSOLE__PORT
retention_secsinteger60NoHow long to retain completed task data. Env: TARSUS__CONSOLE__RETENTION_SECS
publish_interval_msinteger1000NoUpdate interval for connected clients (ms). Env: TARSUS__CONSOLE__PUBLISH_INTERVAL_MS
recording_pathstring-NoPath to record console data for offline analysis. Env: TARSUS__CONSOLE__RECORDING_PATH

WireGuard-based transport configuration for encrypted connectivity. When enabled, Tarsus uses the WireGuard overlay assigned during registration. The relay endpoint (for NAT traversal fallback) is supplied by Mandible at registration time — it is not a config field.

[transport]
enabled = true
private_key_path = "/etc/mantis/wireguard/private.key"
key_rotation_interval_secs = 0
FieldTypeDefaultRequiredDescription
enabledbooleanfalseNoEnable WireGuard transport. Env: TARSUS__TRANSPORT__ENABLED
private_key_pathstring-NoWireGuard private key file. If not set, keys are auto-generated in data_dir. Env: TARSUS__TRANSPORT__PRIVATE_KEY_PATH
key_rotation_interval_secsinteger0NoInterval at which the agent rotates its WireGuard static key over the live overlay. 0 disables periodic rotation. Env: TARSUS__TRANSPORT__KEY_ROTATION_INTERVAL_SECS
relay_expected_identitystring-NoRelay identity to pin — the agent refuses to sign an authentication response for any other. The relay announces the Thorax instance’s name. Unset leaves the relay authenticated by TLS alone. Env: TARSUS__TRANSPORT__RELAY_EXPECTED_IDENTITY

The commands and scripts the agent runs.

[execution]
inherit_env = ["JAVA_HOME", "HTTPS_PROXY"]
FieldTypeDefaultRequiredDescription
inherit_envarray[]NoHost environment variables a command or script inherits besides the base set. Env: TARSUS__EXECUTION__INHERIT_ENV (comma-separated)

A command or script runs with only the base set of this agent’s environment — PATH, HOME, USER, LOGNAME, SHELL, LANG, LANGUAGE, LC_*, TZ, TMPDIR, TERM, and on Windows the system and profile variables a process needs to start — plus the variables the action and deployment define. Name anything else it needs in inherit_env; Mantis’s own variables (MANTIS_*, MANDIBLE__*, THORAX__*, TARSUS__* and DATABASE_URL) are refused there, and the agent does not start. Its process tree is stopped as a whole at a timeout or a cancellation.

Security configuration for protected settings. Settings in this section cannot be overridden by environment variables, preventing configuration injection attacks.

[security]
minimum_transport_level = "wireguard"
FieldTypeDefaultRequiredDescription
minimum_transport_levelstring"none"NoMinimum transport security: none (env override allowed) or wireguard (env override blocked)

Every field in the tables above has an environment key, derived mechanically from its section and name: TARSUS__<SECTION>__<FIELD>, upper case. The keys below are the ones an operator reaches for most often; a field that is not listed here still has one, and the per-section tables give it.

Environment VariableDescription
TARSUS_CONFIGPath to config file (single underscore; not a setting)
TARSUS__NAMEClient name
TARSUS__MODEOperating mode (listen or poll)
TARSUS__LOG_LEVELLog level
TARSUS__DATA_DIRData directory
TARSUS__MANDIBLE__ENDPOINTServer address (hostname:port)
TARSUS__MANDIBLE__CONNECT_TIMEOUT_SECSConnect timeout to Mandible (seconds)
TARSUS__MANDIBLE__REQUEST_TIMEOUT_SECSRequest timeout to Mandible (seconds)
TARSUS__LISTEN__ADDRESSListen bind address
TARSUS__LISTEN__PORTListen port
TARSUS__POLL__INTERVAL_SECSPoll interval (seconds)
TARSUS__POLL__MAX_COMMANDSCommands fetched per poll
TARSUS__REGISTRATION__HEARTBEAT_INTERVAL_SECSHeartbeat interval (seconds)
TARSUS__REGISTRATION__TOKENRegistration token
TARSUS__RETRY__*One key per [retry] field
TARSUS__CONSOLE__ENABLEDEnable the tokio-console endpoint
TARSUS__CONSOLE__ADDRESStokio-console bind address
TARSUS__CONSOLE__PORTtokio-console port
TARSUS__TLS__ENROLLMENT_ADDRESSCSR enrollment address (host:port)
TARSUS__TRANSPORT__ENABLEDEnable WireGuard transport
TARSUS__TRANSPORT__PRIVATE_KEY_PATHWireGuard private key path
TARSUS__TRANSPORT__KEY_ROTATION_INTERVAL_SECSWireGuard key rotation interval (seconds)
TARSUS__TRANSPORT__RELAY_EXPECTED_IDENTITYRelay identity to pin
MANTIS_LOG_LEVELLog level, shared across Mantis services. TARSUS__LOG_LEVEL wins where both are set
MANTIS_TLS_CERT_PATHClient TLS certificate
MANTIS_TLS_KEY_PATHClient TLS private key
MANTIS_TLS_CA_CERT_PATHCA certificate

See Environment Variables for complete reference.

tarsus.toml
name = "web-server-01"
mode = "listen"
log_level = "info"
[tls]
ca_cert_path = "/etc/mantis/certs/ca.crt"
[mandible]
endpoint = "mandible.example.com:50052"
[listen]
address = "0.0.0.0"
port = 9342
[registration]
enabled = true
heartbeat_interval_secs = 30
token = "your-registration-token"
[registration.tags]
role = "web-server"
region = "us-east-1"
[retry]
retry_indefinitely = true
tarsus.toml
name = "db-server-01"
mode = "poll"
log_level = "info"
[tls]
cert_path = "/etc/mantis/certs/client.crt"
key_path = "/etc/mantis/certs/client.key"
ca_cert_path = "/etc/mantis/certs/ca.crt"
[mandible]
endpoint = "mandible.example.com:50052"
[poll]
interval_secs = 15
max_commands = 5
[registration]
enabled = true
[security]
minimum_transport_level = "wireguard"
[transport]
enabled = true