Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ TRACECAT__RESULT_EXTERNALIZATION_THRESHOLD_BYTES=128000
# --- Agent filesystem persistence ---
# Maximum compressed bytes retained in each worker's local agent snapshot archive cache.
TRACECAT__AGENT_FS_ARCHIVE_CACHE_MAX_BYTES=10737418240
# Per-sandbox cgroup memory limit and executor memory reserved outside activity slots.
TRACECAT__AGENT_SANDBOX_MEMORY_MB=4096
TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED=true
TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB=4096
# Readiness sentinel path shared by the worker and the compose healthcheck.
TRACECAT__AGENT_EXECUTOR_READY_FILE=/var/run/tracecat/agent-executor-ready

# --- Local registry ---
# Enable this only for local-registry development. Leave disabled for normal remote/builtin registry use.
Expand Down
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ ENV PYTHONPATH="/home/apiuser/.local"

RUN mkdir -p /home/apiuser/.local/bin && ln -s $(which uv) /home/apiuser/.local/bin/uv

COPY docker/scripts/agent-executor-entrypoint.sh /usr/local/bin/agent-executor-entrypoint.sh
RUN chmod +x /usr/local/bin/agent-executor-entrypoint.sh

# Switch to non-root user (matches production, required for pasta userspace networking)
USER apiuser

Expand Down Expand Up @@ -278,6 +281,9 @@ ENV TMPDIR="/home/apiuser/.cache/tmp" TEMP="/home/apiuser/.cache/tmp" TMP="/home

RUN mkdir -p /app/.scripts && chown -R apiuser:apiuser /app

COPY docker/scripts/agent-executor-entrypoint.sh /usr/local/bin/agent-executor-entrypoint.sh
RUN chmod +x /usr/local/bin/agent-executor-entrypoint.sh

# Switch to non-root user
USER apiuser

Expand Down
9 changes: 9 additions & 0 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,10 @@ services:
TRACECAT__AGENT_EXECUTOR_QUEUE: ${TRACECAT__AGENT_EXECUTOR_QUEUE:-shared-agent-executor-queue}
TRACECAT__EXECUTOR_QUEUE: ${TRACECAT__EXECUTOR_QUEUE:-shared-action-queue}
TRACECAT__AGENT_EXECUTOR_MAX_CONCURRENT_ACTIVITIES: ${TRACECAT__AGENT_EXECUTOR_MAX_CONCURRENT_ACTIVITIES:-1}
TRACECAT__AGENT_SANDBOX_MEMORY_MB: ${TRACECAT__AGENT_SANDBOX_MEMORY_MB:-4096}
TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED: ${TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED:-true}
TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB: ${TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB:-4096}
TRACECAT__AGENT_EXECUTOR_READY_FILE: ${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}
TRACECAT__LLM_PROXY_READ_TIMEOUT: ${TRACECAT__LLM_PROXY_READ_TIMEOUT:-600}
TRACECAT__LLM_GATEWAY_CREDENTIAL_CACHE_TTL_SECONDS: ${TRACECAT__LLM_GATEWAY_CREDENTIAL_CACHE_TTL_SECONDS:-60}
TRACECAT__LLM_GATEWAY_HEALTHCHECK_INTERVAL_SECONDS: ${TRACECAT__LLM_GATEWAY_HEALTHCHECK_INTERVAL_SECONDS:-30}
Expand All @@ -430,6 +434,11 @@ services:
- ${TRACECAT__LOCAL_REPOSITORY_PATH}:/app/local_registry
- sandbox-cache:/var/lib/tracecat/sandbox-cache
command: ["python", "-m", "tracecat.agent.executor_worker"]
healthcheck:
test: ["CMD", "test", "-f", "${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}"]
interval: 30s
retries: 3
start_period: 120s
depends_on:
litellm:
condition: service_healthy
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,10 @@ services:
TRACECAT__AGENT_EXECUTOR_QUEUE: ${TRACECAT__AGENT_EXECUTOR_QUEUE:-shared-agent-executor-queue}
TRACECAT__EXECUTOR_QUEUE: ${TRACECAT__EXECUTOR_QUEUE:-shared-action-queue}
TRACECAT__AGENT_EXECUTOR_MAX_CONCURRENT_ACTIVITIES: ${TRACECAT__AGENT_EXECUTOR_MAX_CONCURRENT_ACTIVITIES:-1}
TRACECAT__AGENT_SANDBOX_MEMORY_MB: ${TRACECAT__AGENT_SANDBOX_MEMORY_MB:-4096}
TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED: ${TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED:-true}
TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB: ${TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB:-4096}
TRACECAT__AGENT_EXECUTOR_READY_FILE: ${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}
TRACECAT__LLM_PROXY_READ_TIMEOUT: ${TRACECAT__LLM_PROXY_READ_TIMEOUT:-600}
TRACECAT__LLM_GATEWAY_CREDENTIAL_CACHE_TTL_SECONDS: ${TRACECAT__LLM_GATEWAY_CREDENTIAL_CACHE_TTL_SECONDS:-60}
TRACECAT__LLM_GATEWAY_HEALTHCHECK_INTERVAL_SECONDS: ${TRACECAT__LLM_GATEWAY_HEALTHCHECK_INTERVAL_SECONDS:-30}
Expand All @@ -450,6 +454,11 @@ services:
- ${TRACECAT__LOCAL_REPOSITORY_PATH}:/app/local_registry
- sandbox-cache:/var/lib/tracecat/sandbox-cache
command: ["python", "-m", "tracecat.agent.executor_worker"]
healthcheck:
test: ["CMD", "test", "-f", "${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}"]
interval: 30s
retries: 3
start_period: 120s
depends_on:
litellm:
condition: service_healthy
Expand Down
15 changes: 15 additions & 0 deletions docker-compose.sandbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,23 @@ services:
# Required for nsjail sandbox execution.
cap_add:
- SYS_ADMIN
# Start as root so the entrypoint can delegate the container's cgroup v2
# subtree to apiuser for per-sandbox memory limits; it drops privileges
# before the worker starts. Override neither independently.
user: "0:0"
entrypoint: ["/usr/local/bin/agent-executor-entrypoint.sh"]
environment:
TRACECAT__AGENT_SANDBOX_MEMORY_MB: ${TRACECAT__AGENT_SANDBOX_MEMORY_MB:-4096}
TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED: ${TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED:-true}
TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB: ${TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB:-4096}
TRACECAT__AGENT_EXECUTOR_READY_FILE: ${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}
security_opt:
- seccomp:unconfined
- systempaths=unconfined
devices:
- /dev/net/tun:/dev/net/tun
healthcheck:
test: ["CMD", "test", "-f", "${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}"]
Comment thread
daryllimyt marked this conversation as resolved.
interval: 30s
retries: 3
start_period: 120s
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,10 @@ services:
TRACECAT__AGENT_EXECUTOR_QUEUE: ${TRACECAT__AGENT_EXECUTOR_QUEUE:-shared-agent-executor-queue}
TRACECAT__EXECUTOR_QUEUE: ${TRACECAT__EXECUTOR_QUEUE:-shared-action-queue}
TRACECAT__AGENT_EXECUTOR_MAX_CONCURRENT_ACTIVITIES: ${TRACECAT__AGENT_EXECUTOR_MAX_CONCURRENT_ACTIVITIES:-1}
TRACECAT__AGENT_SANDBOX_MEMORY_MB: ${TRACECAT__AGENT_SANDBOX_MEMORY_MB:-4096}
TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED: ${TRACECAT__AGENT_SANDBOX_CGROUP_ENABLED:-true}
Comment thread
daryllimyt marked this conversation as resolved.
TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB: ${TRACECAT__AGENT_EXECUTOR_MEMORY_RESERVE_MB:-4096}
TRACECAT__AGENT_EXECUTOR_READY_FILE: ${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}
TRACECAT__LLM_PROXY_READ_TIMEOUT: ${TRACECAT__LLM_PROXY_READ_TIMEOUT:-600}
TRACECAT__LLM_GATEWAY_CREDENTIAL_CACHE_TTL_SECONDS: ${TRACECAT__LLM_GATEWAY_CREDENTIAL_CACHE_TTL_SECONDS:-60}
TRACECAT__LLM_GATEWAY_HEALTHCHECK_INTERVAL_SECONDS: ${TRACECAT__LLM_GATEWAY_HEALTHCHECK_INTERVAL_SECONDS:-30}
Expand All @@ -445,6 +449,11 @@ services:
- ${TRACECAT__LOCAL_REPOSITORY_PATH}:/app/local_registry
- sandbox-cache:/var/lib/tracecat/sandbox-cache
command: ["python", "-m", "tracecat.agent.executor_worker"]
healthcheck:
test: ["CMD", "test", "-f", "${TRACECAT__AGENT_EXECUTOR_READY_FILE:-/var/run/tracecat/agent-executor-ready}"]
interval: 30s
retries: 3
start_period: 120s
depends_on:
litellm:
condition: service_healthy
Expand Down
32 changes: 32 additions & 0 deletions docker/scripts/agent-executor-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail

# Agent-executor entrypoint for deployments that enable per-sandbox cgroup
# memory limits. Start the container as root with this entrypoint (compose:
# user "0:0"; Kubernetes: runAsUser 0) and it hands the container's own
# cgroup v2 directory to apiuser so the worker can prepare nsjail child
# cgroups without root, then drops privileges before starting it. Where the
# needed privileges are absent the worker starts unchanged and falls back to
# rlimit-only sandbox limits. Non-root invocations pass straight through.
if [[ "$(id -u)" == "0" ]]; then
Comment thread
daryllimyt marked this conversation as resolved.
# Resolve this container's cgroup v2 directory: the mount root under a
# private cgroup namespace, a subpath of the host cgroupfs otherwise
# (e.g. privileged Kubernetes). Never touch anything above it.
cgroup_rel="$(sed -n 's/^0:://p' /proc/self/cgroup)"
cgroup_rel="${cgroup_rel#/}"
cgroup_dir="/sys/fs/cgroup${cgroup_rel:+/$cgroup_rel}"
Comment thread
daryllimyt marked this conversation as resolved.
Outdated
mount -o remount,rw /sys/fs/cgroup 2>/dev/null || true
if chown apiuser:apiuser "$cgroup_dir" "$cgroup_dir/cgroup.procs" \
"$cgroup_dir/cgroup.subtree_control" "$cgroup_dir/cgroup.threads"; then
echo "Delegated $cgroup_dir to apiuser."
else
echo "Unable to delegate $cgroup_dir to apiuser; agent sandbox" \
"cgroup limits will be unavailable." >&2
fi
# setpriv changes only IDs; fix the identity env vars ourselves instead of
# --reset-env, which would clear the service configuration environment.
export HOME=/home/apiuser USER=apiuser LOGNAME=apiuser
exec setpriv --reuid=apiuser --regid=apiuser --init-groups "$@"
fi

exec "$@"
Loading
Loading