Containerized Codex CLI (OpenAI's terminal coding agent) with a token-gated web terminal, an authenticated HTTP listener for remote triggering, and a built-in GitHub AI pull-request reviewer.
Reach the same codex CLI three ways: docker exec/attach, a browser web terminal (ttyd), and an HTTP webhook (great for CI/CD).
@openai/codex) preinstalled on Node 22ttyd + shared tmux session (port 7681), gated by an AUTH_TOKEN nginx token gateway8787): POST /trigger (run a prompt) and POST /review (AI review a GitHub PR)codex-run / codex-trigger / codex-review helpers for docker execgh) for fetching PR diffs and posting reviewsservices:
codex-sandbox:
image: itsobaa/codex-sandbox:latest
container_name: codex-sandbox
restart: unless-stopped
environment:
OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
AUTH_TOKEN: "${AUTH_TOKEN:-}" # protects the web terminal (port 7681)
WEBHOOK_TOKEN: "${WEBHOOK_TOKEN:-}" # enables the HTTP listener
GITHUB_TOKEN: "${GITHUB_TOKEN:-}" # enables the AI PR reviewer
# CODEX_MODEL: "gpt-5.3-codex"
# TTYD_CREDENTIAL: "user:replace-me" # optional, layered on top of AUTH_TOKEN
ports:
- "127.0.0.1:7681:7681" # web terminal
- "127.0.0.1:8787:8787" # HTTP listener
volumes:
- codex_sandbox_config:/home/codex/.codex
- codex_sandbox_workspace:/home/codex/workspace
volumes:
codex_sandbox_config:
codex_sandbox_workspace:
http://127.0.0.1:7681/?token=$AUTH_TOKENdocker exec -u codex -it codex-sandbox bash then run codexcurl http://127.0.0.1:8787/healthAll POST endpoints require Authorization: Bearer $WEBHOOK_TOKEN.
GET /health — liveness (no auth)POST /trigger — {prompt, mode?, format?, wait?, continue?, resume?}POST /review — {repo, pr, instructions?, event?, post?, wait?}Session continuity (continue, resume) applies to the headless path only and is rejected when mode is tmux. Capture the session id from a format:"json" run (the thread.started event), then pass it back as resume to continue that conversation.
# Start a session, then continue it later (headless only)
curl -X POST http://127.0.0.1:8787/trigger \
-H "Authorization: Bearer $WEBHOOK_TOKEN" -H "Content-Type: application/json" \
-d '{"prompt":"start the refactor","format":"json"}'
curl -X POST http://127.0.0.1:8787/trigger \
-H "Authorization: Bearer $WEBHOOK_TOKEN" -H "Content-Type: application/json" \
-d '{"prompt":"now add tests","resume":"01J9ABCDEF..."}'
# Or continue the most recent headless session in the workspace (no id required)
curl -X POST http://127.0.0.1:8787/trigger \
-H "Authorization: Bearer $WEBHOOK_TOKEN" -H "Content-Type: application/json" \
-d '{"prompt":"now add tests","continue":true}'
# Trigger an AI review of a PR (fire-and-forget; review is posted to the PR)
curl -X POST http://127.0.0.1:8787/review \
-H "Authorization: Bearer $WEBHOOK_TOKEN" \
-H "Content-Type: application/json" \
-d '{"repo":"owner/name","pr":42}'
A GitHub Action pings /review with {repo, pr}; the container clones the PR, runs Codex as a reviewer, and posts the review back using its own GITHUB_TOKEN (contents:read + pull-requests:write). The workflow needs no model key. See examples/github-workflow-ai-review.yml.
docker exec -i codex-sandbox codex-run "summarize today's git log"
docker exec -i codex-sandbox codex-review --repo owner/name --pr 42
docker exec -i codex-sandbox codex-trigger --tmux "run the linter" # streams into the web terminal
docker exec -i codex-sandbox codex-trigger --continue "now add tests" # continue the latest headless session
docker exec -i codex-sandbox codex-trigger --resume <session-id> "keep going" # resume a specific headless session
OPENAI_API_KEY / OPENAI_BASE_URL / CODEX_MODEL — Codex auth/overridesAUTH_TOKEN — protects the web terminal (Bearer / X-Auth-Token / ?token= / cookie); unset = unauthenticatedWEBHOOK_TOKEN (required to enable listener) / WEBHOOK_PORT (default 8787)GITHUB_TOKEN (or GH_TOKEN) / GH_HOST — for the reviewerTTYD_PORT (default 7681) / TTYD_INTERNAL_PORT (default 7682) / TTYD_CREDENTIAL — web terminalCODEX_EXEC_SANDBOX_FLAGS / CODEX_RUN_FLAGS — headless autonomy flagsCODEX_CONFIG_TOML — seeded config.toml (model defaults + MCP servers)CODEX_HOME (default /home/codex/.codex)/home/codex/.codex — config, auth, session history/home/codex/workspace — working files7681/tcp web terminal (token-gated by AUTH_TOKEN)8787/tcp HTTP listener (token-gated by WEBHOOK_TOKEN)7681/8787 on localhost or a private network; add TLS when exposed.AUTH_TOKEN before exposing 7681 (the terminal is a full shell). Use a long random WEBHOOK_TOKEN; scope GITHUB_TOKEN to the repos that need reviews.OPENAI_API_KEY and GITHUB_TOKEN as secrets.Content type
Image
Digest
sha256:882ed78b8…
Size
287.8 MB
Last updated
about 1 month ago
docker pull itsobaa/codex-sandbox