Inner codex sandbox stays danger-full-access by choice (bwrap path is a separate decision); this hardens everything around it: - DockerExecutor: --security-opt plumbing (repeatable, dedups no-new-privileges), --pids-limit (CLI default 512, fork-bomb guard), per-call extra_env (-e NAME=VALUE, non-secrets only, e.g. proxy URLs; the model key still goes by -e NAME only). - Worker: --egress-proxy-port (0 = off). When on, Docker task containers get HTTP(S)_PROXY pointing at the host filtering proxy via their network gateway IP (tenant network gateway or default bridge gateway). Gateway unresolvable => the attempt fails instead of running unproxied (fail closed, same rule as tenant network creation failure). - AppArmor profile deploy/apparmor/docker-codex: docker-default base + deny network raw/packet, deny ptrace, deny mount/ umount/pivot_root, deny dangerous capabilities, deny writes to /proc/sys, /sys, /proc/keys. Deliberately NO userns rule (that would enable the bwrap path, not this one). File rules mirror docker-default (broad + sensitive denies); a strict file allowlist would need profiling codex's file access set and is not claimed here. - Egress proxy deploy/egress/: Tinyproxy with FilterDefaultDeny + anchored domain allowlist (relay, github, pypi, npm). Anchoring matters: an unanchored 'github.com' regex would also match 'evilgithub.com'. - Seccomp honesty (README): Docker default seccomp already enforces on all task containers; no new stricter allowlist is claimed in this change (building one from memory risks silently breaking the toolchain; it needs syscall profiling first). Tests: 3 outer-hardening tests (security-opt dedup, pids limit, proxy env without leaking the key value, gateway parse/fail, proxy fail-closed). Full suites pass.
26 lines
1.9 KiB
Desktop File
26 lines
1.9 KiB
Desktop File
[Unit]
|
||
Description=Codex cloud autoscaler (scales worker processes by queue depth)
|
||
After=codex-cloud-server.service
|
||
Wants=codex-cloud-server.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=codexsvc
|
||
Group=codexsvc
|
||
WorkingDirectory=/opt/codex-app-server
|
||
EnvironmentFile=/etc/codex-app-server/env
|
||
# scaler 自身参数在前,`--` 之后是传给 cloud.worker 的参数。
|
||
# 不要在这里写 --worker-id / --worker-capacity / --loop,
|
||
# scaler 会按实例强制追加;--db 只给 scaler,scaler 会补给 worker。
|
||
# 注意:启用 autoscaler 后必须停掉静态 codex-cloud-worker,
|
||
# 否则两边同时派任务(scaler 只管理 autoscale-* 实例)。
|
||
ExecStart=/usr/bin/python3 -m cloud.autoscaler --db /var/lib/codex-app-server/control.db --interval 30 --min-workers 1 --max-workers 2 --per-worker-capacity 2 --scale-down-after 3 --drain-timeout 60 --state-file /var/lib/codex-app-server/autoscaler-state.json --log-dir /var/lib/codex-app-server/autoscaler-logs -- --interval 10 --config /opt/codex-app-server/host-config-docker.json --executor docker --docker-image codex-app-server:latest --docker-user 1003:1004 --docker-cpus 2 --docker-memory 2g --docker-extra-mounts /opt/codex-app-server/work:/app/work,/var/lib/codex-app-server/codex-home:/var/lib/codex-app-server/codex-home,/var/lib/codex-app-server/repos:/var/lib/codex-app-server/repos,/var/lib/codex-app-server/test-repo:/var/lib/codex-app-server/test-repo --repos-dir /var/lib/codex-app-server/repos --tenant-isolation --tenants-root /var/lib/codex-app-server/tenants --tenant-template-home /var/lib/codex-app-server/codex-home --tenant-template-repo /var/lib/codex-app-server/test-repo --docker-security-opt apparmor=docker-codex --docker-pids-limit 512 --egress-proxy-port 8888
|
||
Restart=on-failure
|
||
RestartSec=10
|
||
# 停 scaler 时要等它把 worker 优雅排空(drain 60 秒 + 缓冲),
|
||
# 默认 90 秒不够,放到 180 秒;超时后 systemd 再 SIGKILL。
|
||
TimeoutStopSec=180
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|