Hosted deployment: spike: prove the hardened Worker container inside a Sandbox VM
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 12/100
- Issue type
- Documentation
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- docker, linux, typescript
- Domain
- devops, infrastructure, security
Research direction
Start by reading the flags in compose.dynamic.yml and the hardening requirements in parent issue #316, then set up the throw-away Vercel project in fra1 and build the golden snapshot. Each probe T01 to T14 is run by hand and its measured result goes into the write-up in docs/spike/ and the ADR in docs/decisions/. Done means every test case in the table has a recorded result and the VM size and container limit recommendation is written down.
Written by the indexing model from the issue text.
Description
Part of ##316.
Problem
The hosted deployment runs our hardened Worker container inside a Vercel Sandbox VM that hosts Docker. Nothing about nested Docker, the VM kernel, memory use or startup time is known yet. Vercel's firewall and isolation are not part of our security boundary: our container must carry all hardening, and the Dynamic-Worker must fail closed where it cannot. We need facts before building the Sandbox-Launcher.
Design
Manual, time-boxed (3 days). The result is a write-up in docs/spike/ and an ADR in docs/decisions/, with the measured numbers in the PR. No production code. Use a throw-away Vercel project in region fra1.
- Build a golden snapshot by hand: Docker installed with the package manager of the default Ubuntu image, the Dynamic image pre-pulled by digest from Vercel Container Registry,
dockerdstopped cleanly, snapshot. Then clone it once per probe (persistent:false). - Run the real container flags of
compose.dynamic.yml(user, caps,no-new-privileges, read-only root, tmpfs, memory, pids) withdocker run, and the real code and checks. Vercel's network policy stays at its default; no firewall rule is used or relied on. - VM sizes. Per the Vercel Sandbox docs each vCPU includes 2 GB of memory (1 vCPU, or an even number from 2 to 32), so the smallest size is 1 vCPU / 2 GB. T10 confirms this on a real VM. Starting points: Dynamic-Worker VM 1 vCPU / 2 GB with the Worker container limited to about 1.5 GB (
--memory 1.5g --memory-swap 1.5g, leaving room fordockerdand the OS); Diff-Worker VM the smallest size, 1 vCPU / 2 GB. The2gmemory cap of the self-hosted Dynamic compose service was only a cap and was never measured; T10 produces the first real peak numbers. - VM size and container memory limit are configuration per Worker kind in the later issues, not constants. If Dynamic is killed by the OOM killer at 1.5 GB, the recommendation steps up one size (2 vCPU / 4 GB) and the container limit is raised accordingly.
- Decision rule: any failure of T03 to T07 keeps
opencodeoff (Diff may still proceed). T01 or T02 failing ends the approach and triggers the documented fallback (boot the Worker image directly as the sandbox image and re-create the compose hardening in its entry point; its cost is a new hardening module and its privileged tests). - Do not change the self-hosted compose limits in this issue. Record a recommendation and open a follow-up if the measured numbers justify one.
Scope
The probes below, the write-up, the ADR. Findings that need code become new issues.
Out of scope
Any production code, the golden snapshot pipeline (##330), the Sandbox-Launcher (##329), egress restriction (#82).
Related
#82 (egress gate; T11 only records what the container can reach), #202 (Dynamic engine packaging and release gates).
Test cases
| ID | kind | level | case | expected |
|---|---|---|---|---|
| T01 | probe | manual | install Docker in the default image, start dockerd, run docker info in fra1 |
daemon runs; storage driver, cgroup version, memory controller, seccomp and LSM state recorded |
| T02 | probe | manual | create a VM from the golden snapshot with persistent:false, start dockerd, run the image |
images are present after restore; the container starts without a pull |
| T03 | security | manual | run the container with the exact flags of compose.dynamic.yml; inspect it |
HostConfig matches; inside: effective and bounding capabilities equal the list, no-new-privileges set, root filesystem read-only, three tmpfs mounts with noexec,nosuid,nodev and their sizes, memory and pids limits visible in the cgroup |
| T04 | security | manual | container start: install the engine uid's nft rules, drop NET_ADMIN and SETPCAP |
rules installed in the container's network namespace; a probe as uid 10101 reaches only the two loopback ports; nft fails afterwards for every process |
| T05 | security | manual | run the Dynamic startup self-check in the container | passes with no failing reason |
| T06 | security | manual | run the repository's privileged test suite and the Dynamic e2e journey inside the container (fakes only) | both pass |
| T07 | security | manual | from root and from uid 10101 inside the container: AF_VSOCK connect to the host and agent, gateway ports, /proc/net/unix, access to the VM's Docker socket |
the engine uid reaches nothing; anything root reaches is listed; a positive finding creates a follow-up for a seccomp rule |
| T08 | edge | manual | job isolation: write a marker in job A (container layer, tmpfs, /var/lib/docker), then run job B from a fresh clone of the snapshot |
marker absent; a scan of the golden snapshot finds no job data and no secret |
| T09 | measure | manual | timeline: create-from-snapshot, dockerd ready, container ready, self-check done, first heartbeat; cold and warm snapshot |
numbers recorded per segment and compared with the target of 45 s from claim to first Worker heartbeat |
| T10 | measure | manual | worst-case Dynamic job and worst-case Diff job in the container with a 1.5 GB limit on a 1 vCPU / 2 GB VM; confirm the VM's memory (free) and that no smaller size exists |
peak memory per kind (container cgroup and VM), OOM behavior (container killed, VM alive), recommended VM size and container limit per kind; if Dynamic is OOM-killed, the same run on 2 vCPU / 4 GB with a recommended larger limit |
| T11 | probe | manual | egress from the container (bridge NAT) to the App, the Git host and the model host; DNS; IPv6; MTU | works; failures listed |
| T12 | probe | manual | snapshot lifecycle and registry: expiry setting, restore in the same region, behavior of an uncached snapshot; push the Worker image to Vercel Container Registry and pull it by digest in the builder VM with the project's OIDC login | documented limits and durations; the pull works without a long-lived secret |
| T13 | probe | manual | teardown: docker run ...; poweroff, stop(), and a lost SDK call with only the VM timeout |
which option ends the VM; worst-case idle time |
| T14 | probe | manual | a Hono default export deployed as Functions with a cron route and waitUntil use |
works, or the exact workaround |
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 1
- Avg merge
- 1h 15m
- Merged PRs (30d)
- 217
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ExpidetGames/code-reviewer
-
area: app type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ExpidetGames/code-reviewer#308 ·
Maintainers usually reply within 1 day
-
type: docs
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ExpidetGames/code-reviewer#94 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 25/100
ExpidetGames/code-reviewer#401 ·
Maintainers usually reply within 1 day
-
area: app type: chore
Difficulty 3/5 1-2 days Newbie friendliness 45/100
ExpidetGames/code-reviewer#393 ·
Maintainers usually reply within 1 day
-
area: runner type: bug
Difficulty 4/5 3-5 days Newbie friendliness 42/100
ExpidetGames/code-reviewer#390 ·
Maintainers usually reply within 1 day
All issues in ExpidetGames/code-reviewer
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
anomalyco/opencode#56380 · 1 comment ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
BUG | `MCP 服务器` | 全局层行的停用/启用与删除报 404 server row not found,编辑保存会在 profile 层复制出重复行Possibly taken @w6242652 claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Chocobozzz/PeerTube#7832 ·
Maintainers usually reply within 3 days
-
Pay to use?Open
Difficulty 1/5 Under an hour Newbie friendliness 66/100
darkreader/darkreader#16108 · 1 comment ·
Maintainers usually reply within 2 days