Skip to the content.

Configuration reference

Every runtime knob lives in an env var read by orchestrator/config.py. Nothing is hard-coded. Services refuse to start if any required=True variable is unset.

Canonical source: orchestrator/config.py.

Core

Variable Default Required Purpose
DATABASE_URL Postgres DSN for the orchestrator
CELERY_BROKER_URL redis://localhost:6379/0   Celery broker
CELERY_RESULT_BACKEND redis://localhost:6379/1   Celery results backend
ANALYSIS_NETWORK_CIDR 192.168.100.0/24   Analysis-bridge CIDR (used for IOC classification)
QUARANTINE_ROOT /srv/sandgnat/quarantine   Where dropped files are moved after ingestion
ARTIFACT_STAGING_ROOT /srv/sandgnat/staging   SMB/NFS staging share root
ANALYSIS_DEFAULT_TIMEOUT 300   Detonation timeout in seconds
MAX_CONCURRENT_ANALYSES 4   Upper bound for the Postgres pool sizing

Proxmox

Variable Default Required Purpose
PROXMOX_HOST Proxmox API host
PROXMOX_USER root@pam   API user
PROXMOX_TOKEN_NAME API token name
PROXMOX_TOKEN_VALUE API token value
PROXMOX_VERIFY_SSL true   TLS verification
PROXMOX_NODE Proxmox node to place VMs on
PROXMOX_TEMPLATE_VMID 9000   Windows template vmid
PROXMOX_CLEAN_SNAPSHOT clean   Snapshot name to revert to

Windows VM pool

Variable Default Purpose
VM_POOL_VMID_MIN 9100 First vmid in Windows pool range
VM_POOL_VMID_MAX 9199 Last vmid in Windows pool range
VM_POOL_STALE_LEASE_SECONDS 1800 Reap leases older than this

Linux VM pool (static-analysis stage)

Variable Default Purpose
LINUX_VM_POOL_VMID_MIN 9200 First vmid in Linux pool range
LINUX_VM_POOL_VMID_MAX 9299 Last vmid in Linux pool range
LINUX_TEMPLATE_VMID 9001 Linux template vmid
LINUX_CLEAN_SNAPSHOT clean Linux template snapshot name
LINUX_VM_POOL_STALE_LEASE_SECONDS 600 Reap stale Linux leases

Static analysis

Variable Default Purpose
STATIC_ANALYSIS_ENABLED false Route intake through the static stage first
STATIC_SHORT_CIRCUIT_THRESHOLD 0.85 Jaccard threshold for near-duplicate skip
STATIC_SHORT_CIRCUIT_FLAVOUR either byte / opcode / either
STATIC_ANALYSIS_TIMEOUT 240 Static-stage timeout in seconds
STATIC_YARA_DEEP_RULES_DIR "" Directory of .yar files for the deep scan

Intake HTTP service

Variable Default Required Purpose
INTAKE_API_KEY ✅ (to start service) Shared secret for X-API-Key header
INTAKE_BIND_HOST 127.0.0.1   Flask bind address
INTAKE_BIND_PORT 8080   Flask bind port
INTAKE_MAX_SAMPLE_BYTES 134217728 (128 MiB)   Hard upload-size cap
INTAKE_MIN_SAMPLE_BYTES 16   Reject anything smaller
INTAKE_YARA_RULES_DIR ""   Directory of intake-time YARA rules
VIRUSTOTAL_API_KEY ""   If set, enable VT hash lookup
VIRUSTOTAL_BASE_URL https://www.virustotal.com/api/v3   VT v3 base URL
VIRUSTOTAL_TIMEOUT_SECONDS 10   VT request timeout

Linux guest agent

Set these on the Linux static-analysis guest, not on the orchestrator.

Variable Default Purpose
LINUX_GUEST_STAGING_ROOT /srv/sandgnat/staging Where the SMB share is mounted
LINUX_GUEST_POLL_INTERVAL 2.0 Watcher poll interval, seconds
LINUX_GUEST_CAPA_EXE capa Path to the CAPA binary
LINUX_GUEST_YARA_DEEP_RULES_DIR "" Deep YARA rules on the guest
LINUX_GUEST_MAX_STRINGS_BYTES 1048576 Cap on strings kept in envelope

Windows guest agent (anti-analysis mitigations)

Set these on the Windows detonation guest. All are opt-out — defaults match the hardened template produced by the Phase A–C template-bake runbook. Env vars take precedence over the defaults in guest_agent/config.py, so non-hardened dev VMs can disable individual mitigations without rebuilding the frozen agent.

Paths (Phase C)

Variable Default Purpose
SANDGNAT_DECOY_USER %USERNAME% Username whose AppData holds the workspace
SANDGNAT_WORK_ROOT C:\Users\<decoy>\AppData\Local\Microsoft\PowerManagement Per-job workspace root on the guest
SANDGNAT_STAGING_ROOT \\192.168.100.1\analysis UNC path to the orchestrator staging share (no drive letter)
SANDGNAT_PROCMON C:\Windows\System32\SystemAudit.exe Renamed ProcMon binary

Activity simulator (Phase D)

Set SANDGNAT_ACTIVITY_ENABLED=0 to disable the entire simulator; the individual toggles only apply when the master switch is on.

Variable Default Purpose
SANDGNAT_ACTIVITY_ENABLED 1 Master on/off for the four simulator threads
SANDGNAT_ACTIVITY_WARMUP 30 Seconds to wait after sample launch before activity fires
SANDGNAT_ACTIVITY_MOUSE_JIGGLE 1 Enable the mouse-jiggle loop
SANDGNAT_MOUSE_JIGGLE_MIN 20 Min interval between jiggles (seconds)
SANDGNAT_MOUSE_JIGGLE_MAX 60 Max interval between jiggles (seconds)
SANDGNAT_ACTIVITY_CURSOR_TOUR 1 Enable the cursor-tour loop
SANDGNAT_CURSOR_TOUR_MIN 180 Min interval between tours (seconds)
SANDGNAT_CURSOR_TOUR_MAX 420 Max interval between tours (seconds)
SANDGNAT_ACTIVITY_KEYBOARD_NOISE 1 Enable the hidden-Notepad typing loop
SANDGNAT_KEYBOARD_NOISE_MIN 240 Min interval (seconds)
SANDGNAT_KEYBOARD_NOISE_MAX 600 Max interval (seconds)
SANDGNAT_ACTIVITY_WINDOW_DANCE 1 Enable the open/close app loop
SANDGNAT_WINDOW_DANCE_MIN 120 Min interval (seconds)
SANDGNAT_WINDOW_DANCE_MAX 300 Max interval (seconds)

Sleep patcher (Phase E)

Variable Default Purpose
SANDGNAT_SLEEP_PATCHER_DLL <agent_dir>/sleep_patcher.dll Absolute path to sleep_patcher.dll; falls back to the agent directory
SANDGNAT_SLEEP_PATCH_LOG <workspace>/sleep_patches.jsonl Set automatically by the runner per-job; DLL writes here

If the DLL is missing the runner continues without injection (Phase G still catches the import pattern). Off-Windows the injector refuses cleanly; tests can force the Windows code path with SANDGNAT_FAKE_WIN32=1.

Security posture

Examples

Minimal orchestrator .env

DATABASE_URL=postgresql://sandgnat:***@pg.internal:5432/sandgnat
CELERY_BROKER_URL=redis://redis.internal:6379/0
PROXMOX_HOST=proxmox.internal
PROXMOX_TOKEN_NAME=sandgnat
PROXMOX_TOKEN_VALUE=***
PROXMOX_NODE=pve1

INTAKE_API_KEY=some-long-opaque-string
QUARANTINE_ROOT=/srv/sandgnat/quarantine
ARTIFACT_STAGING_ROOT=/srv/sandgnat/staging

Enable the static pre-stage

STATIC_ANALYSIS_ENABLED=1
STATIC_SHORT_CIRCUIT_THRESHOLD=0.85
STATIC_YARA_DEEP_RULES_DIR=/etc/sandgnat/yara-deep
LINUX_TEMPLATE_VMID=9001

Enable VT pre-check

VIRUSTOTAL_API_KEY=xxxxxxxx...

Dev / local stack

DATABASE_URL=postgresql://postgres:postgres@localhost:5432/sandgnat
CELERY_BROKER_URL=redis://localhost:6379/0
INTAKE_API_KEY=dev-key-not-for-production
QUARANTINE_ROOT=/tmp/sandgnat/quarantine
ARTIFACT_STAGING_ROOT=/tmp/sandgnat/staging
# Proxmox vars still required to import the module; use placeholders:
PROXMOX_HOST=localhost
PROXMOX_TOKEN_NAME=dev
PROXMOX_TOKEN_VALUE=dev
PROXMOX_NODE=dev

See tutorials/02-local-dev-stack.md for the full dev setup.