e0ipso / e0ipso/ddev-assistant-codex

Add opt-in Codex desktop app access to the DDEV web container over SSH

Open
#3 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Shell
Stars
0
Forks
1
PR merge metrics
No merged PRs in 30d

Description

- Suggested type/label: Enhancement

## Problem

`ddev-assistant-codex` currently installs Codex CLI in the DDEV web container,
puts `codex` on `PATH`, and mirrors host Codex configuration into a writable
container runtime directory. This works well when Codex is started from a
terminal with `ddev codex` or `ddev exec codex`.

The ChatGPT desktop app (Codex) can now work with remote projects over SSH. The
desktop app discovers a concrete host alias from `~/.ssh/config`, connects to
that host, and starts `codex app-server` using the remote login shell. This is a
good match for DDEV: users could keep the Codex GUI on macOS while all agent
commands and development dependencies run inside the project's DDEV container.

However, `ddev ssh` is a Docker-exec convenience rather than an SSH protocol
endpoint, so the desktop app cannot connect to an ordinary DDEV web container.

OpenAI documentation:
https://learn.chatgpt.com/docs/remote-connections#connect-to-an-ssh-host

Related issue in One-line Installer using this: https://git.drupalcode.org/project/one_line_installer/-/work_items/3601364

## Proposed solution

Add an explicitly enabled **Codex desktop app remote-access mode** to this
add-on. Keep the current terminal-only installation as the default, so installing
`ddev-assistant-codex` does not unexpectedly expose another service or modify
host SSH configuration.

Suggested commands:

```bash
ddev codex-app:status
ddev codex-app:ssh-config --dry-run
ddev codex-app:enable
ddev codex-app:disable
```

`ddev codex-app:enable` would:

1. Install and start OpenSSH server in the DDEV web container.
2. Publish container port 22 to a Docker-assigned port bound only to
`127.0.0.1` on the host.
3. Generate a unique project-specific Ed25519 client key.
4. Generate and persist project-specific SSH host keys.
5. Authorize only the project key for the ordinary DDEV web user.
6. Generate a concrete host alias such as `codex-my-project` in a dedicated
included SSH config fragment.
7. Verify that the alias can run both `codex --version` and
`codex app-server --help` without allocating a TTY.

An example generated SSH entry would be:

```sshconfig
Host codex-my-project
HostName 127.0.0.1
Port
User
IdentityFile /.ddev/.codex-app/id_ed25519
IdentitiesOnly yes
RequestTTY no
StrictHostKeyChecking yes
UserKnownHostsFile /.ddev/.codex-app/known_hosts
```

The generated fragment should be refreshed after `ddev start` because Docker
may allocate a different host port. Persistent server host keys should allow
strict host verification to remain enabled across restarts and rebuilds.

## Security requirements

This feature is intended to improve isolation compared with running Codex CLI
directly on the host. It should therefore have conservative defaults:

- Opt-in only; no SSH daemon or published port after a normal add-on install.
- Bind the published SSH port to `127.0.0.1`, never all host interfaces.
- Disable password authentication and root login.
- Disable agent, TCP, Unix-socket, and X11 forwarding unless a required Codex
capability is identified.
- Do not require `ddev auth ssh` and do not expose the user's general-purpose
SSH agent to the web container.
- Use a project-specific key which cannot authenticate to unrelated hosts or
other DDEV projects.
- Use strict host-key verification; do not use
`StrictHostKeyChecking=no`/`UserKnownHostsFile=/dev/null`.
- Do not force a TTY because the desktop app starts the machine-oriented Codex
app-server protocol.
- Keep Codex approvals enabled. Enabling desktop access must not imply
`--dangerously-bypass-approvals-and-sandbox`.
- Do not mount the Docker socket into the web container.
- Ensure all generated private state is mode-restricted and gitignored.

## Codex authentication and configuration

The current add-on mirrors the host's complete `~/.codex` directory into the
container at startup. For this mode, it would be useful to support a
project-isolated Codex home so remote authentication and configuration persist
without copying unrelated host histories, memories, logs, and project state.

Suggested modes:

- `isolated` (recommended default for desktop access): persistent,
project-specific `CODEX_HOME`; the user runs `ddev codex login` themselves.
- `host-seed` (existing convenience behaviour): explicitly reuse the host seed.

The add-on must never collect a ChatGPT password or automate browser
authentication. Authentication remains a user-owned step.

## Host configuration UX

Writing `~/.ssh/config` is outside the DDEV project, so it should be transparent
and reversible:

- `ddev codex-app:ssh-config --dry-run` prints the exact entry and files.
- `ddev codex-app:enable` asks before adding the include/fragment when
interactive, or supports a clear non-interactive flag for callers such as an
installer.
- Only one generated fragment is owned by this add-on.
- `ddev codex-app:disable` removes the listener and owned fragment without
deleting user project files or unrelated SSH configuration.

## Acceptance criteria

- A normal add-on installation behaves exactly as it does today.
- Enabling the feature creates a loopback-only SSH endpoint and concrete alias.
- The ChatGPT desktop app discovers the alias and opens `/var/www/html` as a
remote project.
- Remote Codex reads and writes the bind-mounted project and runs commands in
the DDEV web container.
- `codex app-server` starts successfully through a non-interactive SSH command.
- The connection survives `ddev restart` and a web-image rebuild.
- Two running DDEV projects have different ports, client keys, host keys, SSH
aliases, and isolated Codex homes.
- Stopping DDEV closes the project's listener.
- Disabling/uninstalling removes all add-on-owned host configuration and the SSH
service without touching unrelated user configuration.
- Automated Bats coverage tests enable, status, restart/rebuild, project
isolation, disable, and uninstall behaviour.

## Possible follow-up integration

The Drupal AI Best Practices one-line installer already offers Codex as an
in-container coding agent. Once this feature is available in a tagged add-on
release, the installer can offer it as an advanced opt-in choice and persist it
in a saved local installer configuration.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by inspecting the existing add-on installation and the current ddev codex entry points, then trace how container startup and configuration persistence work. Use the proposed codex-app commands and acceptance criteria to define the SSH lifecycle, project isolation, restart/rebuild behavior, and Bats coverage; done means the opt-in endpoint works securely without changing the default installation.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, shell
Domain
cli, devops, infrastructure, security, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.