Files
codex-app-server/deploy/host-worker/codex-host-worker.service
T
host 5d09af855f Host-level sandbox tasks: LocalExecutor + bwrap workspace-write
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.
2026-10-26 08:23:37 +08:00

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