[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