feat(devcontainer): add codex-dev and secure profile variants

This commit is contained in:
viyatb-oai
2026-02-02 22:03:17 -08:00
parent 58ab6db211
commit 2a4fef682c
4 changed files with 201 additions and 80 deletions

View File

@@ -1,35 +1,61 @@
# Codex devcontainer
# Codex devcontainer profiles
Use this devcontainer when you want to run Codex inside your own project container.
This folder now ships two profiles:
## Who this is for
- `devcontainer.codex-dev.json` (default intent: develop the Codex repo itself)
- `devcontainer.secure.json` (default intent: run Codex in a stricter, firewall-enforced project container)
- developers using Codex on application repos
- teams that want a consistent, secure dev environment
- contributors working on this repo (also supported)
`devcontainer.json` currently mirrors `devcontainer.codex-dev.json` so VS Code opens into the Codex contributor setup by default.
## Quick start
## Profile 1: Codex contributor (`devcontainer.codex-dev.json`)
1. Put this `.devcontainer/` folder in your project.
2. Open the project in VS Code.
3. Run **Dev Containers: Rebuild and Reopen in Container**.
4. In the container terminal, run `codex`.
Use this when working on this repository:
If you prefer API key auth, set `OPENAI_API_KEY` in your host environment before opening the container.
- forces `linux/arm64` (`platform` + `runArgs`)
- uses `CARGO_TARGET_DIR=${containerWorkspaceFolder}/codex-rs/target-arm64`
- keeps firewall off by default (`CODEX_ENABLE_FIREWALL=0`) for lower friction
- still includes persistent mounts and bootstrap (`post_install.py`)
## What you get by default
## Profile 2: Secure project (`devcontainer.secure.json`)
- `codex` CLI preinstalled (`@openai/codex` via npm)
- Node `22` + pnpm `10.28.2`
- Python 3 + pip
- Rust `1.92.0` with `clippy`, `rustfmt`, `rust-src`
- musl targets: `x86_64-unknown-linux-musl`, `aarch64-unknown-linux-musl`
- common tools: git, zsh, rg, fd, fzf, jq, curl
- persistent state volumes for history, auth/config, Cargo cache, and Rustup
Use this when you want stricter egress control:
## How to use Codex after opening the container
- enables firewall startup (`postStartCommand`)
- uses IPv4 allowlisting + IPv6 default-deny
- requires `NET_ADMIN` / `NET_RAW` caps
- uses project-generic Cargo target dir (`/workspace/.cache/cargo-target`)
Basic flow:
## How to switch profiles
Option A (quick swap in repo):
```bash
cp .devcontainer/devcontainer.secure.json .devcontainer/devcontainer.json
```
or
```bash
cp .devcontainer/devcontainer.codex-dev.json .devcontainer/devcontainer.json
```
Then run **Dev Containers: Rebuild and Reopen in Container**.
Option B (CLI without copying):
```bash
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.secure.json
```
or
```bash
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.codex-dev.json
```
## Using Codex after opening the container
The image preinstalls the Codex CLI. In the container terminal:
```bash
codex
@@ -38,53 +64,6 @@ codex
Useful checks:
```bash
codex --help
which codex
```
Typical usage is from your project root (`/workspace`), so Codex can inspect and edit files directly.
## Firewall and network policy
Strict mode is the default (`CODEX_ENABLE_FIREWALL=1`):
- outbound traffic is allowlisted by domain via `OPENAI_ALLOWED_DOMAINS`
- IPv4 is enforced with `iptables` + `ipset`
- IPv6 is explicitly default-deny via `ip6tables` (prevents bypass)
Default allowlist includes:
- OpenAI: `api.openai.com`, `auth.openai.com`
- GitHub: `github.com`, `api.github.com`, `codeload.github.com`, `raw.githubusercontent.com`, `objects.githubusercontent.com`
- registries: `registry.npmjs.org`, `crates.io`, `index.crates.io`, `static.crates.io`, `static.rust-lang.org`, `pypi.org`, `files.pythonhosted.org`
You can temporarily disable strict mode:
```bash
export CODEX_ENABLE_FIREWALL=0
```
Then rebuild/restart the container.
## Adding more languages or tooling
For project-specific stacks (Go, Java, .NET, etc.), add Dev Container features in `devcontainer.json`.
Example:
```json
{
"features": {
"ghcr.io/devcontainers/features/go:1": { "version": "1.24" },
"ghcr.io/devcontainers/features/java:1": { "version": "21" }
}
}
```
## Local Docker smoke build
```bash
docker build -f .devcontainer/Dockerfile -t codex-devcontainer-test .
docker run --rm -it --cap-add=NET_ADMIN --cap-add=NET_RAW \
-v "$PWD":/workspace -w /workspace codex-devcontainer-test zsh
codex --help
```

View File

@@ -0,0 +1,71 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
"name": "Codex",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"platform": "linux/arm64",
"args": {
"TZ": "${localEnv:TZ:UTC}",
"NODE_MAJOR": "22",
"RUST_TOOLCHAIN": "1.92.0",
"CODEX_NPM_VERSION": "latest"
}
},
"runArgs": [
"--platform=linux/arm64"
],
"init": true,
"updateRemoteUserUID": true,
"remoteUser": "vscode",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"mounts": [
"source=codex-commandhistory-${devcontainerId},target=/commandhistory,type=volume",
"source=codex-home-${devcontainerId},target=/home/vscode/.codex,type=volume",
"source=codex-gh-${devcontainerId},target=/home/vscode/.config/gh,type=volume",
"source=codex-cargo-registry-${devcontainerId},target=/home/vscode/.cargo/registry,type=volume",
"source=codex-cargo-git-${devcontainerId},target=/home/vscode/.cargo/git,type=volume",
"source=codex-rustup-${devcontainerId},target=/home/vscode/.rustup,type=volume",
"source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,readonly"
],
"containerEnv": {
"RUST_BACKTRACE": "1",
"CARGO_TARGET_DIR": "${containerWorkspaceFolder}/codex-rs/target-arm64",
"GIT_CONFIG_GLOBAL": "/home/vscode/.gitconfig.local",
"COREPACK_ENABLE_DOWNLOAD_PROMPT": "0",
"PYTHONDONTWRITEBYTECODE": "1",
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
"CODEX_ENABLE_FIREWALL": "0"
},
"remoteEnv": {
"OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}"
},
"postCreateCommand": "python3 /opt/post_install.py",
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "bash",
"icon": "terminal-bash"
},
"zsh": {
"path": "zsh"
}
},
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true
},
"extensions": [
"openai.chatgpt",
"rust-lang.rust-analyzer",
"tamasfe.even-better-toml",
"vadimcn.vscode-lldb",
"ms-azuretools.vscode-docker"
]
}
}
}

View File

@@ -4,6 +4,7 @@
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"platform": "linux/arm64",
"args": {
"TZ": "${localEnv:TZ:UTC}",
"NODE_MAJOR": "22",
@@ -12,8 +13,7 @@
}
},
"runArgs": [
"--cap-add=NET_ADMIN",
"--cap-add=NET_RAW"
"--platform=linux/arm64"
],
"init": true,
"updateRemoteUserUID": true,
@@ -31,22 +31,17 @@
],
"containerEnv": {
"RUST_BACKTRACE": "1",
"CODEX_UNSAFE_ALLOW_NO_SANDBOX": "1",
"CODEX_ENABLE_FIREWALL": "1",
"CODEX_INCLUDE_GITHUB_META_RANGES": "1",
"OPENAI_ALLOWED_DOMAINS": "api.openai.com auth.openai.com github.com api.github.com codeload.github.com raw.githubusercontent.com objects.githubusercontent.com crates.io index.crates.io static.crates.io static.rust-lang.org registry.npmjs.org pypi.org files.pythonhosted.org",
"CARGO_TARGET_DIR": "/workspace/.cache/cargo-target",
"CARGO_TARGET_DIR": "${containerWorkspaceFolder}/codex-rs/target-arm64",
"GIT_CONFIG_GLOBAL": "/home/vscode/.gitconfig.local",
"COREPACK_ENABLE_DOWNLOAD_PROMPT": "0",
"PYTHONDONTWRITEBYTECODE": "1",
"PIP_DISABLE_PIP_VERSION_CHECK": "1"
"PIP_DISABLE_PIP_VERSION_CHECK": "1",
"CODEX_ENABLE_FIREWALL": "0"
},
"remoteEnv": {
"OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}"
},
"postCreateCommand": "python3 /opt/post_install.py",
"postStartCommand": "bash /opt/post_start.sh",
"waitFor": "postStartCommand",
"customizations": {
"vscode": {
"settings": {

View File

@@ -0,0 +1,76 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
"name": "Codex",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"TZ": "${localEnv:TZ:UTC}",
"NODE_MAJOR": "22",
"RUST_TOOLCHAIN": "1.92.0",
"CODEX_NPM_VERSION": "latest"
}
},
"runArgs": [
"--cap-add=NET_ADMIN",
"--cap-add=NET_RAW"
],
"init": true,
"updateRemoteUserUID": true,
"remoteUser": "vscode",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
"workspaceFolder": "/workspace",
"mounts": [
"source=codex-commandhistory-${devcontainerId},target=/commandhistory,type=volume",
"source=codex-home-${devcontainerId},target=/home/vscode/.codex,type=volume",
"source=codex-gh-${devcontainerId},target=/home/vscode/.config/gh,type=volume",
"source=codex-cargo-registry-${devcontainerId},target=/home/vscode/.cargo/registry,type=volume",
"source=codex-cargo-git-${devcontainerId},target=/home/vscode/.cargo/git,type=volume",
"source=codex-rustup-${devcontainerId},target=/home/vscode/.rustup,type=volume",
"source=${localEnv:HOME}/.gitconfig,target=/home/vscode/.gitconfig,type=bind,readonly"
],
"containerEnv": {
"RUST_BACKTRACE": "1",
"CODEX_UNSAFE_ALLOW_NO_SANDBOX": "1",
"CODEX_ENABLE_FIREWALL": "1",
"CODEX_INCLUDE_GITHUB_META_RANGES": "1",
"OPENAI_ALLOWED_DOMAINS": "api.openai.com auth.openai.com github.com api.github.com codeload.github.com raw.githubusercontent.com objects.githubusercontent.com crates.io index.crates.io static.crates.io static.rust-lang.org registry.npmjs.org pypi.org files.pythonhosted.org",
"CARGO_TARGET_DIR": "/workspace/.cache/cargo-target",
"GIT_CONFIG_GLOBAL": "/home/vscode/.gitconfig.local",
"COREPACK_ENABLE_DOWNLOAD_PROMPT": "0",
"PYTHONDONTWRITEBYTECODE": "1",
"PIP_DISABLE_PIP_VERSION_CHECK": "1"
},
"remoteEnv": {
"OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}"
},
"postCreateCommand": "python3 /opt/post_install.py",
"postStartCommand": "bash /opt/post_start.sh",
"waitFor": "postStartCommand",
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "bash",
"icon": "terminal-bash"
},
"zsh": {
"path": "zsh"
}
},
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true
},
"extensions": [
"openai.chatgpt",
"rust-lang.rust-analyzer",
"tamasfe.even-better-toml",
"vadimcn.vscode-lldb",
"ms-azuretools.vscode-docker"
]
}
}
}