mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
feat(devcontainer): add separate secure customer profile
This commit is contained in:
@@ -1,71 +1,27 @@
|
||||
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ARG TZ
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG NODE_MAJOR=22
|
||||
ARG RUST_TOOLCHAIN=1.92.0
|
||||
ARG CODEX_NPM_VERSION=latest
|
||||
# enable 'universe' because musl-tools & clang live there
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
software-properties-common && \
|
||||
add-apt-repository --yes universe
|
||||
|
||||
ENV TZ="$TZ"
|
||||
# now install build deps
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential curl git ca-certificates \
|
||||
pkg-config libcap-dev clang musl-tools libssl-dev just && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
# Ubuntu 24.04 ships with user 'ubuntu' already created with UID 1000.
|
||||
USER ubuntu
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
curl \
|
||||
git \
|
||||
ca-certificates \
|
||||
pkg-config \
|
||||
clang \
|
||||
musl-tools \
|
||||
libssl-dev \
|
||||
libsqlite3-dev \
|
||||
just \
|
||||
python3 \
|
||||
python3-pip \
|
||||
jq \
|
||||
less \
|
||||
man-db \
|
||||
unzip \
|
||||
ripgrep \
|
||||
fzf \
|
||||
fd-find \
|
||||
zsh \
|
||||
dnsutils \
|
||||
iproute2 \
|
||||
ipset \
|
||||
iptables \
|
||||
aggregate \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
# install Rust + musl target as dev user
|
||||
RUN curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal && \
|
||||
~/.cargo/bin/rustup target add aarch64-unknown-linux-musl && \
|
||||
~/.cargo/bin/rustup component add clippy rustfmt
|
||||
|
||||
RUN curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& npm install -g corepack@latest "@openai/codex@${CODEX_NPM_VERSION}" \
|
||||
&& corepack enable \
|
||||
&& corepack prepare pnpm@10.28.2 --activate \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
ENV PATH="/home/ubuntu/.cargo/bin:${PATH}"
|
||||
|
||||
COPY .devcontainer/init-firewall.sh /usr/local/bin/init-firewall.sh
|
||||
COPY .devcontainer/post_install.py /opt/post_install.py
|
||||
COPY .devcontainer/post-start.sh /opt/post_start.sh
|
||||
|
||||
RUN chmod 500 /usr/local/bin/init-firewall.sh \
|
||||
&& chmod 755 /opt/post_start.sh \
|
||||
&& chmod 644 /opt/post_install.py \
|
||||
&& chown vscode:vscode /opt/post_install.py
|
||||
|
||||
RUN install -d -m 0775 -o vscode -g vscode /commandhistory /workspace \
|
||||
&& touch /commandhistory/.bash_history /commandhistory/.zsh_history \
|
||||
&& chown vscode:vscode /commandhistory/.bash_history /commandhistory/.zsh_history
|
||||
|
||||
USER vscode
|
||||
ENV PATH="/home/vscode/.cargo/bin:${PATH}"
|
||||
WORKDIR /workspace
|
||||
|
||||
RUN curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "${RUST_TOOLCHAIN}" \
|
||||
&& rustup component add clippy rustfmt rust-src \
|
||||
&& rustup target add x86_64-unknown-linux-musl aarch64-unknown-linux-musl
|
||||
|
||||
71
.devcontainer/Dockerfile.secure
Normal file
71
.devcontainer/Dockerfile.secure
Normal file
@@ -0,0 +1,71 @@
|
||||
FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04
|
||||
|
||||
ARG TZ
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG NODE_MAJOR=22
|
||||
ARG RUST_TOOLCHAIN=1.92.0
|
||||
ARG CODEX_NPM_VERSION=latest
|
||||
|
||||
ENV TZ="$TZ"
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
curl \
|
||||
git \
|
||||
ca-certificates \
|
||||
pkg-config \
|
||||
clang \
|
||||
musl-tools \
|
||||
libssl-dev \
|
||||
libsqlite3-dev \
|
||||
just \
|
||||
python3 \
|
||||
python3-pip \
|
||||
jq \
|
||||
less \
|
||||
man-db \
|
||||
unzip \
|
||||
ripgrep \
|
||||
fzf \
|
||||
fd-find \
|
||||
zsh \
|
||||
dnsutils \
|
||||
iproute2 \
|
||||
ipset \
|
||||
iptables \
|
||||
aggregate \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash - \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& npm install -g corepack@latest "@openai/codex@${CODEX_NPM_VERSION}" \
|
||||
&& corepack enable \
|
||||
&& corepack prepare pnpm@10.28.2 --activate \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY .devcontainer/init-firewall.sh /usr/local/bin/init-firewall.sh
|
||||
COPY .devcontainer/post_install.py /opt/post_install.py
|
||||
COPY .devcontainer/post-start.sh /opt/post_start.sh
|
||||
|
||||
RUN chmod 500 /usr/local/bin/init-firewall.sh \
|
||||
&& chmod 755 /opt/post_start.sh \
|
||||
&& chmod 644 /opt/post_install.py \
|
||||
&& chown vscode:vscode /opt/post_install.py
|
||||
|
||||
RUN install -d -m 0775 -o vscode -g vscode /commandhistory /workspace \
|
||||
&& touch /commandhistory/.bash_history /commandhistory/.zsh_history \
|
||||
&& chown vscode:vscode /commandhistory/.bash_history /commandhistory/.zsh_history
|
||||
|
||||
USER vscode
|
||||
ENV PATH="/home/vscode/.cargo/bin:${PATH}"
|
||||
WORKDIR /workspace
|
||||
|
||||
RUN curl -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain "${RUST_TOOLCHAIN}" \
|
||||
&& rustup component add clippy rustfmt rust-src \
|
||||
&& rustup target add x86_64-unknown-linux-musl aarch64-unknown-linux-musl
|
||||
@@ -1,69 +1,45 @@
|
||||
# Codex devcontainer profiles
|
||||
# Containerized Development
|
||||
|
||||
This folder now ships two profiles:
|
||||
We provide two container paths:
|
||||
|
||||
- `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)
|
||||
- `devcontainer.json` keeps the existing Codex contributor setup for working on this repository.
|
||||
- `devcontainer.secure.json` adds a customer-oriented profile with stricter outbound network controls.
|
||||
|
||||
`devcontainer.json` currently mirrors `devcontainer.codex-dev.json` so VS Code opens into the Codex contributor setup by default.
|
||||
## Codex contributor profile
|
||||
|
||||
## Profile 1: Codex contributor (`devcontainer.codex-dev.json`)
|
||||
Use `devcontainer.json` when you are developing Codex itself. This is the same lightweight arm64 container that already exists in the repo.
|
||||
|
||||
Use this when working on this repository:
|
||||
## Secure customer profile
|
||||
|
||||
- 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`)
|
||||
Use `devcontainer.secure.json` when you want a stricter runtime profile for running Codex inside a project container:
|
||||
|
||||
## Profile 2: Secure project (`devcontainer.secure.json`)
|
||||
- installs the Codex CLI plus common build tools
|
||||
- enables firewall startup with an allowlist-driven outbound policy
|
||||
- blocks IPv6 by default so the allowlist cannot be bypassed over AAAA routes
|
||||
- requires `NET_ADMIN` and `NET_RAW` so the firewall can be installed at startup
|
||||
|
||||
Use this when you want stricter egress control:
|
||||
This profile keeps the stricter networking isolated to the customer path instead of changing the default Codex contributor 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`)
|
||||
|
||||
## 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):
|
||||
Start it from the CLI with:
|
||||
|
||||
```bash
|
||||
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.secure.json
|
||||
```
|
||||
|
||||
or
|
||||
In VS Code, choose **Dev Containers: Open Folder in Container...** and select `.devcontainer/devcontainer.secure.json`.
|
||||
|
||||
```bash
|
||||
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.codex-dev.json
|
||||
## Docker
|
||||
|
||||
To build the contributor image locally for x64 and then run it with the repo mounted under `/workspace`:
|
||||
|
||||
```shell
|
||||
CODEX_DOCKER_IMAGE_NAME=codex-linux-dev
|
||||
docker build --platform=linux/amd64 -t "$CODEX_DOCKER_IMAGE_NAME" ./.devcontainer
|
||||
docker run --platform=linux/amd64 --rm -it -e CARGO_TARGET_DIR=/workspace/codex-rs/target-amd64 -v "$PWD":/workspace -w /workspace/codex-rs "$CODEX_DOCKER_IMAGE_NAME"
|
||||
```
|
||||
|
||||
## Using Codex after opening the container
|
||||
Note that `/workspace/target` will contain the binaries built for your host platform, so we include `-e CARGO_TARGET_DIR=/workspace/codex-rs/target-amd64` in the `docker run` command so that the binaries built inside your container are written to a separate directory.
|
||||
|
||||
The image preinstalls the Codex CLI. In the container terminal:
|
||||
For arm64, specify `--platform=linux/arm64` instead for both `docker build` and `docker run`.
|
||||
|
||||
```bash
|
||||
codex
|
||||
```
|
||||
|
||||
Useful checks:
|
||||
|
||||
```bash
|
||||
which codex
|
||||
codex --help
|
||||
```
|
||||
Currently, the contributor `Dockerfile` works for both x64 and arm64 Linux, though you need to run `rustup target add x86_64-unknown-linux-musl` yourself to install the musl toolchain for x64.
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
{
|
||||
"$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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +1,27 @@
|
||||
{
|
||||
"$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"
|
||||
}
|
||||
"platform": "linux/arm64"
|
||||
},
|
||||
"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"
|
||||
],
|
||||
|
||||
/* Force VS Code to run the container as arm64 in
|
||||
case your host is x86 (or vice-versa). */
|
||||
"runArgs": ["--platform=linux/arm64"],
|
||||
|
||||
"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"
|
||||
"CARGO_TARGET_DIR": "${containerWorkspaceFolder}/codex-rs/target-arm64"
|
||||
},
|
||||
"remoteEnv": {
|
||||
"OPENAI_API_KEY": "${localEnv:OPENAI_API_KEY}"
|
||||
},
|
||||
"postCreateCommand": "python3 /opt/post_install.py",
|
||||
|
||||
"remoteUser": "ubuntu",
|
||||
"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
|
||||
"terminal.integrated.defaultProfile.linux": "bash"
|
||||
},
|
||||
"extensions": [
|
||||
"openai.chatgpt",
|
||||
"rust-lang.rust-analyzer",
|
||||
"tamasfe.even-better-toml",
|
||||
"vadimcn.vscode-lldb",
|
||||
"ms-azuretools.vscode-docker"
|
||||
]
|
||||
"extensions": ["rust-lang.rust-analyzer", "tamasfe.even-better-toml"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json",
|
||||
"name": "Codex",
|
||||
"name": "Codex (Secure)",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"dockerfile": "Dockerfile.secure",
|
||||
"context": "..",
|
||||
"args": {
|
||||
"TZ": "${localEnv:TZ:UTC}",
|
||||
|
||||
Reference in New Issue
Block a user