Docker outer layer and bwrap inner layer are mutually exclusive on this host (fresh proc mounts fail with kernel EPERM inside Docker's nested pidns, but work on the host under a userns profile). So tasks that need an inner sandbox run on the host: - Worker --claim-executor-only: strict executor claim (only executor == own type, never NULL). The host worker MUST use it, or it would steal NULL-executor tasks meant for Docker workers (those tasks would lose the Docker outer layer). Default behavior unchanged (NULL claimable by any worker). - host-config-host.json: sandbox workspace-write, state work/host-state-host.json (distinct from Docker tasks' host-state.json), same relay home and test repo as Docker. - deploy/apparmor/codex-host: docker-codex base + userns, mount, pivot_root for bwrap; still denies raw network, ptrace, dangerous capabilities, /proc/sys writes. - deploy/host-worker/codex-host-worker.service: aa-exec -p codex-host, --executor local --claim-executor-only, capacity 2, proxy env 127.0.0.1:8888 so host tasks' relay/git egress also goes through the Tinyproxy allowlist (host direct egress would bypass it). POST /tasks already accepts executor (local/docker/cloud), so no API change was needed for routing. Tests: 4 host-sandbox-routing tests (strict claim incl. CAS, default still takes NULL, config sandbox/state, profile allows bwrap without deny mount). Full suites pass.
36 lines
1.6 KiB
Desktop File
36 lines
1.6 KiB
Desktop File
[Unit]
|
|
Description=Codex host-level sandbox worker (LocalExecutor, bwrap inner sandbox)
|
|
After=network.target codex-cloud-server.service
|
|
Wants=codex-cloud-server.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=codexsvc
|
|
Group=codexsvc
|
|
WorkingDirectory=/opt/codex-app-server
|
|
# EnvironmentFile supplies CLOUD_DB_* and XCM_API_KEY (0600, root-owned).
|
|
# The worker never prints env values.
|
|
EnvironmentFile=/etc/codex-app-server/env
|
|
# Egress allowlist for host-level tasks: relay/git go through the same
|
|
# Tinyproxy as container tasks (127.0.0.1 is allowed by the iptables
|
|
# rules; without this, host tasks would bypass the allowlist).
|
|
Environment=HTTP_PROXY=http://127.0.0.1:8888
|
|
Environment=HTTPS_PROXY=http://127.0.0.1:8888
|
|
Environment=http_proxy=http://127.0.0.1:8888
|
|
Environment=https_proxy=http://127.0.0.1:8888
|
|
Environment=NO_PROXY=localhost,127.0.0.1
|
|
Environment=no_proxy=localhost,127.0.0.1
|
|
# aa-exec confines the worker (and its children: host.py, app-server,
|
|
# codex, bwrap, tools) under the codex-host AppArmor profile, which
|
|
# allows userns+mount for bwrap. Without aa-exec, bwrap fails on
|
|
# AppArmor userns/mount restrictions. --claim-executor-only is
|
|
# REQUIRED: this worker must only take executor='local' tasks and
|
|
# must never steal NULL-executor tasks meant for Docker workers.
|
|
ExecStart=/usr/bin/aa-exec -p codex-host -- /usr/bin/python3 -m cloud.worker --interval 10 --config /opt/codex-app-server/host-config-host.json --executor local --claim-executor-only --worker-capacity 2 --loop --db /var/lib/codex-app-server/control.db --worker-id host-1 --repos-dir /var/lib/codex-app-server/repos
|
|
Restart=on-failure
|
|
RestartSec=10
|
|
TimeoutStopSec=180
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|