Skip to content

Latest commit

 

History

History
366 lines (267 loc) · 9.14 KB

File metadata and controls

366 lines (267 loc) · 9.14 KB

GitHub and Codex Credentials Setup

  • Path: docs/setup/ubuntu/auth.md
  • Template Version: 20260508

Purpose

This document describes how to configure credentials for GitHub CLI and Codex CLI when running Codex agents through GitHub Flows.

The credentials are used by Docker-isolated agent executions.

This document covers:

  • GitHub personal access token storage;
  • GitHub CLI authentication through GH_TOKEN;
  • Codex authentication through persisted Codex auth state;
  • profile configuration for passing credentials into the agent container.

This document does not describe Docker image creation, application deployment, Apache configuration, or GitHub webhook setup.

Runtime Assumptions

The runtime user is referenced as user.

The application is deployed into:

/home/user/app/github-flows/

The runtime workspace is located under:

/home/user/app/github-flows/var/work/

The Codex agent image is:

github-flows-agent-codex:latest

The GitHub token file is:

/home/user/.secrets/gh-token

The Codex auth state directory is:

/home/user/.secrets/codex/

Inside the container:

/run/secrets/gh-token      GitHub token file
/home/user/.codex          Codex auth state
/workspace                 per-run workspace

GitHub Account Access

The GitHub account used by the agent must have access to the target repository.

For a private organization repository, organization membership alone may not be enough. The account must have repository access through direct repository permissions, team membership, or another approved organization access policy.

For a Codex agent that reads issues, modifies files, pushes branches, and opens pull requests, the GitHub account typically needs write access to the target repository.

GitHub Token

Create a fine-grained personal access token for the GitHub account used by the agent.

Recommended repository access:

Only selected repositories:
  owner/repository

Recommended repository permissions:

Metadata: Read
Contents: Read and write
Issues: Read and write
Pull requests: Read and write

If the repository belongs to an organization, the token may require organization owner approval before it can access private organization resources.

For organization approval, use the organization settings:

Organization
  -> Settings
  -> Personal access tokens
  -> Pending requests
  -> select the token request
  -> Approve

Store the GitHub Token

Run under the runtime user:

sudo -iu user

Create the secrets directory:

mkdir -p /home/user/.secrets
chmod 700 /home/user/.secrets

Create the token file:

nano /home/user/.secrets/gh-token
chmod 600 /home/user/.secrets/gh-token

The file must contain only the raw GitHub token value.

Check that the runtime user can read the token:

test -r /home/user/.secrets/gh-token && echo gh-token-ok

Verify GitHub Token in the Container

Check the GitHub identity exposed by the token:

docker run --rm \
  --mount type=bind,src=/home/user/.secrets/gh-token,dst=/run/secrets/gh-token,readonly \
  -e GH_TOKEN_FILE=/run/secrets/gh-token \
  github-flows-agent-codex:latest \
  bash -lc 'export GH_TOKEN="$(tr -d "\r\n" < "$GH_TOKEN_FILE")"; export GITHUB_TOKEN="$GH_TOKEN"; gh api user --jq .login'

Check repository access:

docker run --rm \
  --mount type=bind,src=/home/user/.secrets/gh-token,dst=/run/secrets/gh-token,readonly \
  -e GH_TOKEN_FILE=/run/secrets/gh-token \
  github-flows-agent-codex:latest \
  bash -lc 'export GH_TOKEN="$(tr -d "\r\n" < "$GH_TOKEN_FILE")"; export GITHUB_TOKEN="$GH_TOKEN"; gh repo view owner/repository'

The tr -d "\r\n" command removes line endings from the token file before exporting the token.

Codex Authentication

Codex CLI supports authentication through a ChatGPT account or through an OpenAI API key.

For subscription-based Codex use, authenticate Codex through ChatGPT sign-in and persist the Codex auth state outside the container image.

Create the Codex auth directory:

sudo -iu user

mkdir -p /home/user/.secrets/codex
chmod 700 /home/user/.secrets/codex

Run Codex login interactively:

docker run --rm -it \
  --name github-flows-codex-login \
  --mount type=bind,src=/home/user/.secrets/codex,dst=/home/user/.codex \
  --mount type=bind,src=/home/user/app/github-flows/var/work,dst=/workspace \
  -w /workspace \
  github-flows-agent-codex:latest \
  codex login

Complete the browser or device authentication flow shown by Codex.

After login, check that Codex auth state was written:

find /home/user/.secrets/codex -maxdepth 3 -type f -ls

Choose and Persist Codex Model

Run Codex interactively with the persisted auth state:

docker run --rm -it \
  --name github-flows-codex-interactive \
  --mount type=bind,src=/home/user/.secrets/codex,dst=/home/user/.codex \
  --mount type=bind,src=/home/user/app/github-flows/var/work,dst=/workspace \
  -w /workspace \
  github-flows-agent-codex:latest \
  codex

Inside Codex, select the model:

/model

Check the active session settings:

/status

The selected model and Codex settings are stored in the mounted Codex auth/config directory.

Profile Credential Configuration

A profile can mount both credential sources into the container:

{
  "runtime": {
    "env": {
      "LOG_LEVEL": "info",
      "GH_TOKEN_FILE": "/run/secrets/gh-token"
    },
    "dockerArgs": [
      "--mount",
      "type=bind,src=/home/user/.secrets/codex,dst=/home/user/.codex",
      "--mount",
      "type=bind,src=/home/user/.secrets/gh-token,dst=/run/secrets/gh-token,readonly"
    ]
  }
}

This does not automatically create GH_TOKEN.

The profile command must read GH_TOKEN_FILE and export GH_TOKEN before starting Codex.

Profile Example

This profile launches Codex through bash -lc, reads the GitHub token from /run/secrets/gh-token, exports GH_TOKEN and GITHUB_TOKEN, and then starts Codex.

{
  "trigger": {
    "repository": "owner/repository",
    "event": "issue_comment",
    "action": "created"
  },
  "execution": {
    "handler": {
      "type": "agent",
      "command": ["bash", "-lc"],
      "args": [
        "export GH_TOKEN=\"$(tr -d '\\r\\n' < \"$GH_TOKEN_FILE\")\"; export GITHUB_TOKEN=\"$GH_TOKEN\"; exec codex exec --dangerously-bypass-approvals-and-sandbox -C /workspace/repo"
      ],
      "promptRef": "prompt.md",
      "promptVariables": {
        "REPOSITORY": "event.repository.full_name",
        "ISSUE_NUMBER": "event.issue.number",
        "ISSUE_TITLE": "event.issue.title",
        "ISSUE_BODY": "event.issue.body",
        "ISSUE_AUTHOR": "event.issue.user.login"
      }
    },
    "runtime": {
      "image": "github-flows-agent-codex:latest",
      "setupScript": "test -d repo",
      "timeoutSec": 1800,
      "env": {
        "LOG_LEVEL": "info",
        "GH_TOKEN_FILE": "/run/secrets/gh-token"
      },
      "dockerArgs": [
        "--mount",
        "type=bind,src=/home/user/.secrets/codex,dst=/home/user/.codex",
        "--mount",
        "type=bind,src=/home/user/.secrets/gh-token,dst=/run/secrets/gh-token,readonly"
      ]
    }
  }
}

Manual Container Check

Prepare a test workspace:

mkdir -p /home/user/app/github-flows/var/work/auth-test

Run a container with both GitHub and Codex credentials mounted:

docker run --rm -it \
  --name github-flows-auth-test \
  --mount type=bind,src=/home/user/.secrets/codex,dst=/home/user/.codex \
  --mount type=bind,src=/home/user/.secrets/gh-token,dst=/run/secrets/gh-token,readonly \
  --mount type=bind,src=/home/user/app/github-flows/var/work/auth-test,dst=/workspace \
  -e GH_TOKEN_FILE=/run/secrets/gh-token \
  -w /workspace \
  github-flows-agent-codex:latest \
  bash -lc 'export GH_TOKEN="$(tr -d "\r\n" < "$GH_TOKEN_FILE")"; export GITHUB_TOKEN="$GH_TOKEN"; gh api user --jq .login && codex --help'

Security Rules

Do not mount the runtime user home directory:

/home/user

Do not mount SSH configuration:

/home/user/.ssh/

Do not mount the full user configuration directory:

/home/user/.config/

Do not mount the application .env file into the agent workspace:

/home/user/app/github-flows/.env

Do not mount the Docker socket:

/var/run/docker.sock

Do not place credentials inside:

/home/user/app/github-flows/var/work/

The runtime workspace may be visible through logs or debugging tools. It must not contain long-lived credentials.

Result

After this setup:

  • the GitHub token is stored in /home/user/.secrets/gh-token;
  • the GitHub token file is readable only by the runtime user;
  • the Codex auth state is stored in /home/user/.secrets/codex/;
  • GitHub CLI receives GH_TOKEN and GITHUB_TOKEN from the mounted token file;
  • Codex CLI uses the mounted Codex auth state from /home/user/.codex;
  • profile execution can authenticate to GitHub without mounting the host home directory;
  • profile execution can authenticate Codex without storing Codex credentials in the image;
  • credentials are mounted into the container only at runtime;
  • the per-run workspace remains separated from long-lived credentials.