# ============================================================================= # Secrets & Security (AUTO-GENERATED — normally you do NOT set these) # ============================================================================= # `./redamon.sh install|up|update` generates strong random values for all of the # secrets below into your real `.env` on a FRESH install, so a default deployment # is secure out of the box. You only need to set one here to OVERRIDE the # generated value (e.g. to share a password with an external tool). # # IMPORTANT: POSTGRES_PASSWORD / NEO4J_PASSWORD are baked into the postgres/neo4j # data volumes at first init. Changing them AFTER the volumes exist will lock you # out of the running database — redamon.sh detects this and warns instead of # rewriting. Rotate deliberately (ALTER USER / neo4j changePassword) or destroy # the volume for a clean re-init. # # AUTH_SECRET # webapp JWT signing key (openssl rand -hex 32) # INTERNAL_API_KEY # webapp <-> agent/service auth (master internal key) # SCANNER_API_KEY # S3/E6: scoped token injected into scan containers # # INSTEAD of INTERNAL_API_KEY. Accepted only on # # GET /api/users/[id]/settings + GET /api/projects/[id] # # + agent /llm/*; cannot mint admins or read # # llm-providers. Auto-generated by install/update. # ORCHESTRATOR_API_KEY # webapp <-> recon-orchestrator (X-Orchestrator-Key) # POSTGRES_PASSWORD # PostgreSQL password (required; the DB refuses to start if unset (run redamon.sh)) # NEO4J_PASSWORD # Neo4j password (required; the DB refuses to start if unset (run redamon.sh)) # MCP_AUTH_TOKEN # bearer token the agent presents to the Kali MCP # # servers; the servers validate it on every SSE request. # # If left empty the MCP servers FAIL OPEN (dev only) — # # host ports are loopback-only, so this is still gated. # # Host-port exposure: the MCP servers (8000-8005), progress (8013/8014), tunnel # (8015), ngrok (4040) and the datastores (5432/7474/7687) are all published on # 127.0.0.1 only. Only the webapp (3000), agent (8090) and reverse-shell catcher # (4444) are reachable off-host. See internal/security/README.TM.STRIDE.md. # # Three of those host-side publishes can be relocated when the default is # already taken on a shared host: # MSF_PROGRESS_HOST_PORT # default 8013 # HYDRA_PROGRESS_HOST_PORT # default 8014 # NGROK_API_HOST_PORT # default 4040 # They move the HOST side only; the container keeps its own port. Hence # *_HOST_PORT rather than the MSF_PROGRESS_PORT / HYDRA_PROGRESS_PORT the MCP # servers read to decide what to bind -- same number today, different jobs. # The reverse-shell catcher (4444) is deliberately not relocatable this way; # docker-compose.yml says why. # ============================================================================= # Knowledge Base Embedding Configuration # ============================================================================= # Controls how the KB generates vector embeddings for ingestion and query. # When KB_EMBEDDING_USE_API is false (default), the local sentence-transformers # model runs on CPU/GPU inside the agent container. # # IMPORTANT: Ingestion and query MUST use the same embedding model. # Switching models requires a full KB rebuild: # make -C knowledge_base kb-rebuild-lite MODE=docker # Use an external API for KB embedding (ingestion + query) KB_EMBEDDING_USE_API=false # API base URL (only used when KB_EMBEDDING_USE_API=true) # Uses the OpenAI SDK, which works with any OpenAI-compatible API. # Examples: # OpenAI: https://api.openai.com/v1 (default if left empty) # Ollama: http://host.docker.internal:11434/v1 # LiteLLM: http://host.docker.internal:4000/v1 # Together AI: https://api.together.xyz/v1 # Azure: https://.openai.azure.com/openai/deployments/ # vLLM: http://host.docker.internal:8000/v1 # Fireworks: https://api.fireworks.ai/inference/v1 KB_EMBEDDING_API_BASE_URL= # API key (only used when KB_EMBEDDING_USE_API=true) KB_EMBEDDING_API_KEY= # API model name (only used when KB_EMBEDDING_USE_API=true) # OpenAI: text-embedding-3-small (1536 dim), text-embedding-3-large (3072 dim) # Ollama: nomic-embed-text, mxbai-embed-large, all-minilm # Together AI: togethercomputer/m2-bert-80M-8k-retrieval KB_EMBEDDING_API_MODEL=text-embedding-3-small # ============================================================================= # NVD API Key (optional, speeds up NVD ingestion 10x) # Get a free key: https://nvd.nist.gov/developers/request-an-api-key # ============================================================================= NVD_API_KEY= # ============================================================================= # Memory Governor (RAM-aware dual-cap) — ALL OPTIONAL # ============================================================================= # RedAmon caps every RAM-heavy operation with two limits at once: the value you # configure (the HARD CEILING) and a DYNAMIC cap derived from the RAM actually # available at runtime. The effective value is always the smaller of the two, so # it only ever throttles DOWN under memory pressure, never above your ceiling. # # Leave every variable below EMPTY to use the built-in default (shown in # parentheses). Set a value only to override. Memory sizes accept Docker-style # suffixes: 512m, 2g, etc. Byte figures for on-demand units are normally MEASURED # by the calibration step (resource_profile.json), not hand-set. # --- Master switch --------------------------------------------------------- # Turn the whole memory governor on/off (default: on). When off, behavior is the # legacy static-limits-only mode. REDAMON_MEM_GOVERNOR= # --- Ratio model (for in-process concurrency: threads, -c/-t, pool widths) -- # Available-RAM ratio (available/total) at/above which parallelism runs at the # full configured ceiling (default: 0.50). MEM_SCALE_HIGH= # Available-RAM ratio at/below which parallelism is throttled to the floor # (default: 0.15). MEM_SCALE_LOW= # Floor scale factor: parallelism never drops below this fraction of the ceiling # (default: 0.15). MEM_SCALE_FLOOR= # Seconds to cache the /proc/meminfo read so a wide fan-out doesn't hammer it # (default: 2). MEM_READ_TTL_S= # --- Byte-budget model (for anything that costs real megabytes) ------------ # Safety margin added on top of EVERY measured memory figure before it is used # (default: 0.25, i.e. +25% over the measured peak). MEM_SAFETY_TOLERANCE= # Share of currently-available RAM a single memory-sink list or a single # on-demand unit may claim (default: 0.10 = 10%). MEM_BUDGET_FRACTION= # Path to the calibration output holding measured bytes-per-unit and per-process # envelope figures (default: resource_profile.json). Regenerate when tool # versions change materially. It is merged OVER resource_profile.default.json # (git-tracked, sane per-scan-type defaults), which is merged over the built-in # fallbacks, so leaving both alone is safe. RESOURCE_PROFILE_PATH= # Path to the git-tracked shipped profile that sits under the measured one # (default: resource_profile.default.json, next to the governor module). RESOURCE_PROFILE_DEFAULT_PATH= # --- Simultaneous recon scans (admission reservation ledger) --------------- # RAM reserved for the OS/kernel, never handed to work (default: 2g). OS_HEADROOM_MEM= # Total RAM the always-on core services are expected to use; subtracted from the # scan pool (default: measured, from resource_profile.json). SERVICE_BASELINE_MEM= # Expected peak RAM of one recon job (container + its sibling tools), the unit # the scan pool is divided into. Default is PER SCAN TYPE (full recon 2g, partial # recon 768m, gvm 2.5g, ai-attack 1g, github/trufflehog 768m); setting this # applies one figure to every type instead. Lower it if a small host reports # "not enough free memory to start this scan". RECON_JOB_ENVELOPE_MEM= # Hard ceiling on globally-concurrent recon scans across ALL projects # (default: computed = scan_pool / RECON_JOB_ENVELOPE_MEM). RECON_MAX_CONCURRENT_GLOBAL= # --- Agent sessions / jobs ------------------------------------------------- # Max concurrent agent chat / WebSocket sessions # (default: computed = available RAM x MEM_BUDGET_FRACTION / session envelope). MAX_AGENT_SESSIONS= # Max concurrent background agent jobs # (default: computed from available RAM / background-job envelope). MAX_BACKGROUND_JOBS= # --- Per-container hard caps: on-demand scan containers --------------------- # These are computed at SPAWN from the (RAM-scaled) parameters the container # will run with, then clamped to PER_CONTAINER_MAX. Set one to force a fixed # ceiling for that scan type instead (default: spawn-time envelope x headroom). RECON_CONTAINER_MEM= AI_ATTACK_MEM= GVM_SCAN_MEM= GITHUB_HUNT_MEM= TRUFFLEHOG_MEM= # --- Neo4j query ceiling --------------------------------------------------- # Milliseconds a single Cypher query may run before the driver aborts it # (default 120000). The driver's connection timeouts only bound ACQUIRING a # connection; without this, a whole-graph read on a very large project leaves the # HTTP request pending forever and pins a pooled connection. Raise it if you # legitimately run long analytical queries. NEO4J_QUERY_TIMEOUT_MS= # --- Always-on service memory: the proportional allocator ------------------- # redamon.sh sizes EVERY always-on service from the host's RAM and writes the # result into a managed block at the bottom of your .env, so the values apply # however the stack is started (including a bare `docker compose up`). Do not # set the per-service sizes here: they are computed. Tune the SHARES instead. # # os_reserve = MemTotal x OS_RESERVE_PCT # usable = MemTotal - os_reserve # services = usable x SERVICES_PCT <- split between services by weight # scan_pool = usable - services <- what scan admission may hand out # # Percentage of RAM held back for the kernel/OS (default 8). OS_RESERVE_PCT= # Percentage of the remainder given to the always-on services; the rest becomes # the scan pool (default 65). SERVICES_PCT= # Over-commit multiplier for ceiling-type services. This is a REQUEST, not a # guarantee: it is clamped so that os_reserve + reserved + the sum of all burst # ceilings can never exceed RAM + swap, at any host size or profile combination. A mem_limit is a ceiling, # not a reservation, so unused headroom is free and one busy service may use # what the others are not. Neo4j and Postgres are EXCLUDED (they really allocate # their share). Default 1.75, or 2.5 when swap/zram is active, since a # simultaneous peak then pages instead of OOM-killing. BURST_FACTOR= # How much swap must exist, as a percentage of RAM, before BURST_FACTOR is # auto-raised to 2.5 (default 25). Burst 2.5 over-commits by ~21% of RAM, so a # token 64MB zram device must not unlock it. Ignored if BURST_FACTOR is set. BURST_SWAP_MIN_PCT= # No single service may exceed this percentage of host RAM (default 55), so a # runaway cannot starve the databases. BLAST_PCT= # Per-service share overrides, in per-mille of the services pool. Defaults: # NEO4J 320 AGENT 180 WEBAPP 180 KALI 100 POSTGRES 80 # RECON_ORCHESTRATOR 60 CAPTURE_PROXY 40 DOCKER_BROKER 20 TRAFFIC_INGEST 20 # gvm profile: GVMD 120 GVM_OSPD 110 GVM_REDIS 90 GVM_POSTGRES 50 # GVM_DATA 40 (one share split across the 8 one-shot feed loaders) # kb profile: KB_REFRESH 150 # The sum is renormalised, so enabling a profile shrinks the others instead of # over-committing. # e.g. REDAMON_WEIGHT_WEBAPP=260 to give the graph page a bigger share. REDAMON_WEIGHT_WEBAPP= REDAMON_WEIGHT_NEO4J= REDAMON_WEIGHT_AGENT= # # To PIN one service to a fixed size, set it anywhere outside the managed block # (here is fine). The allocator then leaves it alone and omits it from the block, # so there is never a competing assignment: NEO4J_HEAP= NEO4J_PAGECACHE= GVMD_MEM= # One cap shared by the 8 one-shot GVM feed loaders. They `cp -r` a multi-GB # Greenbone feed, so anything under ~128m is OOM-killed mid-copy; redamon.sh # floors the computed value at 512m. Pin it higher on a slow disk. GVM_DATA_MEM= AGENT_MEM= RECON_ORCHESTRATOR_MEM= WEBAPP_MEM= POSTGRES_MEM= KALI_MEM= # D1: each always-on service also takes optional _PIDS + _CPUS overrides # (generous env-defaults) - POSTGRES/NEO4J/AGENT/WEBAPP/RECON_ORCHESTRATOR/ # DOCKER_BROKER/KALI (e.g. AGENT_CPUS, KALI_PIDS). See docker-compose.yml. # The compose _CPUS defaults are sized for a workstation (neo4j 8, kali 10, # agent 8) and the Docker daemon REJECTS any value above the host core count, so # redamon.sh auto-clamps each one to min(default, detected cores) on every # command. Set one here to pin it; a value in .env always wins over the clamp. KB_REFRESH_MEM= KB_REFRESH_PIDS= # --- Agent reverse-shell LHOST suggestion ---------------------------------- # The Docker host's LAN IP that a target reaches for reverse-shell callbacks # (issue #180). redamon.sh auto-detects this from the default-route interface on # every install/update/up and passes it to the agent, which SUGGESTS it as LHOST. # It is NEVER persisted, so it re-detects when you change networks. Set a value # here ONLY to override detection -- e.g. pin your VPN interface's IP when the # default route is not the interface that reaches the engagement target. A bare # `HOST_LAN_IP=` (empty) is NOT a pin and does not disable detection. HOST_LAN_IP= # --- Container cap ceiling & headroom -------------------------------------- # Absolute max any SINGLE container may use, so one container can never take the # whole host and starve the database (default: ~55% of host RAM). PER_CONTAINER_MAX= # Multiplier that sets each container's hard cap ABOVE its admission envelope, so # a normal peak is never killed and only true runaways are (default: 1.5). CONTAINER_CAP_HEADROOM= # --- D1: per-scan-container CPU + PID ceilings ------------------------------ # CPU cap per scan spawn = CONTAINER_CPU_FRACTION x detected host cores, clamped # to PER_CONTAINER_CPUS. The one machine-proportional knob (default 0.5; 0=off). CONTAINER_CPU_FRACTION= # Absolute per-scan-container CPU ceiling in cores (default: unset = no ceiling). PER_CONTAINER_CPUS= # Fixed generous PID ceiling per scan spawn — stops a fork bomb (default 512). CONTAINER_PIDS_MAX= # --- D3: agent billed-LLM endpoint governor -------------------------------- # Token-bucket burst + sustained refill per (user,ip), and per-user daily call # cap on /llm/*, guardrail, roe, models, provider-test (generous defaults). LLM_GUARD_RATE_CAPACITY= # default 60 LLM_GUARD_RATE_REFILL_PER_SEC= # default 1.0 LLM_GUARD_DAILY_CALL_CAP= # default 5000 # --- S2/E2: internal-key middleware allowlist rollout ---------------------- # Default log-only (off-allowlist internal-key requests are logged, not blocked). # Set true to ENFORCE once logs confirm only the known internal routes appear. INTERNAL_KEY_ALLOWLIST_ENFORCE= # --- Sibling tool containers (katana/nuclei/httpx/... via the broker) ------- # Hard memory ceiling injected into each sibling tool container by the docker # broker (default: spawn-time per-tool envelope passed through by recon). BROKER_TOOL_MEM_BYTES= # D1: fork-bomb PID ceiling injected into each sibling tool container (default 512). BROKER_TOOL_PIDS= # T1/T2: extra host-path prefixes a tool container may bind READ-WRITE (comma- # separated). /tmp/redamon is always allowed; source-tree binds must be :ro. DOCKER_BROKER_ALLOWED_RW_PREFIXES= # --- Dirty supply-chain analyzer (spawned by orchestrator / recon / L1) ----- # The one sibling spawned from THREE processes. Leave EMPTY to let the memory # governor size it (tool envelope x CONTAINER_CAP_HEADROOM, ~1.5 GB, shrinking # on a starved host). Setting it pins a fixed ceiling on every spawn path and # opts this container out of the governor. SUPPLY_CHAIN_ANALYZER_MEM= # Fork-bomb PID ceiling for the analyzer (default 512). SUPPLY_CHAIN_ANALYZER_PIDS= # CPU ceiling in nano-cpus used when the governor returns no CPU cap (default 2e9). SUPPLY_CHAIN_ANALYZER_NANOCPUS= # --- Recon circuit breakers ------------------------------------------------- # A failing dependency (an OSINT API, the agent LLM, WHOIS, a dead scan target) # stops being called after a few consecutive failures instead of costing its # full timeout for every remaining item. Leave EMPTY (= on). Only the exact # value `off` disables the skipping; coverage recording and the finding-prune # guard stay on. Wired explicitly in docker-compose.yml because the orchestrator # has NO env_file; apply with `docker compose up -d recon-orchestrator`. RECON_CIRCUIT_BREAKERS= # --- Scan Timeline (versioned recon graphs) -------------------------------- # ALL OPTIONAL. Every value below has a safe built-in default, so an existing # install needs no edit here: `./redamon.sh update` enables the feature as-is. # Scheduler worker (recon-orchestrator). Wired explicitly in docker-compose.yml # because the orchestrator has NO env_file. SCAN_SCHEDULER_ENABLED= # default true; set false to disable scheduled scans SCAN_SCHEDULER_TICK_SECONDS= # default 60 (floor 10) # Refuse to schedule scans closer together than this (scheduler-DoS guard). SCAN_SCHEDULE_MIN_INTERVAL_MINUTES= # default 15 # How long a scheduled scan is assumed to hold its RAM envelope, for the # overlap check that runs when a schedule is created. SCAN_SCHEDULE_ASSUMED_RUN_MINUTES= # default 60 # Retry cadence + give-up bound when a due run is deferred (graph busy / no RAM). SCAN_SCHEDULE_DEFER_RETRY_MINUTES= # default 5 SCAN_SCHEDULE_MAX_DEFERRALS= # default 6 # Snapshot storage (webapp). Refuse to store a gzipped snapshot above this size, # and cap how many capture/restore windows may hit Neo4j at once. SCAN_SNAPSHOT_MAX_BYTES= # default 134217728 (128 MB) SCAN_SNAPSHOT_MAX_CONCURRENCY= # default 2 # Retention: keep the newest N UNPINNED past versions per project (0 = unlimited), # and prune failed run-history rows older than N days (0 = never). SCAN_VERSION_RETENTION_KEEP= # default 20 SCAN_JOB_FAILED_RETENTION_DAYS= # default 30 # How long a version-activation lock may be held before it is treated as stale # (a crashed activation must never wedge a project forever). ACTIVATION_LOCK_TTL_MS= # default 900000 (15 min) # --- Inbound MCP server (RedAmon AS an MCP server) ------------------------- # Lets YOUR OWN AI agent connect INTO RedAmon and drive recon as one user. # This is the opposite direction from the two MCP features below and above: # "MCP terminal sessions" and MCP_AUTH_TOKEN are the internal Kali servers the # agent calls OUT to; MCP Tool Plugins are also outbound. This one is inbound. # # On is safe here because it is not, by itself, access. With no token minted the # endpoint answers 401 to everyone; enabling it only changes 404 to 401. A token # is per user, is minted in Global Settings behind a password re-confirmation, # and is the only way in. # # A DEPLOYED host is a different question, and the answer there is different: # tooling/deploy/single-host/.env.example ships this as false, deploy.sh # defaults it to false, and it is REFUSED outright over plain http, because # there the endpoint faces the internet rather than loopback. MCP_SERVER_ENABLED=true # Sandbox commands over MCP (kali_exec / kali_output / kali_cancel). ON by # default, and independent of the switch above. This is the only part of the # MCP surface that reaches a live target outside a scan. # # It IS a shell: `bash -c` with the sandbox's full toolset, at parity with # RedAmon's in-app agent. No allowlist, and NO per-command scope check - a # token holding this can reach any host the sandbox can, including one the # project is not for. Nothing catches a bad command afterwards. # # Three switches gate it and all three must be on: this one, the `kali:exec` # token permission (ticked by default, password-confirmed at mint), and the # project's own "Allow MCP Sandbox Commands" toggle (on for new projects), # which a token cannot set for itself. Unticking `kali:exec` is how a token is # kept off the shell; set this to false to withdraw it from every token. MCP_KALI_EXEC_ENABLED=true # kali_exec calls per token per minute (default: 20). Reading a running command's # output uses the cheap read limit instead, so watching one is not priced like # starting another. MCP_RATE_EXEC_PER_MIN= # compare_scan_versions: far heavier than any other read (it gunzips and parses a # whole stored graph, and a `current` side captures the live one). Per PROJECT. MCP_RATE_COMPARE_PER_WINDOW= MCP_RATE_COMPARE_WINDOW_MS= # Withdraw individual MCP tools without taking the whole server down. # Comma-separated tool names; empty means every tool is served. MCP_DISABLED_TOOLS= # Findings one token may mute per day over MCP (default: 200), counted per # finding. The one bound on how much an agent holding triage:mute can hide in # total; unmutes are not counted. Held in memory: a webapp restart resets it. MCP_MUTE_DAILY_BUDGET= # --- MCP terminal sessions ------------------------------------------------- # Max concurrent kali-sandbox PTY terminal sessions (default: 5; further limited # dynamically by available RAM). TERMINAL_MAX_SESSIONS= # --- GVM scan --------------------------------------------------------------- # Abandon a GVM task that reports NO progress for this many seconds (default: # 1800 = 30 min; 0 disables the watchdog). It exists so a stack with no running # scanner fails in minutes instead of burning the full 4h task timeout on every # target. Raise it if you scan slow/filtered hosts with a full IANA port list and # see healthy scans being abandoned. Needs no edit for normal use. # Seconds between mid-scan re-checks that gvmd can still reach ospd-openvas. # This is the dead-scanner detector; 0 disables it. Default 300. GVM_LIVENESS_INTERVAL= # Opt-in hard ceiling on time at an unchanged progress percentage. Default 0 # (off): a large port list legitimately reports no percent for hours. GVM_NO_PROGRESS_TIMEOUT= # --- Startup gate & swap cushion ------------------------------------------- # Set to 1 to SKIP the startup RAM-sufficiency check that refuses to boot when # the host can't hold the core services (default: gate enabled). REDAMON_SKIP_RAM_GATE= # Set to 1 to set up a one-time compressed-RAM (zram) swap cushion on Linux, so # brief overshoots degrade gracefully instead of OOM-killing (default: off). REDAMON_ENABLE_ZRAM=