Summary
The compiler needs a gVisor installation script and a new sandbox.agent.runtime frontmatter field so workflows can opt into running the agent container under gVisor's runsc runtime for additional sandboxing.
AWF already supports container.containerRuntime: "gvisor" in its stdin config (PR github/gh-aw-firewall#6093). AWF translates "gvisor" → "runsc" internally and handles all Docker Compose plumbing, DNS workarounds, and extra_hosts injection. The compiler just needs to:
- Add a
sandbox.agent.runtime frontmatter field
- Emit a gVisor install step before the AWF invocation
- Pass
container.containerRuntime: "gvisor" in the AWF stdin config JSON
Frontmatter syntax
sandbox:
agent:
runtime: gvisor
AWF config mapping
The compiler should add this to the AWF stdin config JSON:
{
"container": {
"containerRuntime": "gvisor"
}
}
AWF handles the translation from "gvisor" to the Docker OCI runtime name "runsc" — the compiler should NOT emit --container-runtime as a CLI flag.
gVisor installation step
The compiler must emit a pre-agent installation step that runs before AWF. This step requires sudo — see the root access section below.
Working reference implementation
This is the proven install script from the smoke-gvisor workflow (all CI runs passing):
set -euo pipefail
echo "::group::Install gVisor (runsc)"
ARCH=$(uname -m)
URL="https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH}"
echo "Downloading runsc for ${ARCH}..."
curl -fsSL "${URL}/runsc" -o /tmp/runsc
curl -fsSL "${URL}/containerd-shim-runsc-v1" -o /tmp/containerd-shim-runsc-v1
sudo install -m 755 /tmp/runsc /usr/local/bin/runsc
sudo install -m 755 /tmp/containerd-shim-runsc-v1 /usr/local/bin/containerd-shim-runsc-v1
runsc --version
echo "::endgroup::"
echo "::group::Register runsc as Docker runtime"
sudo runsc install
# IMPORTANT: Must use `restart` (not `reload`).
# Docker's SIGHUP reload does NOT call setHostGatewayIP(), so
# --add-host host.docker.internal:host-gateway breaks for any
# container started after a reload-only config change.
sudo systemctl restart docker
echo "Docker runtimes:"
docker info --format '{{.Runtimes}}' || docker info | grep -i runtime
echo "::endgroup::"
echo "::group::Verify gVisor works"
docker run --rm --runtime=runsc hello-world
echo "✅ gVisor runtime verified"
echo "::endgroup::"
Critical implementation notes
| Item |
Detail |
| Architecture |
Use uname -m directly (x86_64, aarch64). Do NOT remap to amd64/arm64 — gVisor's download URLs use raw architecture names. |
| Docker restart |
Must use systemctl restart docker, NOT reload. Docker's SIGHUP reload does not call initNetworkController() / setHostGatewayIP(), causing --add-host host.docker.internal:host-gateway to fail with ParseAddr("invalid IP"). |
| Step ordering |
The install step must run BEFORE the AWF invocation step. AWF's --container-runtime gvisor sets runtime: runsc on the agent container in docker-compose.yml — Docker will fail to start the container if runsc isn't registered. |
| Containerd shim |
Both runsc and containerd-shim-runsc-v1 must be downloaded. The shim is required for Docker's containerd integration. |
⚠️ Root access required — compile-time validation
gVisor installation fundamentally requires root access. The install script uses sudo for:
sudo install -m 755 /tmp/runsc /usr/local/bin/runsc — installs binary to system path
sudo runsc install — modifies /etc/docker/daemon.json to register the runtime
sudo systemctl restart docker — restarts the Docker daemon (system-level systemd service)
There is no rootless alternative. Docker rootless mode doesn't help because daemon.json is still root-owned and systemd --user services cannot manage the system Docker daemon.
Compile-time incompatibilities
The compiler should fail at compile time if sandbox.agent.runtime: gvisor is combined with any of these:
| Incompatible option |
Reason |
runner.topology: arc-dind |
ARC DinD runners use a sidecar Docker daemon with a split filesystem. gVisor requires runsc install + systemctl restart on the Docker daemon host, but the runner has no access to the DinD sidecar's daemon config or systemd. gVisor is fundamentally incompatible with ARC DinD. |
sandbox.agent.sudo: false |
The gVisor install step itself requires sudo. While AWF can run rootless after installation, the pre-agent install step cannot be made rootless. The compiler should either reject this combination or document that sudo is required for the install step regardless of the sudo setting. |
Example compile-time error messages
error: sandbox.agent.runtime: gvisor is incompatible with runner.topology: arc-dind.
gVisor requires registering the runsc runtime with Docker via systemctl, which
is not possible on ARC DinD runners where the Docker daemon runs in a sidecar.
error: sandbox.agent.runtime: gvisor requires root access for installation.
Cannot combine with sandbox.agent.sudo: false.
DNS compatibility (handled by AWF)
gVisor's userspace netstack has a known DNS incompatibility (google/gvisor#7469) — Docker's embedded DNS at 127.0.0.11 is unreachable inside gVisor's isolated sandbox loopback. AWF handles this automatically when containerRuntime is set:
- Injects
extra_hosts entries for compose-internal services (squid-proxy, api-proxy)
- Patches the chroot
/etc/hosts file with topology peer IPs
- No compiler action needed for DNS — AWF manages it end-to-end
Related
Summary
The compiler needs a gVisor installation script and a new
sandbox.agent.runtimefrontmatter field so workflows can opt into running the agent container under gVisor'srunscruntime for additional sandboxing.AWF already supports
container.containerRuntime: "gvisor"in its stdin config (PR github/gh-aw-firewall#6093). AWF translates"gvisor"→"runsc"internally and handles all Docker Compose plumbing, DNS workarounds, andextra_hostsinjection. The compiler just needs to:sandbox.agent.runtimefrontmatter fieldcontainer.containerRuntime: "gvisor"in the AWF stdin config JSONFrontmatter syntax
AWF config mapping
The compiler should add this to the AWF stdin config JSON:
{ "container": { "containerRuntime": "gvisor" } }AWF handles the translation from
"gvisor"to the Docker OCI runtime name"runsc"— the compiler should NOT emit--container-runtimeas a CLI flag.gVisor installation step
The compiler must emit a pre-agent installation step that runs before AWF. This step requires
sudo— see the root access section below.Working reference implementation
This is the proven install script from the smoke-gvisor workflow (all CI runs passing):
Critical implementation notes
uname -mdirectly (x86_64,aarch64). Do NOT remap toamd64/arm64— gVisor's download URLs use raw architecture names.systemctl restart docker, NOTreload. Docker's SIGHUP reload does not callinitNetworkController()/setHostGatewayIP(), causing--add-host host.docker.internal:host-gatewayto fail withParseAddr("invalid IP").--container-runtime gvisorsetsruntime: runscon the agent container in docker-compose.yml — Docker will fail to start the container if runsc isn't registered.runscandcontainerd-shim-runsc-v1must be downloaded. The shim is required for Docker's containerd integration.gVisor installation fundamentally requires root access. The install script uses
sudofor:sudo install -m 755 /tmp/runsc /usr/local/bin/runsc— installs binary to system pathsudo runsc install— modifies/etc/docker/daemon.jsonto register the runtimesudo systemctl restart docker— restarts the Docker daemon (system-level systemd service)There is no rootless alternative. Docker rootless mode doesn't help because
daemon.jsonis still root-owned andsystemd --userservices cannot manage the system Docker daemon.Compile-time incompatibilities
The compiler should fail at compile time if
sandbox.agent.runtime: gvisoris combined with any of these:runner.topology: arc-dindrunsc install+systemctl restarton the Docker daemon host, but the runner has no access to the DinD sidecar's daemon config or systemd. gVisor is fundamentally incompatible with ARC DinD.sandbox.agent.sudo: falsesudosetting.Example compile-time error messages
DNS compatibility (handled by AWF)
gVisor's userspace netstack has a known DNS incompatibility (google/gvisor#7469) — Docker's embedded DNS at 127.0.0.11 is unreachable inside gVisor's isolated sandbox loopback. AWF handles this automatically when
containerRuntimeis set:extra_hostsentries for compose-internal services (squid-proxy, api-proxy)/etc/hostsfile with topology peer IPsRelated
specs/security-architecture-spec.md— references "Sandbox Runtime (SRT)" as experimental