Skip to content

Add Dev Container Feature for Dev Proxy - #2009

Open
waldekmastykarz wants to merge 4 commits into
dotnet:mainfrom
waldekmastykarz:devcontainer-feature
Open

waldekmastykarz wants to merge 4 commits into
dotnet:mainfrom
waldekmastykarz:devcontainer-feature

Conversation

@waldekmastykarz

@waldekmastykarz waldekmastykarz commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1334

Adds a Dev Container Feature that installs Dev Proxy and trusts a per-container root certificate, following the spec in #1334 (comment).

Usage

"features": {
  "ghcr.io/dotnet/dev-proxy/dev-proxy:1": {}
}

What's included

  • features/src/dev-proxy: the Feature (version 1.0.0, versioned separately from Dev Proxy).
    • Options: version (latest, beta, 2.2.0 or v2.2.0) and trustCertificate (default true).
    • install.sh runs at build time as root. It installs dependencies (curl, unzip, ca-certificates, openssl, ICU) and resolves the version. It downloads the x64/arm64 Linux release into /opt/devproxy, symlinks /usr/local/bin/devproxy (plus devproxy-beta for betas) and creates ~/.config/dev-proxy for the remote user. It also installs a root-owned cert-trust helper that the remote user can run with sudo and no password, then verifies devproxy --version. It's idempotent and non-interactive, and fails clearly on Alpine/musl and non-apt distros.
    • No certificate is generated at build time, so no CA private key ends up in image layers or prebuilds. In postCreateCommand, the remote user runs devproxy cert ensure, then the helper validates the certificate (CA:TRUE) and adds it to /usr/local/share/ca-certificates + update-ca-certificates.
    • containerEnv: NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE and SSL_CERT_FILE, all pointing to the system CA bundle.
    • The Feature doesn't auto-start Dev Proxy, set HTTP(S)_PROXY or support Java.
  • features/test/dev-proxy: tests for devcontainer features test.
    • Autogenerated tests on debian, ubuntu and devcontainers/base:ubuntu. The duplicate test installs the Feature twice.
    • Scenarios: non-root user without sudo, specific versions (with and without v), beta, trustCertificate: false (verifies no cert is generated or trusted), and end-to-end trust through Dev Proxy for curl, Node.js, Python urllib and requests, and .NET.
    • Every test checks that no certificate exists outside the user's profile.
  • Workflows:
    • devcontainer-feature-test.yml: runs on PRs/pushes touching features/**, on x64 and arm64 runners, plus metadata validation.
    • devcontainer-feature-release.yml: publishes to GHCR with devcontainers/action on pushes to main that touch features/src/**, or manually.
  • Docs: the Feature README, a mention in the root README and the skill's installation reference, and a note in copilot-instructions.

Design decisions and notes for reviewers

  • installToolkit option dropped. Feature customizations are static metadata and can't depend on option values. The Feature always adds garrytrinder.dev-proxy-toolkit, and users can opt out with "-garrytrinder.dev-proxy-toolkit" in their devcontainer.json (documented).
  • Python 3.13+ and Dev Proxy v3: Python 3.13 enables VERIFY_X509_STRICT, which rejects v3's leaf certificates because they lack an Authority Key Identifier. v4 (the Kestrel engine on main) already adds it. The runtimes scenario uses beta for this reason, and the limitation is documented in the Feature README.
  • Beta resolution picks the newest beta tag whose Linux asset exists. v4.0.0-beta.13 currently has a tag but no assets.
  • v4 creates the root certificate on any command, even --version. The install-time check runs in an isolated temporary HOME so no certificate is left in the image.

After merging

  • Make the dev-proxy GHCR package (ghcr.io/dotnet/dev-proxy/dev-proxy) public after the first publish.
  • Optionally add the Feature to the containers.dev index.

Open questions from the spec

  • Documenting a sidecar setup (Dev Proxy in a separate container) isn't covered here.
  • The API port (8897) isn't forwarded or configured by the Feature.

Testing

Ran devcontainer features test (CLI 0.89.0) locally with Docker on arm64. All autogenerated tests (debian, ubuntu, devcontainers/base:ubuntu, including the duplicate install) and all scenarios pass.

Adds a Dev Container Feature (features/src/devproxy), published as
ghcr.io/dotnet/dev-proxy/devproxy, that installs Dev Proxy and, after
the container is created, generates a per-container root certificate and
trusts it system-wide, for Node.js and Python. Includes tests for the
devcontainer CLI and workflows to test and publish the Feature.

Closes dotnet#1334

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@waldekmastykarz
waldekmastykarz requested a review from a team as a code owner October 27, 2026 10:14
Copilot AI balanced review requested due to automatic review settings October 27, 2026 10:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

CA private-key isolation and permissions need correction, and certificate-leak assertions can miss root-owned files.

3 open issues
What changed in this PR

Adds a Dev Container Feature for Dev Proxy, addressing #1334 with installation and certificate-trust setup for Dev Containers and GitHub Codespaces.

Changes:

  • Adds configurable installation and post-create certificate setup for Debian/Ubuntu containers on x64 and arm64.
  • Adds installation, version-selection, restricted-user, and runtime-trust tests.
  • Adds validation and publishing workflows, plus usage documentation.
File Description
skills/​dev-proxy/​references/​installation.md Documents Feature-based installation.
README.md Adds a Dev Container usage example.
features/​test/​devproxy/​test.sh Tests default installation and trust.
features/​test/​devproxy/​specific_version.sh Tests a pinned version.
features/​test/​devproxy/​specific_version_with_v.sh Tests a version with the v prefix.
features/​test/​devproxy/​scenarios.json Defines integration-test scenarios.
features/​test/​devproxy/​runtimes.sh Tests trust across common runtimes.
features/​test/​devproxy/​non_root_user/​Dockerfile Provides a restricted-user test image.
features/​test/​devproxy/​non_root_user.sh Tests restricted-user setup and permissions.
features/​test/​devproxy/​no_trust_certificate/​Dockerfile Provides an image for disabled-trust testing.
features/​test/​devproxy/​no_trust_certificate.sh Tests installation without certificate setup.
features/​test/​devproxy/​duplicate.sh Tests repeated installation.
features/​test/​devproxy/​common.sh Provides shared proxy and certificate assertions.
features/​test/​devproxy/​beta.sh Tests beta installation and trust.
features/​src/​devproxy/​scripts/​trust-cert.sh Validates and installs the public CA certificate.
features/​src/​devproxy/​scripts/​post-create.sh Generates and trusts the user's certificate.
features/​src/​devproxy/​README.md Documents options, behavior, and limitations.
features/​src/​devproxy/​install.sh Installs Dev Proxy, dependencies, and helpers.
features/​src/​devproxy/​devcontainer-feature.json Defines options, environment, and lifecycle setup.
.github/​workflows/​devcontainer-feature-test.yml Runs architecture-matrix tests and metadata validation.
.github/​workflows/​devcontainer-feature-release.yml Publishes the Feature to GHCR.
.github/​copilot-instructions.md Adds Feature development and release guidance.

Review effort: Balanced

Comment thread features/src/devproxy/install.sh Outdated
Comment thread features/src/devproxy/scripts/post-create.sh
Comment thread features/test/devproxy/common.sh Outdated
waldekmastykarz and others added 2 commits October 27, 2026 11:44
- Pin DEV_PROXY_CERT_PATH to the throwaway home during the build-time
  version check so an inherited absolute path can't leave a CA in the image
- Generate the root certificate with umask 077 and restrict it to 0600
- Scan for stray certificates as root when possible and fail on
  incomplete scans

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The privileged certificate-trust lifecycle and automatic GHCR publishing warrant final human validation before approval.

No open issues 🎉

3 resolved since last review

Review effort: Balanced

Publishes the Feature as ghcr.io/dotnet/dev-proxy/dev-proxy so the name
is spelled consistently with the repository.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a Development Container Feature for Dev Proxy

2 participants