Commit 4b737a8
feat: add the selectable Apple Container runtime backend
Layer 3 of the Apple Container backend stack. Layers 1 and 2 built the
primitives and the no-NIC capability transport but registered nothing; this
makes `--container-runtime apple-container` a real, user-selectable runtime and
wires the complete AWF lifecycle around it. Docker Compose keeps owning
infrastructure (Squid, the API proxy, the CLI proxy); only the agent crosses the
hypervisor boundary.
The guest has zero NICs. `--network none` is not a hardening flag that can be
traded away — omitting `--network` attaches Apple's default vmnet network — so
layer 1 always emits it, layer 2's merge re-asserts it, and the backend checks
it once more immediately before `container create`. Direct IP egress, DNS, DoH,
IPv6, raw sockets, the metadata address, and every host network path are
unreachable by construction rather than by rule.
Runtime selection:
- `apple-container` is a `microvm` execution-model entry in the runtime registry
and a factory in the external backend resolver, so the agent is excluded from
docker-compose.yml while infrastructure is still generated.
- `--apple-container-preview` (required opt-in), `--apple-container-cpus`,
`--apple-container-memory`, `--apple-container-init-image`, and
`--apple-container-cli`, with matching `appleContainer` config, schema, and
spec sections.
- runtime-validation.ts is an exhaustive, fail-closed compatibility matrix, wired
both before and after `applySecurityMode` and re-asserted in the backend's
preflight — the latter is load-bearing, because main-action auto-applies
`dockerHostPathPrefix` after config validation. Docker-in-Docker, ARC split
filesystems, legacy iptables security, host access, enclaves, topology peers,
DoH, `filesystem.allowWrite`, extra volumes, TTY, ssl-bump, the chroot sysroot,
non-default agent images, `--build-local`, and Vertex are each refused with a
message naming the reason. Vertex specifically: its provider port is not in the
transport allowlist, so it is rejected rather than silently losing its endpoint.
Infrastructure bridging:
On macOS the sidecars live inside the Docker Desktop VM, so their 172.30.0.x
addresses are unreachable from the host as well; two hops are required. AWF
publishes exactly the ports backing an allowlisted capability, to 127.0.0.1 only.
That *replaces* rather than supplements the service builders' mappings —
`buildSquidService` emits `3128:3128`, which binds 0.0.0.0 and would leave an
open forward proxy and unauthenticated credential-injecting endpoints on every
interface the runner sits on. Fixed ports are validated free before Compose
starts, so a collision is a named conflict instead of a Docker bind error.
Agent launch:
- The agent image's entrypoint is Docker-specific end to end (iptables-init
handshake, `awfuser` remap, resolv.conf rewrite, chroot into /host). It is
bypassed, not adapted, so no half-applicable assumption runs.
- Mounts are a short explicit list: the workspace and `${RUNNER_TEMP}/gh-aw` at
their own absolute host paths, plus run-scoped `/tmp`, `$HOME`, and the two
`.copilot` directories. Host credential stores are absent because they were
never mounted — there is nothing to shadow, so no credential-hiding overlay
that temporarily moves live host files is needed.
- The workload runs as the host uid:gid on a read-only rootfs.
- Reusing AWF's own environment builders with a loopback "network" yields exactly
the endpoints the transport plan publishes, so the plan's conflict check passes
on identical values rather than being bypassed. A value that cannot survive a
single `--env` argv token fails the run with the variable named instead of
being silently dropped.
- Capability sockets live under /tmp, deliberately not workDir: macOS caps
sun_path at 104 bytes and a realistic `${RUNNER_TEMP}/awf-<ts>/...` path
exceeds it, which would make the relay unbindable.
- Images must be digest-pinned, and `--skip-pull` is honoured by verification:
Apple Container's image store is independent of Docker's, so a Docker pre-pull
does not populate it.
- `container inspect` output carries the guest environment, and the audit
directory is widened to a+rX for artifact upload, so environment blocks are
reduced to variable names before being persisted — matching the "no env vars"
contract the Docker and Cloud Hypervisor collectors already keep. An
unparseable capture is dropped rather than written through.
- Teardown quiesces the guest before removing the transport. `preserve` keeps the
VM for inspection but still unlinks every socket, so a preserved run never
leaves a live path into the credential-injecting sidecar.
Init image, docs, CI:
containers/apple-init/ takes Apple's digest-pinned vminit, moves /sbin/vminitd
to /sbin/vminitd.apple, and installs the layer-2 shim in its place — nothing else
is added, removed, or rewritten. The supported `container` CLI range is recorded
as labels and asserted against the compiled-in host contract by a test that
parses the Dockerfile. The release job is gated on an `APPLE_VMINIT_IMAGE`
repository variable; when unset, no apple-init digest is published and the
runtime simply cannot be selected, rather than falling back to an unknown init.
action.yml gains macOS arm64 installation without weakening Linux behaviour, and
does not claim hosted macOS can run the runtime — hosted macOS reports
kern.hv_support=0 and fails preflight.
The live smoke workflow is `workflow_dispatch`-only against a maintainer-reviewed
SHA in a protected environment. It deliberately has no pull request trigger, not
even a label-gated one: this repository is public, the runner is persistent bare
metal, and a label does not stop commits landing between the label and the
checkout of `refs/pull/N/merge`.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>1 parent 90800af commit 4b737a8
36 files changed
Lines changed: 4434 additions & 48 deletions
File tree
- .github/workflows
- containers/apple-init
- docs
- scripts
- src
- apple-container
- commands
- validators
- types
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
350 | 350 | | |
351 | 351 | | |
352 | 352 | | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
353 | 476 | | |
354 | 477 | | |
355 | 478 | | |
| |||
721 | 844 | | |
722 | 845 | | |
723 | 846 | | |
724 | | - | |
| 847 | + | |
725 | 848 | | |
726 | 849 | | |
727 | 850 | | |
| |||
830 | 953 | | |
831 | 954 | | |
832 | 955 | | |
| 956 | + | |
| 957 | + | |
833 | 958 | | |
834 | 959 | | |
835 | 960 | | |
| |||
843 | 968 | | |
844 | 969 | | |
845 | 970 | | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
846 | 982 | | |
847 | 983 | | |
848 | 984 | | |
| |||
0 commit comments